diff --git a/build.sbt b/build.sbt index 5668cdf..669557d 100644 --- a/build.sbt +++ b/build.sbt @@ -10,6 +10,5 @@ libraryDependencies ++= Seq( libraryDependencies ++= Seq( "net.debasishg" %% "redisclient" % "3.10" ) -libraryDependencies += "com.bot4s" %% "telegram-core" % "4.2.0-RC1" -mainClass := Some("Runner") +mainClass := Some("org.congressodeiradicali.karlmarx.Runner") diff --git a/src/main/scala/org/congressodeiradicali/karlmarx/Bot.scala b/src/main/scala/org/congressodeiradicali/karlmarx/Bot.scala index d274ed2..119793b 100644 --- a/src/main/scala/org/congressodeiradicali/karlmarx/Bot.scala +++ b/src/main/scala/org/congressodeiradicali/karlmarx/Bot.scala @@ -22,6 +22,7 @@ import com.bot4s.telegram.api.declarative.{Command, Commands} import com.bot4s.telegram.clients.ScalajHttpClient import com.bot4s.telegram.future.{Polling, TelegramBot} import com.bot4s.telegram.models.{Message, User} +import org.congressodeiradicali.karlmarx.coreplugins.{BanPlugin, EchoPlugin, PluginManagerPlugin} import slogging.{LogLevel, LoggerConfig, PrintLoggerFactory} import scala.concurrent.Future @@ -42,6 +43,12 @@ class Bot(val token: String) extends TelegramBot var plugins: List[Plugin] = List[Plugin](new PluginManagerPlugin(localizer, this)) + def getPluginManager() : PluginManagerPlugin = plugins.head.asInstanceOf[PluginManagerPlugin] + + // load core plugins + getPluginManager().managePlugin(new BanPlugin(localizer, this)) + getPluginManager().managePlugin(new EchoPlugin(localizer, this)) + def runAgainst(handlerPair: Plugin#HandlerPair, botUser: Option[User], cmd: Command): Boolean = { handlerPair._1 .to(botUser.flatMap(_.username)) // Apply filter to bot username diff --git a/src/main/scala/org/congressodeiradicali/karlmarx/EchoPlugin.scala b/src/main/scala/org/congressodeiradicali/karlmarx/EchoPlugin.scala deleted file mode 100644 index 0bb1445..0000000 --- a/src/main/scala/org/congressodeiradicali/karlmarx/EchoPlugin.scala +++ /dev/null @@ -1,12 +0,0 @@ -package org.congressodeiradicali.karlmarx - -import com.bot4s.telegram.api.declarative.{CommandFilterMagnet, CommandImplicits} -import com.bot4s.telegram.models.Message - -import scala.concurrent.{ExecutionContext, Future, blocking} - -class EchoPlugin(localizer: Localizer, bot: Bot) extends Plugin with CommandImplicits { - override var handlers: Map[CommandFilterMagnet, Handler] = Map { - stringToCommandFilter("echo") -> { msg => Future { msg.text }(ExecutionContext.global) } - } -} diff --git a/src/main/scala/org/congressodeiradicali/karlmarx/Plugin.scala b/src/main/scala/org/congressodeiradicali/karlmarx/Plugin.scala index 5175b6a..1c3d490 100644 --- a/src/main/scala/org/congressodeiradicali/karlmarx/Plugin.scala +++ b/src/main/scala/org/congressodeiradicali/karlmarx/Plugin.scala @@ -9,5 +9,16 @@ trait Plugin { type Handler = Message => Future[Option[String]] type HandlerPair = (CommandFilterMagnet, Handler) + val name: String + val description: String + val license: String + val author: String + + /** + * A string that identifies the plugin + * used for loading and unloading it with bot commands + */ + val identifier: String + var handlers: Map[CommandFilterMagnet, Handler] } \ No newline at end of file diff --git a/src/main/scala/org/congressodeiradicali/karlmarx/PluginManagerPlugin.scala b/src/main/scala/org/congressodeiradicali/karlmarx/PluginManagerPlugin.scala deleted file mode 100644 index 6c822f8..0000000 --- a/src/main/scala/org/congressodeiradicali/karlmarx/PluginManagerPlugin.scala +++ /dev/null @@ -1,20 +0,0 @@ -package org.congressodeiradicali.karlmarx - -import com.bot4s.telegram.api.declarative.{CommandFilterMagnet, CommandImplicits} - -import scala.concurrent.{ExecutionContext, Future} - -class PluginManagerPlugin(localizer: Localizer, bot: Bot) extends Plugin with CommandImplicits { - override var handlers: Map[CommandFilterMagnet, Handler] = Map { - stringToCommandFilter("enable") -> { msg => - val response = msg.text.map { - case "echo" => Some(new EchoPlugin(localizer, bot)) - case "ban" => Some(new BanPlugin(localizer, bot)) - case _ => None - }.map { - case Some(plugin) => bot.plugins :+= plugin; "Added." - } - Future { response }(ExecutionContext.global) - } - } -} diff --git a/src/main/scala/org/congressodeiradicali/karlmarx/BanPlugin.scala b/src/main/scala/org/congressodeiradicali/karlmarx/coreplugins/BanPlugin.scala similarity index 76% rename from src/main/scala/org/congressodeiradicali/karlmarx/BanPlugin.scala rename to src/main/scala/org/congressodeiradicali/karlmarx/coreplugins/BanPlugin.scala index bd76e64..02f293d 100644 --- a/src/main/scala/org/congressodeiradicali/karlmarx/BanPlugin.scala +++ b/src/main/scala/org/congressodeiradicali/karlmarx/coreplugins/BanPlugin.scala @@ -1,10 +1,17 @@ -package org.congressodeiradicali.karlmarx +package org.congressodeiradicali.karlmarx.coreplugins + import com.bot4s.telegram.api.declarative.{CommandFilterMagnet, CommandImplicits} +import org.congressodeiradicali.karlmarx._ import scala.concurrent.{ExecutionContext, Future} import scala.util.{Failure, Success} -class BanPlugin(localizer: Localizer, bot: Bot) extends Plugin with CommandImplicits { +class BanPlugin(localizer: Localizer, bot: Bot) extends CorePlugin with CommandImplicits { + + override val name: String = "Ban Plugin" + override val description: String = "Ban users and unban them" + + override val identifier: String = "ban" override var handlers: Map[CommandFilterMagnet, Handler] = Map { stringToCommandFilter("ban") -> { msg => diff --git a/src/main/scala/org/congressodeiradicali/karlmarx/coreplugins/CorePlugin.scala b/src/main/scala/org/congressodeiradicali/karlmarx/coreplugins/CorePlugin.scala new file mode 100644 index 0000000..4aa2ae1 --- /dev/null +++ b/src/main/scala/org/congressodeiradicali/karlmarx/coreplugins/CorePlugin.scala @@ -0,0 +1,10 @@ +package org.congressodeiradicali.karlmarx.coreplugins + +import org.congressodeiradicali.karlmarx.Plugin + +trait CorePlugin extends Plugin { + + override val license = "GNU AGPL" + override val author = "Congresso dei Radicali" + +} diff --git a/src/main/scala/org/congressodeiradicali/karlmarx/coreplugins/EchoPlugin.scala b/src/main/scala/org/congressodeiradicali/karlmarx/coreplugins/EchoPlugin.scala new file mode 100644 index 0000000..cb3b9de --- /dev/null +++ b/src/main/scala/org/congressodeiradicali/karlmarx/coreplugins/EchoPlugin.scala @@ -0,0 +1,18 @@ +package org.congressodeiradicali.karlmarx.coreplugins + +import com.bot4s.telegram.api.declarative.{CommandFilterMagnet, CommandImplicits} +import org.congressodeiradicali.karlmarx.{Bot, Localizer} + +import scala.concurrent.{ExecutionContext, Future} + +class EchoPlugin(localizer: Localizer, bot: Bot) extends CorePlugin with CommandImplicits { + + override val name: String = "Echo Plugin" + override val description: String = "An echoing plugin" + + override val identifier: String = "echo" + + override var handlers: Map[CommandFilterMagnet, Handler] = Map { + stringToCommandFilter("echo") -> { msg => Future { msg.text }(ExecutionContext.global) } + } +} diff --git a/src/main/scala/org/congressodeiradicali/karlmarx/coreplugins/PluginManagerPlugin.scala b/src/main/scala/org/congressodeiradicali/karlmarx/coreplugins/PluginManagerPlugin.scala new file mode 100644 index 0000000..928b541 --- /dev/null +++ b/src/main/scala/org/congressodeiradicali/karlmarx/coreplugins/PluginManagerPlugin.scala @@ -0,0 +1,84 @@ +package org.congressodeiradicali.karlmarx.coreplugins + +import com.bot4s.telegram.api.declarative.{CommandFilterMagnet, CommandImplicits} +import com.bot4s.telegram.models.Message +import org.congressodeiradicali.karlmarx.{Bot, Localizer, Plugin} + +import scala.concurrent.{ExecutionContext, Future} + +class PluginManagerPlugin(localizer: Localizer, bot: Bot) extends CorePlugin with CommandImplicits { + + override val name = "Plugin Manager" + override val description = "Manages other plugins" + + override val identifier = "pluginmanager" + + var managedPlugins: Map[String, Plugin] = Map() + var pluginStatus: Map[String, Boolean] = Map() + + def managePlugin(plugin: Plugin) = { + managedPlugins += (plugin.identifier -> plugin) + pluginStatus += (plugin.identifier -> false) + } + + def enableByIdentifier(id: String) : Boolean = managedPlugins.get(id).fold { + false + } { plugin => + bot.plugins :+= plugin + pluginStatus = pluginStatus.updated(plugin.identifier, true) + true + } + + def disableByIdentifier(id: String) : Boolean = managedPlugins.get(id).fold { /*checks if the plugin is managed*/ + false + } { plugin => + bot.plugins = bot.plugins.filter { _.identifier != plugin.identifier } + pluginStatus = pluginStatus.updated(plugin.identifier, false) + true + } + + override var handlers: Map[CommandFilterMagnet, Handler] = Map { + stringToCommandFilter("enable") -> { msg : Message => + val response = msg.text.fold { + "Enter a plugin name" + } { text => + if (enableByIdentifier(text)) { + "Enabled!" + } else { + "Plugin not found" + } + } + + Future { Some(response) }(ExecutionContext.global) + } + + stringToCommandFilter("disable") -> { msg : Message => + val response = msg.text.fold { + "Enter a plugin name" + } { text => + if (disableByIdentifier(text)) { + "Disabled!" + } else { + "Plugin not found" + } + } + + Future { Some(response) }(ExecutionContext.global) + } + + stringToCommandFilter("status") -> { _ => + var response = "" + + pluginStatus.foreach { pair => + response += managedPlugins.get(pair._1).fold { + // ignore and do the rest + "" + } { plugin => + s"${plugin.name}. Status: ${if (pair._2) "UP" else "DOWN"}" + } + } + + Future { Some(response) }(ExecutionContext.global) + } + } +}