From 82faf2d25f95f42940e0945f68f2b4231949950f Mon Sep 17 00:00:00 2001 From: zingmars Date: Sun, 11 Oct 2015 14:16:11 +0300 Subject: [PATCH] See the releases section for full change list --- CHANGELOG | 18 ++++++- PluginSettings.example | 1 + README.MD | 3 +- TODO | 20 ++++++++ src/BasePlugin.kt | 5 +- src/BotPlugins/AbuserList.kt | 78 +++++++++++++++++++++++++++++ src/BotPlugins/AdminCommands.kt | 2 +- src/BotPlugins/DeadboxCheck.kt | 26 ++++++---- src/BotPlugins/HonourableUsers.kt | 81 +++++++++++++++++++++++++++++++ src/BotPlugins/LastSeen.kt | 11 ++--- src/BotPlugins/Quotes.kt | 48 ++++++++++++++++++ src/BotPlugins/Time.kt | 78 +++++++++++++++++++++++++++++ src/BotPlugins/TwitchCheck.kt | 16 ++---- src/BotPlugins/UserCommands.kt | 10 ++-- src/Box.kt | 3 +- src/CLI.kt | 25 +++++++--- src/Logger.kt | 2 +- src/Plugins.kt | 28 +++++++++-- src/Settings.kt | 11 +++++ 19 files changed, 411 insertions(+), 55 deletions(-) create mode 100644 TODO create mode 100644 src/BotPlugins/AbuserList.kt create mode 100644 src/BotPlugins/HonourableUsers.kt create mode 100644 src/BotPlugins/Quotes.kt create mode 100644 src/BotPlugins/Time.kt diff --git a/CHANGELOG b/CHANGELOG index 925599c..4ad3b4f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,2 +1,16 @@ -(29.09.2015) v0.0.0 - Initial commit -(06.10.2015) v1.0.0 - Initial commit to github \ No newline at end of file +(29.09.2015) v0.0.0 ++ Initial commit +(06.10.2015) v1.0.0 ++ Initial commit to github ++ A bot that allows connecting to a cbot.ws chatbox and implements various plugins +(11.10.2015) v1.1.0 ++) You can now set plugin settings from CLI (if they implement the function) ++) Implemented privilege system for plugins. ++) New default plugin - Time manager. Either outputs current time (in any time zone) or time until a specified time/date. ++) New default plugin - You can now ban specific users from using the bot ++) New default plugin - Honourable user (bot admin) manager. + +*) Fixed plugin: Deadbox check. The plugin never properly set the time of the last message, so it never worked. +*) Fixed plugin: LastSeen should now properly greet specific users if they haven't posted for ~24hrs +*) There is now a function that allows you to get the current UNIX time. It's in the settings class. +*) Release.zip should now be extractable by all zip archivers, not just the very modern ones. \ No newline at end of file diff --git a/PluginSettings.example b/PluginSettings.example index 10cc702..32d6cdc 100644 --- a/PluginSettings.example +++ b/PluginSettings.example @@ -2,3 +2,4 @@ #Tue Oct 06 10:28:36 UTC 2015 LastSeen= StreamerList=zingmars\:0\\0 +HonourableUsers= \ No newline at end of file diff --git a/README.MD b/README.MD index 15c08ac..b9a4033 100644 --- a/README.MD +++ b/README.MD @@ -91,8 +91,7 @@ There are couple of notes though: ------ # TODO? - -A full refactor to make the code consistent would be nice. Plenty of TODO's scattered through the code as well. Even so, this is project is, for all intents and purposes, finished. Feel free to fork and do whatever. +A full refactor to make the code consistent would be nice. Some TODO's are listed in the TODO file as well. Even so, this is project is, for all intents and purposes, finished. Feel free to fork and do whatever. ------ # License diff --git a/TODO b/TODO new file mode 100644 index 0000000..ca6381a --- /dev/null +++ b/TODO @@ -0,0 +1,20 @@ +Cbox class: ++) Have it check login state every couple of hours +*) Fix characters going missing when sending a message +*) Fix custom emotes being in tags (have them appear as emote: ) +*) Since cbox automatically html encodes the messages, decode them back to their respective characters + +CLI class: +*) All of the CLI commands should have some sort of result indicators +*) Fix CLI crashing on some exceptions, even if they are caught +*) Make CLI chat have output that is independent of input + +Plugin loader class: +*) Find a way to make Class loader non-case sensitive + +Plugins: ++) Write a plugin that allows managing the bot the same way you can do it from CLI. (Have them share the function sets?) ++) Finish the quotes plugin +*) Rewrite AdminCommands +*) Get a JSON parser library for LastSeen and TwitchCheck plugins, implement it +*) Implement a way for plugins to register their commands to avoid duplicate commands and allow easier @help output \ No newline at end of file diff --git a/src/BasePlugin.kt b/src/BasePlugin.kt index a816c05..9577689 100644 --- a/src/BasePlugin.kt +++ b/src/BasePlugin.kt @@ -12,7 +12,7 @@ import ThreadController open public class BasePlugin() { public var settings :Settings? = null public var logger :Logger? = null - public var handher :Plugins? = null + public var handler :Plugins? = null public var pluginName :String? = null public var controller :ThreadController? = null @@ -30,7 +30,7 @@ open public class BasePlugin() { { this.settings = settings this.logger = logger - this.handher = pluginsHandler + this.handler = pluginsHandler this.pluginName = pluginName this.controller = controller if(this.pubInit()) this.logger?.LogPlugin(pluginName, "Started!") @@ -45,4 +45,5 @@ open public class BasePlugin() { open public fun pubInit() :Boolean { return true } //Initializer open public fun connector(buffer :PluginBufferItem) :Boolean { return true } //Receives data from Plugin controller open public fun stop() {} //This is run when the plugin is unloaded + open public fun executeCommand(command :String) :String { return "Plugin not configured" } //Execute a command } \ No newline at end of file diff --git a/src/BotPlugins/AbuserList.kt b/src/BotPlugins/AbuserList.kt new file mode 100644 index 0000000..c42c291 --- /dev/null +++ b/src/BotPlugins/AbuserList.kt @@ -0,0 +1,78 @@ +/** + * Created by zingmars on 11.10.2015. + */ +package BotPlugins +import Containers.PluginBufferItem + +public class AbuserList : BasePlugin() +{ + override fun pubInit() :Boolean + { + return true + } + override fun connector(buffer : PluginBufferItem) :Boolean + { + var message = buffer.message.split(" ") + when(message[0].toLowerCase()) { + "@ignorelist" -> { + var ignored = settings?.GetSetting("AbuserList") as String + var isAdmin = handler?.isPluginAdmin(buffer.userName) as Boolean + if(message[1] != "") { + controller?.AddToBoxBuffer("Users banned from using the bot: " + ignored) + } else { + if (isAdmin) { + if(message[1] == "add") { + if(message[2] == "") { + controller?.AddToBoxBuffer("Please enter an username") + } else { + AddIgnored(message[2]) + } + } else if (message[1] == "remove") { + if(message[2] == "") { + controller?.AddToBoxBuffer("Please enter an username") + } else { + if(!RemoveIgnored(message[2])) { + controller?.AddToBoxBuffer(message[2] + " is not in the ignored list.") + } + } + } + } else { + controller?.AddToBoxBuffer("Insufficient rights") + } + } + } + } + return true + } + override fun executeCommand(command :String) :String + { + var action = command.split(",") + when(action[0].toLowerCase()) { + "add" -> { return "Result: " + AddIgnored(action[1]).toString()} + "remove" -> { return "Result: " + RemoveIgnored(action[1]).toString() } + else -> { return "Incorrect command"} + } + } + + private fun AddIgnored(name :String) :Boolean + { + var ignorelist = settings?.GetSetting("AbuserList") as String + if(!ignorelist.contains(name)) { + settings?.SetSetting("AbuserList", ignorelist+","+name) + logger?.LogPlugin(this.pluginName as String, "User ignored: " + name) + return true + } + return false + } + private fun RemoveIgnored(name :String) :Boolean + { + var ignorelist = settings?.GetSetting("AbuserList") as String + if(ignorelist.contains(name)) { + ignorelist = ignorelist.substring(0, ignorelist.indexOf(name)-1) + ignorelist.substring(ignorelist.indexOf(name)+name.length()) + settings?.SetSetting("AbuserList", ignorelist) + logger?.LogPlugin(this.pluginName as String, "Removed ignored user: " + name) + return true + } + return false + } +} diff --git a/src/BotPlugins/AdminCommands.kt b/src/BotPlugins/AdminCommands.kt index d81347e..d873b39 100644 --- a/src/BotPlugins/AdminCommands.kt +++ b/src/BotPlugins/AdminCommands.kt @@ -12,7 +12,7 @@ public class AdminCommands : BasePlugin() override fun pubInit() :Boolean { try { - if(handher?.isAdmin() == false) { + if(handler?.isAdmin() == false) { throw Exception("User does not have mod rights to the given box. Exiting.") } diff --git a/src/BotPlugins/DeadboxCheck.kt b/src/BotPlugins/DeadboxCheck.kt index 1972b78..9fd3f02 100644 --- a/src/BotPlugins/DeadboxCheck.kt +++ b/src/BotPlugins/DeadboxCheck.kt @@ -29,18 +29,24 @@ public class DeadboxCheck : BasePlugin() } override fun connector(buffer : PluginBufferItem) :Boolean { - var timeSinceLast = buffer.time.toLong() - lastMessage - if(lastMessage != 0L && timeSinceLast >= 3600L) { - if(timeSinceLast > RecordTime) { - RecordTime = timeSinceLast - RecordUsername = buffer.userName - controller?.AddToBoxBuffer("Congratz " + buffer.userName + "! You just revived the box and set a new record doing so! This deadbox lasted " + (timeSinceLast.toDouble()/60).toString() + " minutes.") - saveData() - } else { - controller?.AddToBoxBuffer("Congratz " + buffer.userName + "! You just revived the box. This deadbox lasted " + (timeSinceLast.toDouble()/60).toString() + " minutes. The longest recorded deadbox was " + (RecordTime.toDouble()/60).toString() + " minutes long and it was broken by " + RecordUsername) + try { + var timeSinceLast = buffer.time.toLong() - lastMessage + if(lastMessage != 0L && timeSinceLast >= 3600L) { + if(timeSinceLast > RecordTime) { + RecordTime = timeSinceLast + RecordUsername = buffer.userName + controller?.AddToBoxBuffer("Congratz " + buffer.userName + "! You just revived the box and set a new record doing so! This deadbox lasted " + (timeSinceLast.toDouble()/60).toString() + " minutes.") + saveData() + } else { + controller?.AddToBoxBuffer("Congratz " + buffer.userName + "! You just revived the box. This deadbox lasted " + (timeSinceLast.toDouble()/60).toString() + " minutes. The longest recorded deadbox was " + (RecordTime.toDouble()/60).toString() + " minutes long and it was broken by " + RecordUsername) + } } + lastMessage = settings?.getCurrentTime() as Long + return true + } catch (e: Exception) { + logger?.LogPlugin(this.pluginName as String, "Error: " + e.toString()) + return false } - return true } private fun saveData() { diff --git a/src/BotPlugins/HonourableUsers.kt b/src/BotPlugins/HonourableUsers.kt new file mode 100644 index 0000000..d1a22aa --- /dev/null +++ b/src/BotPlugins/HonourableUsers.kt @@ -0,0 +1,81 @@ +/** + * Allows adding bot admins + * Created by zingmars on 11.10.2015. + */ +package BotPlugins +import Containers.PluginBufferItem + +public class HonourableUsers : BasePlugin() +{ + override fun pubInit() :Boolean + { + return true + } + override fun connector(buffer : PluginBufferItem) :Boolean + { + var message = buffer.message.split(" ") + when(message[0].toLowerCase()) { + "@admins" -> { + var admins = settings?.GetSetting("HonourableUsers").toString() + var isAdmin = handler?.isPluginAdmin(buffer.userName) as Boolean + if(message[1] != "") { + controller?.AddToBoxBuffer("Bot administrators: " + admins) + } else { + if(isAdmin) { + if(message[1] == "add") { + if(message[2] == "") { + controller?.AddToBoxBuffer("Please enter username") + } else { + AddAdmin(message[2]) + } + } else if (message[1] == "remove") { + if(message[2] == "") { + controller?.AddToBoxBuffer("Please enter username") + } else { + if(!RemoveAdmin(message[2])) { + controller?.AddToBoxBuffer(message[2]+" is not an admin.") + } + } + } + } else { + controller?.AddToBoxBuffer("Insufficient rights") + } + } + } + } + return true + } + override fun executeCommand(command :String) :String + { + var action = command.split(",") + when(action[0].toLowerCase()) { + "add" -> { return "Result: " + AddAdmin(action[1]).toString()} + "remove" -> { return "Result: " + RemoveAdmin(action[1]).toString() } + else -> { return "Incorrect command"} + } + } + + // Admin management functions + private fun AddAdmin(name :String) :Boolean + { + var admins = settings?.GetSetting("HonourableUsers") as String + if(!admins.contains(name)) { + settings?.SetSetting("HonourableUsers", admins+","+name) + logger?.LogPlugin(this.pluginName as String, "Adding admin: " + name) + return true + } + return false + } + private fun RemoveAdmin(name :String) :Boolean + { + var admins = settings?.GetSetting("HonourableUsers") as String + if(admins.contains(name)) { + admins = admins.substring(0, admins.indexOf(name)-1) + admins.substring(admins.indexOf(name)+name.length()) + settings?.SetSetting("HonourableUsers", admins) + logger?.LogPlugin(this.pluginName as String, "Removed admin: " + name) + return true + } + return false + } +} + diff --git a/src/BotPlugins/LastSeen.kt b/src/BotPlugins/LastSeen.kt index 16839b2..cfb2e85 100644 --- a/src/BotPlugins/LastSeen.kt +++ b/src/BotPlugins/LastSeen.kt @@ -8,7 +8,6 @@ import java.util.* public class LastSeen : BasePlugin() { var users :TreeMap> = TreeMap(String.CASE_INSENSITIVE_ORDER) - var HonourableUsers = ArrayList() //TODO: Convert the data into a JSON string or something, because if someone uses these characters in their username the loading will be broken var dbUserNameSeparator = "=" var dbUserDataSeparator = "+" @@ -50,9 +49,7 @@ public class LastSeen : BasePlugin() { //Load data saved in the database try { settings?.checkSetting("LastSeen", true) //Create the settings variable if it doesn't exist, otherwise it will return a fail - settings?.checkSetting("LastSeenHonourable", true) - var savedHonours = settings?.GetSetting("LastSeenHonourable") var savedDB = settings?.GetSetting("LastSeen").toString() if(savedDB != "") { var data = savedDB.split(dbRecordSeparator) @@ -62,9 +59,6 @@ public class LastSeen : BasePlugin() { users.put(username, userdata) } } - if(savedHonours != "" && savedHonours != null) { - HonourableUsers = savedHonours.split(",").toArrayList() - } //Run a separate thread to save users in the background saverThread = Thread(Runnable { this.databaseSaver() }) saverThread.isDaemon = true @@ -83,7 +77,7 @@ public class LastSeen : BasePlugin() { if(message[0].toLowerCase() == "@lastseen" && (buffer.privilvl == "mod" || buffer.privilvl == "user")) { var user = users.get(message[1]) if(user != null) { - if(message[1].toLowerCase() != handher?.username?.toLowerCase()) { + if(message[1].toLowerCase() != handler?.username?.toLowerCase()) { controller?.AddToBoxBuffer(buffer.userName+": User \"" + message[1] + "\" last seen " + Date(user[2].toLong()*1000).toString()) } else { controller?.AddToBoxBuffer(buffer.userName+": I'm here!") @@ -97,7 +91,8 @@ public class LastSeen : BasePlugin() { var user = users.get(buffer.userName) if(user != null) { // Greet Honourable users - if(HonourableUsers.contains(buffer.userName) && buffer.time.toLong() - user[2].toLong() > 86400) { + var isAdmin = handler?.isPluginAdmin(buffer.userName) as Boolean + if(isAdmin && buffer.time.toLong() - user[2].toLong() > 86400) { controller?.AddToBoxBuffer("Welcome back " + buffer.userName + "!") } diff --git a/src/BotPlugins/Quotes.kt b/src/BotPlugins/Quotes.kt new file mode 100644 index 0000000..9a64cca --- /dev/null +++ b/src/BotPlugins/Quotes.kt @@ -0,0 +1,48 @@ +/** + * Return a quote. + * Created by zingmars on 11.10.2015. + */ +package BotPlugins +import Containers.PluginBufferItem + +public class Quotes : BasePlugin() +{ + override fun pubInit() :Boolean + { + // Load quotes DB + return false // Not implemented yet + } + override fun connector(buffer : PluginBufferItem) :Boolean + { + var message = buffer.message.split(" ") + when(message[0].toLowerCase()) { + "@quote" -> { + var isAdmin = handler?.isPluginAdmin(buffer.userName) as Boolean + if(message[1] != "") { + // Select specific quote + } else { + if(isAdmin) { + if(message[1] == "add") { + // Add a quote. Check for privileges. + } else if(message[1] == "remove") { + + } + else { + // Select a random quote + } + } else { + + } + } + } + } + return true + } + override fun executeCommand(command :String) :String + { + // Reload quotes + // Add + // Remove + return "" + } +} diff --git a/src/BotPlugins/Time.kt b/src/BotPlugins/Time.kt new file mode 100644 index 0000000..c84e228 --- /dev/null +++ b/src/BotPlugins/Time.kt @@ -0,0 +1,78 @@ +/** + * Time command plugin + * Created by zingmars on 11.10.2015. + */ +package BotPlugins +import Containers.PluginBufferItem +import java.text.SimpleDateFormat +import java.util.* + +public class Time : BasePlugin() +{ + override fun pubInit() :Boolean + { + return true + } + override fun connector(buffer : PluginBufferItem) :Boolean + { + var message = buffer.message.split(" ") + when(message[0].toLowerCase()) { + "@time" -> { + var Format = SimpleDateFormat("dd-MM-yyyy HH:mm:ss z") + if(message[1] == "") { + controller?.AddToBoxBuffer("Current time: " + Format.format(Date())) + } else { + try { + var TZ = TimeZone.getTimeZone(message[1]) + Format.timeZone = TZ + controller?.AddToBoxBuffer("Current time: " + Format.format(Date())) + } catch (e: Exception) { + controller?.AddToBoxBuffer("Current time: " + Format.format(Date())) + } + } + } + "@timeuntil" -> { + var Format = SimpleDateFormat("dd-MM-yyyy HH:mm:ss") + try { + // 1 - Date + if(message[1] == "") { + throw Exception("Wrong date") + } + var date = message[1] + + // 2 - Hour + var hour = "00:00:00" + if(message[2] != "") { + hour = message[2] + } + + // 3 - Time zone + var timezone = "UTC" + if(message[3] != "") { + timezone = message[3] + } + + var currentDate = Date() + var currentUNIX = currentDate.time/1000 + + var TZ = TimeZone.getTimeZone(timezone) + Format.timeZone = TZ + var inputTime = Format.parse(date + " " + hour) + var inputUNIX = inputTime.time/1000 + + var difference = inputUNIX - currentUNIX + if(difference < 1) { + controller?.AddToBoxBuffer(settings?.generateTimeString(currentUNIX, inputUNIX, "ago") as String) + } + else { + controller?.AddToBoxBuffer(settings?.generateTimeString(inputUNIX, currentUNIX, "") as String) + } + + } catch (e: Exception) { + controller?.AddToBoxBuffer("Syntax - dd-MM-yyyy HH:mm:ss z, where dd - date, MM - month, yyyy - year, HH - hour (24h), mm - minute, ss - second, z - timezone. You must specify a date, the rest is optional.") + } + } + } + return true + } +} diff --git a/src/BotPlugins/TwitchCheck.kt b/src/BotPlugins/TwitchCheck.kt index 9feb892..c473139 100644 --- a/src/BotPlugins/TwitchCheck.kt +++ b/src/BotPlugins/TwitchCheck.kt @@ -61,8 +61,7 @@ public class TwitchCheck : BasePlugin() } else { var lastStreamDate = user.get(1).toLong() if(lastStreamDate != 0L) { - //var timeString = generateTimeString((System.currentTimeMillis() / 1000L), user.get(0).toLong(), " ago") - var stopTimeString = generateTimeString((System.currentTimeMillis() / 1000L), lastStreamDate, " ago") + var stopTimeString = settings?.generateTimeString(settings?.getCurrentTime() as Long, lastStreamDate, " ago") var timeString = Date((user.get(0).toLong()*1000)) controller?.AddToBoxBuffer("User last streamed " + timeString + " (stream ended " + stopTimeString + ")") } else { @@ -103,7 +102,7 @@ public class TwitchCheck : BasePlugin() if(!response.contains("\"stream\":null") && state == "false") { changes = true - data.set(0, (System.currentTimeMillis() / 1000L).toString()) + data.set(0, settings?.getCurrentTime().toString()) stalkList.set(key, data) stalkState.set(key, "true") @@ -119,11 +118,11 @@ public class TwitchCheck : BasePlugin() if(stalkState.get(key) == "true") { changes = true - data.set(1, (System.currentTimeMillis() / 1000L).toString()) + data.set(1, settings?.getCurrentTime().toString()) stalkList.set(key, data) stalkState.set(key, "false") logger?.LogPlugin(this.pluginName.toString(), "User " + key + " has stopped streaming!") - controller?.AddToBoxBuffer("User " + key + " has stopped streaming. Stream length was " + generateTimeString(data.get(1).toLong(), data.get(0).toLong()) + " minutes") + controller?.AddToBoxBuffer("User " + key + " has stopped streaming. Stream length was " + settings?.generateTimeString(data.get(1).toLong(), data.get(0).toLong()) + " minutes") } } } else { @@ -152,11 +151,4 @@ public class TwitchCheck : BasePlugin() } } } - private fun generateTimeString(current :Long, past :Long, endString :String = "") :String - { - var streamMinutesAgo = (current-past).toDouble()/60 - var streamHoursAgo = if(streamMinutesAgo/60.0 >= 1.0) {streamMinutesAgo/60.0} else 0.0 - var streamDaysAgo = if(streamHoursAgo/24.0 >= 1.0) {streamHoursAgo/24.0} else 0.0 - return if(streamDaysAgo != 0.0) {streamDaysAgo.toString() + " days"+ endString} else if (streamHoursAgo != 0.0) {streamHoursAgo.toString() + " hours" + endString} else {streamMinutesAgo.toString() + " minutes" + endString} - } } diff --git a/src/BotPlugins/UserCommands.kt b/src/BotPlugins/UserCommands.kt index 2027134..c248358 100644 --- a/src/BotPlugins/UserCommands.kt +++ b/src/BotPlugins/UserCommands.kt @@ -20,13 +20,13 @@ public class UserCommands : BasePlugin() //TODO: have some sort of database where plugins can register their commands so this command can be automated. "@help" -> { controller?.AddToBoxBuffer("For more information please see https://github.com/zingmars/Cbox-bot. For feature requests ask zingmars.") - controller?.AddToBoxBuffer("@about - About this bot; @lastseen - Output the date of user's last message; @ping - check if I'm alive; @help - display this") - controller?.AddToBoxBuffer("@laststream - Get when an user has last streamed (try @laststream zingmars); @nextstream - OTG's next stream time") + controller?.AddToBoxBuffer("@about - About this bot; @lastseen - Output the date of user's last message; @ping - check if I'm alive; @help - display this; @time - time related commands (try help as a parameter") + controller?.AddToBoxBuffer("@laststream - Get when an user has last streamed (try @laststream zingmars); @nextstream - OTG's next stream time; @quote - gets a random quote.") controller?.AddToBoxBuffer("Available commands:") } - "@about" -> { - controller?.AddToBoxBuffer("Hi! My name is " + handher?.username + " and I'm a bot for cbox.ws written in Kotlin. Check me out at: https://github.com/zingmars/Cbox-bot") - } + "@about" -> { + controller?.AddToBoxBuffer("Hi! My name is " + handler?.username + " and I'm a bot for cbox.ws written in Kotlin. Check me out at: https://github.com/zingmars/Cbox-bot") + } } return true } diff --git a/src/Box.kt b/src/Box.kt index b086408..671db04 100644 --- a/src/Box.kt +++ b/src/Box.kt @@ -71,6 +71,7 @@ public class Box(private val Settings :Settings, private val Logger :Logger, pri } private fun Demon() { + //TODO: Check login state every couple of hours var pingcounter = 0 while(active) { try { @@ -130,7 +131,7 @@ public class Box(private val Settings :Settings, private val Logger :Logger, pri public fun GetMessages(lastID :String = lastMessageID) :ArrayList? { try { - var messages = HTTPUtility.GET("http://www"+server+".cbox.ws/box/?sec=ar&boxid="+id+"&boxtag="+tag+"&_v=857&p="+lastID+"&c="+(System.currentTimeMillis() / 1000L).toString()).split("\n").reversed() + var messages = HTTPUtility.GET("http://www"+server+".cbox.ws/box/?sec=ar&boxid="+id+"&boxtag="+tag+"&_v=857&p="+lastID+"&c="+Settings.getCurrentTime().toString()).split("\n").reversed() var sortedMessages = ArrayList() if(messages.size() > 0) { for (i in 0..messages.size()-2) { diff --git a/src/CLI.kt b/src/CLI.kt index c43ba6f..59b0e59 100644 --- a/src/CLI.kt +++ b/src/CLI.kt @@ -75,7 +75,7 @@ public class CLI (private val Settings :Settings, private val Logger :Logger, pr } private fun ActiveConnectionHandler(client :java.net.Socket) { - val SessionStartTime = System.currentTimeMillis() / 1000L; + val SessionStartTime = Settings.getCurrentTime() val out = PrintWriter(client.outputStream, true) val _in = BufferedReader(InputStreamReader(client.inputStream)) var connectionActive = true @@ -110,7 +110,7 @@ public class CLI (private val Settings :Settings, private val Logger :Logger, pr //TODO: have all of the functions return some sort of indication of their actions ":quit" -> { // Disconnect if(ConfirmAction(out, _in)) { - Logger.LogMessage(16, "Session lasted " + (System.currentTimeMillis() / 1000L - SessionStartTime).toString() + " seconds") + Logger.LogMessage(16, "Session lasted " + (Settings.getCurrentTime() - SessionStartTime).toString() + " seconds") client.close() connectionActive = false } @@ -120,7 +120,7 @@ public class CLI (private val Settings :Settings, private val Logger :Logger, pr } ":shutdowncli" -> { // Shut down the CLI interface. Warn - can't bring it up without restarting the server. if(ConfirmAction(out, _in)) { - Logger.LogMessage(16, "Session lasted " + (System.currentTimeMillis() / 1000L - SessionStartTime).toString() + " seconds") + Logger.LogMessage(16, "Session lasted " + (Settings.getCurrentTime() - SessionStartTime).toString() + " seconds") Logger.LogMessage(29) client.close() this.stop() @@ -135,7 +135,7 @@ public class CLI (private val Settings :Settings, private val Logger :Logger, pr } ":shutdown" -> { if(ConfirmAction(out, _in)) { - Logger.LogMessage(16, "Session lasted " + (System.currentTimeMillis() / 1000L - SessionStartTime).toString() + " seconds") + Logger.LogMessage(16, "Session lasted " + Settings.getCurrentTime().toString() + " seconds") Logger.LogMessage(55) out.println("Shutdown initiated. Good bye!") connectionActive = false @@ -335,7 +335,16 @@ public class CLI (private val Settings :Settings, private val Logger :Logger, pr Plugins.SetSetting(command[1], command[2]) out.println(command[1] + " set to " + command[2]) } - //TODO: Create a way to talk directly to plugins from CLI + "plugins.command" -> { + if (command[1] == "" || command[2] == "") { + out.println("Wrong syntax. Syntax - plugins.command ") + } else { + var param = command.join(",") + param = param.substring(param.indexOf(",")+1) //Pluginname + param = param.substring(param.indexOf(",")+1) //Command + out.println(Plugins.executeFunction(command[1], param)) + } + } else -> { out.println("Unrecognised command") } @@ -375,9 +384,10 @@ public class CLI (private val Settings :Settings, private val Logger :Logger, pr } private fun CLIChat(output :PrintWriter, input :BufferedReader, client :java.net.Socket) { + //TODO: Have CLI chat be independent of input // Very hacky CLI chat. It basically relies on timeout interruptions to receive messages and it isn't the most stable thing around. //Initialise environment - val SessionStartTime = System.currentTimeMillis() / 1000L; + val SessionStartTime = Settings.getCurrentTime(); Logger.LogMessage(57) ThreadController.GetCLIBuffer() //Clear buffer Box.toCLI = true @@ -395,7 +405,6 @@ public class CLI (private val Settings :Settings, private val Logger :Logger, pr for(msg in ThreadController.GetCLIBuffer()) { output.println(msg) } - try { var userInput = input.readLine() when (userInput) { @@ -403,7 +412,7 @@ public class CLI (private val Settings :Settings, private val Logger :Logger, pr CLIActive = false client.soTimeout = 0 Box.toCLI = false - Logger.LogMessage(58, "Session lasted " + (System.currentTimeMillis() / 1000L - SessionStartTime).toString() + " seconds") + Logger.LogMessage(58, "Session lasted " + (Settings.getCurrentTime() - SessionStartTime).toString() + " seconds") ThreadController.GetCLIBuffer() output.print("\u001B[2J") } diff --git a/src/Logger.kt b/src/Logger.kt index c827cca..deb3ce6 100644 --- a/src/Logger.kt +++ b/src/Logger.kt @@ -269,7 +269,7 @@ public class Logger(private val Settings :Settings) { } public fun ArchiveOldLogs(log :Boolean = true) { - val appZip = ZipUtil(logFolder, (System.currentTimeMillis() / 1000L).toString()+"_logs.zip", Settings.GetSetting("logFile"), Settings.GetSetting("chatLogFile"), Settings.GetSetting("pluginLogFile"), if (log) this else null) + val appZip = ZipUtil(logFolder, Settings.getCurrentTime().toString()+"_logs.zip", Settings.GetSetting("logFile"), Settings.GetSetting("chatLogFile"), Settings.GetSetting("pluginLogFile"), if (log) this else null) appZip.generateFileList() appZip.zipIt() //Wipe the folder diff --git a/src/Plugins.kt b/src/Plugins.kt index c95cb03..1fa2f26 100644 --- a/src/Plugins.kt +++ b/src/Plugins.kt @@ -18,6 +18,7 @@ public class Plugins(private val Settings :Settings, private val Logger :Logger, private val pluginList :MutableList = ArrayList() private val plugins = ArrayList() private var refreshRate = Settings.GetSetting("refreshRate").toLong() + private var abuserList = "" public var username = "" init @@ -25,6 +26,16 @@ public class Plugins(private val Settings :Settings, private val Logger :Logger, if(enabled) { if(Settings.checkSetting("username")) username = Settings.GetSetting("username") if(!Settings.checkSetting("isAdmin")) Settings.SetSetting("isAdmin", "false") + if(pluginSettings.checkSetting("AbuserList", true)) abuserList = pluginSettings.GetSetting("AbuserList") + pluginSettings.checkSetting("AbuserList", true) + //Add plugin admin + //TODO: Manager plugin that allows to do the same things you can do from CLI + if(pluginSettings.GetSetting("HonourableUsers") == "") { + println("Plugin admin not configured. Please enter new admin(s - comma seperated no spaces) (or leave blank to have no admin, in which case you'll need to manually enter comma seperated nicknames in plugin conf file)") + var input = readLine() + if(input == "") input = " " + pluginSettings.SetSetting("HonourableUsers", input.toString()) + } pluginSettings.SetLogger(Logger) this.start() @@ -102,7 +113,7 @@ public class Plugins(private val Settings :Settings, private val Logger :Logger, //Run data to plugins for (message in ThreadController.GetPluginBuffer()) { //run through loaded plugin's checklist - if(message.userName != username) { + if(message.userName != username && !pluginSettings.GetSetting("AbuserList").contains(message.userName)) { for(plugin in plugins) { plugin.connector(message) } @@ -121,8 +132,7 @@ public class Plugins(private val Settings :Settings, private val Logger :Logger, // We need to go through all of the plugins since we don't keep an index :( var i = 0 for (plugin in plugins) { - if(name.toLowerCase() == plugin.pluginName?.toLowerCase()) - { + if(name.toLowerCase() == plugin.pluginName?.toLowerCase()) { plugin.stop() plugins.remove(i) Logger.LogPlugin(plugin.pluginName.toString(), "Unloaded.") @@ -132,6 +142,14 @@ public class Plugins(private val Settings :Settings, private val Logger :Logger, } return "Plugin not found or already disabled." } + public fun executeFunction(pluginName :String, command :String) + { + for (plugin in plugins) { + if(pluginName.toLowerCase() == plugin.pluginName?.toLowerCase()) { + plugin.executeCommand(command) + } + } + } public fun LoadPlugin(name :String) :Int? { var source = pluginDirectory+name @@ -208,4 +226,8 @@ public class Plugins(private val Settings :Settings, private val Logger :Logger, { return Settings.GetSetting("isAdmin").toBoolean() } + public fun isPluginAdmin(name :String) :Boolean + { + return pluginSettings.GetSetting("HonourableUsers").toString().toLowerCase().toString().contains(name.toLowerCase()) + } } \ No newline at end of file diff --git a/src/Settings.kt b/src/Settings.kt index e2eb21b..cf7955d 100644 --- a/src/Settings.kt +++ b/src/Settings.kt @@ -176,4 +176,15 @@ public class Settings(private var settingsFileName :String = "settings.cfg", pri settingsFile = File(FileName) this.LoadSettings() } + public fun getCurrentTime() :Long + { + return System.currentTimeMillis() / 1000L + } + public fun generateTimeString(current :Long, past :Long, endString :String = "") :String + { + var streamMinutesAgo = (current-past).toDouble()/60 + var streamHoursAgo = if(streamMinutesAgo/60.0 >= 1.0) {streamMinutesAgo/60.0} else 0.0 + var streamDaysAgo = if(streamHoursAgo/24.0 >= 1.0) {streamHoursAgo/24.0} else 0.0 + return if(streamDaysAgo != 0.0) {streamDaysAgo.toString() + " days"+ endString} else if (streamHoursAgo != 0.0) {streamHoursAgo.toString() + " hours" + endString} else {streamMinutesAgo.toString() + " minutes" + endString} + } } \ No newline at end of file