External plugins
This commit is contained in:
parent
04537e3a46
commit
e97c52212a
6 changed files with 124 additions and 26 deletions
|
@ -17,6 +17,8 @@
|
||||||
|
|
||||||
package org.congressodeiradicali.karlmarx
|
package org.congressodeiradicali.karlmarx
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
import com.bot4s.telegram.api.RequestHandler
|
import com.bot4s.telegram.api.RequestHandler
|
||||||
import com.bot4s.telegram.api.declarative.{Command, Commands}
|
import com.bot4s.telegram.api.declarative.{Command, Commands}
|
||||||
import com.bot4s.telegram.clients.ScalajHttpClient
|
import com.bot4s.telegram.clients.ScalajHttpClient
|
||||||
|
@ -52,6 +54,21 @@ class Bot(val token: String) extends TelegramBot
|
||||||
plugin(new SetPlugin(this))
|
plugin(new SetPlugin(this))
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Load external plugins
|
||||||
|
|
||||||
|
val pluginLoader: PluginLoader = new JARPluginLoader()
|
||||||
|
|
||||||
|
private def loadExternalPlugins = {
|
||||||
|
val d = new File("plugins")
|
||||||
|
if (d.exists && d.isDirectory) {
|
||||||
|
d.listFiles().filter(_.isFile).map(pluginLoader.loadFromFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loadExternalPlugins
|
||||||
|
|
||||||
|
////////////////////////
|
||||||
|
|
||||||
// Future[Option[T]] is just two wrappers; remove the inner, useless one
|
// Future[Option[T]] is just two wrappers; remove the inner, useless one
|
||||||
def collapseFutureOption[T](arg: Future[Option[T]]): Future[T] = arg.flatMap {
|
def collapseFutureOption[T](arg: Future[Option[T]]): Future[T] = arg.flatMap {
|
||||||
case Some(x) => Future(x)
|
case Some(x) => Future(x)
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
This file is part of karl-marx.
|
||||||
|
|
||||||
|
karl-marx is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
karl-marx is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with karl-marx. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.congressodeiradicali.karlmarx
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URL
|
||||||
|
import java.util.Properties
|
||||||
|
import java.util.jar.JarFile
|
||||||
|
|
||||||
|
import scala.reflect.internal.util.ScalaClassLoader.URLClassLoader
|
||||||
|
import scala.util.{Failure, Success, Try}
|
||||||
|
|
||||||
|
class JARPluginLoader extends PluginLoader {
|
||||||
|
|
||||||
|
final val MANIFEST_LOCATION = "plugin-manifest.properties"
|
||||||
|
// manifest structure is
|
||||||
|
// package=some.package
|
||||||
|
// class=PluginClassName
|
||||||
|
|
||||||
|
|
||||||
|
override def loadFromFile(file: File): Try[Plugin] = {
|
||||||
|
val jarFile = new JarFile(file)
|
||||||
|
val manifestInputStream = jarFile.getInputStream(jarFile.getEntry(MANIFEST_LOCATION))
|
||||||
|
|
||||||
|
val props = new Properties()
|
||||||
|
props.load(manifestInputStream)
|
||||||
|
|
||||||
|
manifestInputStream.close()
|
||||||
|
|
||||||
|
val `package` = props.getProperty("package")
|
||||||
|
val `class` = props.getProperty("class")
|
||||||
|
|
||||||
|
val fullClassName = s"${`package`}.${`class`}"
|
||||||
|
|
||||||
|
try {
|
||||||
|
val url = file.toURI.toURL
|
||||||
|
val jarUrl = s"jar:${url.toString}!/"
|
||||||
|
val urls = Seq[URL](new URL(jarUrl))
|
||||||
|
val ucl = new URLClassLoader(urls, null)
|
||||||
|
|
||||||
|
// TODO deprecation
|
||||||
|
val plugin = Class.forName(fullClassName, true, ucl).newInstance().asInstanceOf[Plugin]
|
||||||
|
Success(plugin)
|
||||||
|
} catch {
|
||||||
|
case e: Throwable => Failure(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -33,7 +33,6 @@ object Locales {
|
||||||
|
|
||||||
(LocalizableString.BAN_UNAUTHORIZED, "Only an administrator can ban users"),
|
(LocalizableString.BAN_UNAUTHORIZED, "Only an administrator can ban users"),
|
||||||
(LocalizableString.BAN_SUCCESSFUL, "User was banned successfully"),
|
(LocalizableString.BAN_SUCCESSFUL, "User was banned successfully"),
|
||||||
(LocalizableString.BAN_FAILED, "Cannot ban, something went wrong"),
|
|
||||||
(LocalizableString.BAN_FAILED_INVALID_USER, "Cannot ban, invalid user"),
|
(LocalizableString.BAN_FAILED_INVALID_USER, "Cannot ban, invalid user"),
|
||||||
(LocalizableString.BAN_FAILED_BAN_ADMIN, "Cannot ban an admin user"),
|
(LocalizableString.BAN_FAILED_BAN_ADMIN, "Cannot ban an admin user"),
|
||||||
(LocalizableString.BAN_FAILED_REPLY, "Please reply to a message to ban someone"),
|
(LocalizableString.BAN_FAILED_REPLY, "Please reply to a message to ban someone"),
|
||||||
|
@ -49,7 +48,6 @@ object Locales {
|
||||||
|
|
||||||
(LocalizableString.BAN_UNAUTHORIZED, "Solo un amministratore può bannare gli utenti"),
|
(LocalizableString.BAN_UNAUTHORIZED, "Solo un amministratore può bannare gli utenti"),
|
||||||
(LocalizableString.BAN_SUCCESSFUL, "Utente bannato con successo"),
|
(LocalizableString.BAN_SUCCESSFUL, "Utente bannato con successo"),
|
||||||
(LocalizableString.BAN_FAILED, "Non sono riuscito a bannare, qualcosa è andato storto"),
|
|
||||||
(LocalizableString.BAN_FAILED_INVALID_USER, "Impossibile bannare, utente non valido"),
|
(LocalizableString.BAN_FAILED_INVALID_USER, "Impossibile bannare, utente non valido"),
|
||||||
(LocalizableString.BAN_FAILED_BAN_ADMIN, "Non puoi bannare un admin"),
|
(LocalizableString.BAN_FAILED_BAN_ADMIN, "Non puoi bannare un admin"),
|
||||||
(LocalizableString.BAN_FAILED_REPLY, "Rispondi a un messaggio per bannare qualcuno"),
|
(LocalizableString.BAN_FAILED_REPLY, "Rispondi a un messaggio per bannare qualcuno"),
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
/*
|
||||||
|
This file is part of karl-marx.
|
||||||
|
|
||||||
|
karl-marx is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
karl-marx is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with karl-marx. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.congressodeiradicali.karlmarx
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
import scala.util.Try
|
||||||
|
|
||||||
|
trait PluginLoader {
|
||||||
|
|
||||||
|
def loadFromFile(file: File): Try[Plugin]
|
||||||
|
|
||||||
|
}
|
|
@ -18,11 +18,9 @@
|
||||||
package org.congressodeiradicali.karlmarx.coreplugins
|
package org.congressodeiradicali.karlmarx.coreplugins
|
||||||
|
|
||||||
import com.bot4s.telegram.api.declarative.{CommandFilterMagnet, CommandImplicits}
|
import com.bot4s.telegram.api.declarative.{CommandFilterMagnet, CommandImplicits}
|
||||||
import org.congressodeiradicali.karlmarx.LocalizableString.LocalizableString
|
|
||||||
import org.congressodeiradicali.karlmarx._
|
import org.congressodeiradicali.karlmarx._
|
||||||
|
|
||||||
import scala.concurrent.Future
|
import scala.concurrent.Future
|
||||||
import scala.util.{Failure, Success}
|
|
||||||
|
|
||||||
class BanPlugin(bot: Bot) extends CorePlugin with CommandImplicits {
|
class BanPlugin(bot: Bot) extends CorePlugin with CommandImplicits {
|
||||||
|
|
||||||
|
@ -32,33 +30,25 @@ class BanPlugin(bot: Bot) extends CorePlugin with CommandImplicits {
|
||||||
override val identifier: String = "ban"
|
override val identifier: String = "ban"
|
||||||
|
|
||||||
override var commandHandlers: Map[CommandFilterMagnet, CommandHandler] = Map {
|
override var commandHandlers: Map[CommandFilterMagnet, CommandHandler] = Map {
|
||||||
stringToCommandFilter("ban") -> { (msg, argv) =>
|
stringToCommandFilter("ban") -> { (msg, _) =>
|
||||||
|
|
||||||
var futureLocalizedString: Future[LocalizableString] = null
|
val futureLocalizedString = msg.replyToMessage.fold {
|
||||||
|
Future { LocalizableString.BAN_FAILED_REPLY }
|
||||||
if (argv.length > 0) {
|
} { reply =>
|
||||||
|
reply.from.fold {
|
||||||
} else {
|
Future { LocalizableString.BAN_FAILED_INVALID_USER }
|
||||||
futureLocalizedString = msg.replyToMessage.fold {
|
} { user =>
|
||||||
Future { LocalizableString.BAN_FAILED_REPLY }
|
bot.requestBotUser(user, msg.chat).map { target =>
|
||||||
} { reply =>
|
if (target.isAdmin || target.isCreator)
|
||||||
reply.from.fold {
|
LocalizableString.BAN_FAILED_BAN_ADMIN
|
||||||
Future { LocalizableString.BAN_FAILED_INVALID_USER }
|
else {
|
||||||
} { user =>
|
target.ban()
|
||||||
bot.requestBotUser(user, msg.chat).map { target =>
|
LocalizableString.BAN_SUCCESSFUL
|
||||||
if (target.isAdmin || target.isCreator)
|
|
||||||
LocalizableString.BAN_FAILED_BAN_ADMIN
|
|
||||||
else {
|
|
||||||
target.ban()
|
|
||||||
LocalizableString.BAN_SUCCESSFUL
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
futureLocalizedString.map { s => Some(bot.localize(s)) }
|
futureLocalizedString.map { s => Some(bot.localize(s)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,7 +71,7 @@ class PluginManagerPlugin(bot: Bot) extends CorePlugin with CommandImplicits {
|
||||||
Some(
|
Some(
|
||||||
bot.plugins.values.map { plugin =>
|
bot.plugins.values.map { plugin =>
|
||||||
s"${plugin.identifier}: ${plugin.name}. ${plugin.description}. License: ${plugin.license}. Author: ${plugin.author}"
|
s"${plugin.identifier}: ${plugin.name}. ${plugin.description}. License: ${plugin.license}. Author: ${plugin.author}"
|
||||||
}.mkString("\n")
|
}.mkString("\n\n")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in a new issue