From acb679f8fa78349415de4ed070322afcaaf2cac4 Mon Sep 17 00:00:00 2001 From: Brayden Banks Date: Fri, 8 Apr 2016 14:12:02 -0700 Subject: [PATCH 1/9] I should probably commit now. Less global magic! --- README.md | 14 +- bindings.lua | 100 +- bot.lua | 124 +-- plugins/about.lua | 31 +- plugins/administration.lua | 1771 +++++++++++++++++------------------ plugins/apod.lua | 49 +- plugins/bandersnatch.lua | 27 +- plugins/bible.lua | 50 +- plugins/blacklist.lua | 40 +- plugins/calc.lua | 34 +- plugins/cats.lua | 39 +- plugins/dice.lua | 2 +- plugins/dilbert.lua | 2 +- plugins/echo.lua | 2 +- plugins/gImages.lua | 2 +- plugins/gMaps.lua | 2 +- plugins/gSearch.lua | 2 +- plugins/hearthstone.lua | 2 +- plugins/help.lua | 2 +- plugins/imdb.lua | 2 +- plugins/lastfm.lua | 2 +- plugins/librefm.lua | 2 +- plugins/luarun.lua | 2 +- plugins/me.lua | 2 +- plugins/moderation.lua | 8 +- plugins/nick.lua | 2 +- plugins/pokedex.lua | 2 +- plugins/preview.lua | 2 +- plugins/reddit.lua | 4 +- plugins/setandget.lua | 4 +- plugins/shell.lua | 2 +- plugins/shout.lua | 2 +- plugins/slap.lua | 2 +- plugins/time.lua | 2 +- plugins/translate.lua | 2 +- plugins/urbandictionary.lua | 2 +- plugins/weather.lua | 2 +- plugins/wikipedia.lua | 2 +- plugins/xkcd.lua | 2 +- plugins/youtube.lua | 2 +- utilities.lua | 107 ++- 41 files changed, 1213 insertions(+), 1241 deletions(-) diff --git a/README.md b/README.md index b61e7af..5c7ec4e 100755 --- a/README.md +++ b/README.md @@ -53,13 +53,13 @@ Most plugins are intended for public use, but a few are for other purposes, like A plugin can have five components, and two of them are required: -| Component | Description | Required? | -|:----------|:---------------------------------------------|:----------| -| action | Main function. Expects `msg` table as an argument. | Y | -| triggers | Table of triggers for the plugin. Uses Lua patterns. | Y | -| cron | Optional function to be called every minute. | N | -| command | Basic command and syntax. Listed in the help text. | N | -| doc | Usage for the plugin. Returned by "/help $command". | N | +| Component | Description | Required? | +|:----------|:-----------------------------------------------------|:----------| +| action | Main function. Expects `msg` table as an argument. | Y | +| triggers | Table of triggers for the plugin. Uses Lua patterns. | Y | +| cron | Optional function to be called every minute. | N | +| command | Basic command and syntax. Listed in the help text. | N | +| doc | Usage for the plugin. Returned by "/help $command". | N | The `on_msg_receive()` function adds a few variables to the `msg` table for your convenience. These are self-explanatory: `msg.from.id_str`, `msg.to.id_str`, `msg.chat.id_str`, `msg.text_lower`, `msg.from.name`. diff --git a/bindings.lua b/bindings.lua index 0ddf9b5..db117bd 100755 --- a/bindings.lua +++ b/bindings.lua @@ -2,17 +2,13 @@ -- Bindings for the Telegram bot API. -- https://core.telegram.org/bots/api -assert(HTTPS) -assert(JSON) -assert(URL) +local bindings = {} -local BASE_URL = 'https://api.telegram.org/bot' .. config.bot_api_key +local HTTPS = require('ssl.https') +local JSON = require('cjson') +local URL = require('socket.url') -if config.bot_api_key == '' then - error('You did not set your bot token in config.lua!') -end - -sendRequest = function(url) +function bindings.sendRequest(url) local dat, res = HTTPS.request(url) @@ -30,28 +26,28 @@ sendRequest = function(url) end -getMe = function() +function bindings:getMe() - local url = BASE_URL .. '/getMe' - return sendRequest(url) + local url = self.BASE_URL .. '/getMe' + return bindings.sendRequest(url) end -getUpdates = function(offset) +function bindings:getUpdates(offset) - local url = BASE_URL .. '/getUpdates?timeout=20' + local url = self.BASE_URL .. '/getUpdates?timeout=20' if offset then url = url .. '&offset=' .. offset end - return sendRequest(url) + return bindings.sendRequest(url) end -sendMessage = function(chat_id, text, disable_web_page_preview, reply_to_message_id, use_markdown, disable_notification) +function bindings:sendMessage(chat_id, text, disable_web_page_preview, reply_to_message_id, use_markdown, disable_notification) - local url = BASE_URL .. '/sendMessage?chat_id=' .. chat_id .. '&text=' .. URL.escape(text) + local url = self.BASE_URL .. '/sendMessage?chat_id=' .. chat_id .. '&text=' .. URL.escape(text) if disable_web_page_preview == true then url = url .. '&disable_web_page_preview=true' @@ -69,30 +65,30 @@ sendMessage = function(chat_id, text, disable_web_page_preview, reply_to_message url = url .. '&disable_notification=true' end - return sendRequest(url) + return bindings.sendRequest(url) end -sendReply = function(msg, text) +function bindings:sendReply(msg, text) - return sendMessage(msg.chat.id, text, true, msg.message_id) + return bindings.sendMessage(self, msg.chat.id, text, true, msg.message_id) end -sendChatAction = function(chat_id, action) +function bindings:sendChatAction(chat_id, action) -- Support actions are typing, upload_photo, record_video, upload_video, record_audio, upload_audio, upload_document, find_location - local url = BASE_URL .. '/sendChatAction?chat_id=' .. chat_id .. '&action=' .. action - return sendRequest(url) + local url = self.BASE_URL .. '/sendChatAction?chat_id=' .. chat_id .. '&action=' .. action + return bindings.sendRequest(self, url) end -sendLocation = function(chat_id, latitude, longitude, reply_to_message_id, disable_notification) +function bindings:sendLocation(chat_id, latitude, longitude, reply_to_message_id, disable_notification) if latitude == 0 then latitude = 0.001 end if longitude == 0 then longitude = 0.001 end - local url = BASE_URL .. '/sendLocation?chat_id=' .. chat_id .. '&latitude=' .. latitude .. '&longitude=' .. longitude + local url = self.BASE_URL .. '/sendLocation?chat_id=' .. chat_id .. '&latitude=' .. latitude .. '&longitude=' .. longitude if reply_to_message_id then url = url .. '&reply_to_message_id=' .. reply_to_message_id @@ -102,27 +98,27 @@ sendLocation = function(chat_id, latitude, longitude, reply_to_message_id, disab url = url .. '&disable_notification=true' end - return sendRequest(url) + return bindings.sendRequest(self, url) end -forwardMessage = function(chat_id, from_chat_id, message_id, disable_notification) +function bindings:forwardMessage(chat_id, from_chat_id, message_id, disable_notification) - local url = BASE_URL .. '/forwardMessage?chat_id=' .. chat_id .. '&from_chat_id=' .. from_chat_id .. '&message_id=' .. message_id + local url = self.BASE_URL .. '/forwardMessage?chat_id=' .. chat_id .. '&from_chat_id=' .. from_chat_id .. '&message_id=' .. message_id if disable_notification then url = url .. '&disable_notification=true' end - return sendRequest(url) + return bindings.sendRequest(self, url) end -- TODO: More of this. -sendPhotoID = function(chat_id, file_id, caption, reply_to_message_id, disable_notification) +function bindings:sendPhotoID(chat_id, file_id, caption, reply_to_message_id, disable_notification) - local url = BASE_URL .. '/sendPhoto?chat_id=' .. chat_id .. '&photo=' .. file_id + local url = self.BASE_URL .. '/sendPhoto?chat_id=' .. chat_id .. '&photo=' .. file_id if caption then url = url .. '&caption=' .. URL.escape(caption) @@ -136,20 +132,20 @@ sendPhotoID = function(chat_id, file_id, caption, reply_to_message_id, disable_n url = url .. '&disable_notification=true' end - return sendRequest(url) + return bindings.sendRequest(self, url) end -curlRequest = function(curl_command) +function bindings.curlRequest(curl_command) -- Use at your own risk. Will not check for success. io.popen(curl_command) end -sendPhoto = function(chat_id, photo, caption, reply_to_message_id, disable_notification) +function bindings:sendPhoto(chat_id, photo, caption, reply_to_message_id, disable_notification) - local url = BASE_URL .. '/sendPhoto' + local url = self.BASE_URL .. '/sendPhoto' local curl_command = 'curl -s "' .. url .. '" -F "chat_id=' .. chat_id .. '" -F "photo=@' .. photo .. '"' @@ -165,13 +161,13 @@ sendPhoto = function(chat_id, photo, caption, reply_to_message_id, disable_notif curl_command = curl_command .. ' -F "disable_notification=true"' end - return curlRequest(curl_command) + return bindings.curlRequest(curl_command) end -sendDocument = function(chat_id, document, reply_to_message_id, disable_notification) +function bindings:sendDocument(chat_id, document, reply_to_message_id, disable_notification) - local url = BASE_URL .. '/sendDocument' + local url = self.BASE_URL .. '/sendDocument' local curl_command = 'curl -s "' .. url .. '" -F "chat_id=' .. chat_id .. '" -F "document=@' .. document .. '"' @@ -183,13 +179,13 @@ sendDocument = function(chat_id, document, reply_to_message_id, disable_notifica curl_command = curl_command .. ' -F "disable_notification=true"' end - return curlRequest(curl_command) + return bindings.curlRequest(curl_command) end -sendSticker = function(chat_id, sticker, reply_to_message_id, disable_notification) +function bindings:sendSticker(chat_id, sticker, reply_to_message_id, disable_notification) - local url = BASE_URL .. '/sendSticker' + local url = self.BASE_URL .. '/sendSticker' local curl_command = 'curl -s "' .. url .. '" -F "chat_id=' .. chat_id .. '" -F "sticker=@' .. sticker .. '"' @@ -201,13 +197,13 @@ sendSticker = function(chat_id, sticker, reply_to_message_id, disable_notificati curl_command = curl_command .. ' -F "disable_notification=true"' end - return curlRequest(curl_command) + return bindings.curlRequest(curl_command) end -sendAudio = function(chat_id, audio, reply_to_message_id, duration, performer, title, disable_notification) +function bindings:sendAudio(chat_id, audio, reply_to_message_id, duration, performer, title, disable_notification) - local url = BASE_URL .. '/sendAudio' + local url = self.BASE_URL .. '/sendAudio' local curl_command = 'curl -s "' .. url .. '" -F "chat_id=' .. chat_id .. '" -F "audio=@' .. audio .. '"' @@ -231,13 +227,13 @@ sendAudio = function(chat_id, audio, reply_to_message_id, duration, performer, t curl_command = curl_command .. ' -F "disable_notification=true"' end - return curlRequest(curl_command) + return bindings.curlRequest(curl_command) end -sendVideo = function(chat_id, video, reply_to_message_id, duration, caption, disable_notification) +function bindings:sendVideo(chat_id, video, reply_to_message_id, duration, caption, disable_notification) - local url = BASE_URL .. '/sendVideo' + local url = self.BASE_URL .. '/sendVideo' local curl_command = 'curl -s "' .. url .. '" -F "chat_id=' .. chat_id .. '" -F "video=@' .. video .. '"' @@ -257,13 +253,13 @@ sendVideo = function(chat_id, video, reply_to_message_id, duration, caption, dis curl_command = curl_command .. ' -F "disable_notification=true"' end - return curlRequest(curl_command) + return bindings.curlRequest(curl_command) end -sendVoice = function(chat_id, voice, reply_to_message_id, duration, disable_notification) +function bindings:sendVoice(chat_id, voice, reply_to_message_id, duration, disable_notification) - local url = BASE_URL .. '/sendVoice' + local url = self.BASE_URL .. '/sendVoice' local curl_command = 'curl -s "' .. url .. '" -F "chat_id=' .. chat_id .. '" -F "voice=@' .. voice .. '"' @@ -279,6 +275,8 @@ sendVoice = function(chat_id, voice, reply_to_message_id, duration, disable_noti curl_command = curl_command .. ' -F "disable_notification=true"' end - return curlRequest(curl_command) + return bindings.curlRequest(curl_command) end + +return bindings diff --git a/bot.lua b/bot.lua index cc8e331..915d8f7 100755 --- a/bot.lua +++ b/bot.lua @@ -1,73 +1,77 @@ -HTTP = require('socket.http') -HTTPS = require('ssl.https') -URL = require('socket.url') -JSON = require('cjson') +local bot = {} -version = '3.5' +local bindings = require('bindings') -- Load Telegram bindings. +local utilities = require('utilities') -- Load miscellaneous and cross-plugin functions. -bot_init = function() -- The function run when the bot is started or reloaded. +bot.version = '3.5' - config = dofile('config.lua') -- Load configuration file. - dofile('bindings.lua') -- Load Telegram bindings. - dofile('utilities.lua') -- Load miscellaneous and cross-plugin functions. +function bot:init() -- The function run when the bot is started or reloaded. + + self.config = require('config') -- Load configuration file. + + self.BASE_URL = 'https://api.telegram.org/bot' .. self.config.bot_api_key + if self.config.bot_api_key == '' then + error('You did not set your bot token in config.lua!') + end -- Fetch bot information. Try until it succeeds. - repeat bot = getMe() until bot - bot = bot.result + repeat self.info = bindings.getMe(self) until self.info + self.info = self.info.result -- Load the "database"! ;) - if not database then - database = load_data(bot.username..'.db') + if not self.database then + self.database = utilities.load_data(self.info.username..'.db') end - plugins = {} -- Load plugins. - for i,v in ipairs(config.plugins) do - local p = dofile('plugins/'..v) - table.insert(plugins, p) + self.plugins = {} -- Load plugins. + for _,v in ipairs(self.config.plugins) do + local p = require('plugins/'..v) + table.insert(self.plugins, p) + if p.init then p.init(self) end end - print('@' .. bot.username .. ', AKA ' .. bot.first_name ..' ('..bot.id..')') + print('@' .. self.info.username .. ', AKA ' .. self.info.first_name ..' ('..self.info.id..')') -- Generate a random seed and "pop" the first random number. :) math.randomseed(os.time()) math.random() - last_update = last_update or 0 -- Set loop variables: Update offset, - last_cron = last_cron or os.date('%M') -- the time of the last cron job, - is_started = true -- and whether or not the bot should be running. - database.users = database.users or {} -- Table to cache userdata. - database.users[tostring(bot.id)] = bot + self.last_update = self.last_update or 0 -- Set loop variables: Update offset, + self.last_cron = self.last_cron or os.date('%M') -- the time of the last cron job, + self.is_started = true -- and whether or not the bot should be running. + self.database.users = self.database.users or {} -- Table to cache userdata. + self.database.users[tostring(self.info.id)] = self.info -- Migration code. Remove in 3.6. - if database.lastfm then - for k,v in pairs(database.lastfm) do - if not database.users[k] then database.users[k] = {} end - database.users[k].lastfm = v + if self.database.lastfm then + for k,v in pairs(self.database.lastfm) do + if not self.database.users[k] then self.database.users[k] = {} end + self.database.users[k].lastfm = v end end -- Migration code. Remove in 3.6. - if database.nicknames then - for k,v in pairs(database.nicknames) do - if not database.users[k] then database.users[k] = {} end - database.users[k].nickname = v + if self.database.nicknames then + for k,v in pairs(self.database.nicknames) do + if not self.database.users[k] then self.database.users[k] = {} end + self.database.users[k].nickname = v end end end -on_msg_receive = function(msg) -- The fn run whenever a message is received. +function bot:on_msg_receive(msg) -- The fn run whenever a message is received. -- Create a user entry if it does not exist. - if not database.users[tostring(msg.from.id)] then - database.users[tostring(msg.from.id)] = {} + if not self.database.users[tostring(msg.from.id)] then + self.database.users[tostring(msg.from.id)] = {} end -- Clear things that no longer exist. - database.users[tostring(msg.from.id)].username = nil - database.users[tostring(msg.from.id)].last_name = nil + self.database.users[tostring(msg.from.id)].username = nil + self.database.users[tostring(msg.from.id)].last_name = nil -- Wee. for k,v in pairs(msg.from) do - database.users[tostring(msg.from.id)][k] = v + self.database.users[tostring(msg.from.id)][k] = v end if msg.date < os.time() - 5 then return end -- Do not process old messages. @@ -78,24 +82,24 @@ on_msg_receive = function(msg) -- The fn run whenever a message is received. end -- If the replied-to message has a caption, make that its text. if msg.text:match('^/start .+') then - msg.text = '/' .. msg.text:input() + msg.text = '/' .. utilities.input(msg.text) end - for i,v in ipairs(plugins) do - for k,w in pairs(v.triggers) do + for _,v in ipairs(self.plugins) do + for _,w in pairs(v.triggers) do if string.match(msg.text:lower(), w) then -- a few shortcuts msg.chat.id_str = tostring(msg.chat.id) msg.from.id_str = tostring(msg.from.id) msg.text_lower = msg.text:lower() - msg.from.name = build_name(msg.from.first_name, msg.from.last_name) + msg.from.name = utilities.build_name(msg.from.first_name, msg.from.last_name) local success, result = pcall(function() - return v.action(msg) + return v.action(self, msg) end) if not success then - sendReply(msg, 'Sorry, an unexpected error occurred.') - handle_exception(result, msg.from.id .. ': ' .. msg.text) + bindings.sendReply(self, msg, 'Sorry, an unexpected error occurred.') + bindings.handle_exception(self, result, msg.from.id .. ': ' .. msg.text) return end -- If the action returns a table, make that table msg. @@ -111,28 +115,30 @@ on_msg_receive = function(msg) -- The fn run whenever a message is received. end -bot_init() -- Actually start the script. Run the bot_init function. +bot.init(bot) -- Actually start the script. Run the bot_init function. -while is_started do -- Start a loop while the bot should be running. +while bot.is_started do -- Start a loop while the bot should be running. - local res = getUpdates(last_update+1) -- Get the latest updates! - if res then - for i,v in ipairs(res.result) do -- Go through every new message. - last_update = v.update_id - on_msg_receive(v.message) + do + local res = bindings.getUpdates(bot, bot.last_update+1) -- Get the latest updates! + if res then + for _,v in ipairs(res.result) do -- Go through every new message. + bot.last_update = v.update_id + bot.on_msg_receive(bot, v.message) + end + else + print(bot.config.errors.connection) end - else - print(config.errors.connection) end - if last_cron ~= os.date('%M') then -- Run cron jobs every minute. - last_cron = os.date('%M') - save_data(bot.username..'.db', database) -- Save the database. - for i,v in ipairs(plugins) do + if bot.last_cron ~= os.date('%M') then -- Run cron jobs every minute. + bot.last_cron = os.date('%M') + utilities.save_data(bot.info.username..'.db', bot.database) -- Save the database. + for i,v in ipairs(bot.plugins) do if v.cron then -- Call each plugin's cron function, if it has one. local res, err = pcall(function() v.cron() end) if not res then - handle_exception(err, 'CRON: ' .. i) + utilities.handle_exception(bot, err, 'CRON: ' .. i) end end end @@ -141,5 +147,5 @@ while is_started do -- Start a loop while the bot should be running. end -- Save the database before exiting. -save_data(bot.username..'.db', database) +utilities.save_data(bot.info.username..'.db', bot.database) print('Halted.') diff --git a/plugins/about.lua b/plugins/about.lua index f57dc28..f64ac50 100755 --- a/plugins/about.lua +++ b/plugins/about.lua @@ -1,26 +1,30 @@ -local command = 'about' -local doc = '`Returns information about the bot.`' +local about = {} -local triggers = { +local bindings = require('bindings') + +about.command = 'about' +about.doc = '`Returns information about the bot.`' + +about.triggers = { '' } -local action = function(msg) +function about:action(msg) -- Filthy hack, but here is where we'll stop forwarded messages from hitting -- other plugins. if msg.forward_from then return end - local message = config.about_text .. '\nBased on @otouto v'..version..' by topkecleon.' + local message = self.config.about_text .. '\nBased on @otouto v'..self.version..' by topkecleon.' - if msg.new_chat_participant and msg.new_chat_participant.id == bot.id then - sendMessage(msg.chat.id, message, true) + if msg.new_chat_participant and msg.new_chat_participant.id == self.info.id then + bindings.sendMessage(self, msg.chat.id, message, true) return - elseif msg.text_lower:match('^/about[@'..bot.username..']*') then - sendMessage(msg.chat.id, message, true) + elseif msg.text_lower:match('^/about[@'..self.info.username..']*') then + bindings.sendMessage(self, msg.chat.id, message, true) return elseif msg.text_lower:match('^/start') then - sendMessage(msg.chat.id, message, true) + bindings.sendMessage(self, msg.chat.id, message, true) return end @@ -28,9 +32,4 @@ local action = function(msg) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return about diff --git a/plugins/administration.lua b/plugins/administration.lua index a92bf9e..3d56316 100644 --- a/plugins/administration.lua +++ b/plugins/administration.lua @@ -25,45 +25,56 @@ ]]-- - -- Build the administration db if nonexistent. -if not database.administration then - database.administration = { - admins = {}, - groups = {}, - activity = {} - } -end +local JSON = require('cjson') +local drua = dofile('drua-tg/drua-tg.lua') +local bindings = require('bindings') +local utilities = require('utilities') -admin_temp = { - help = {}, - flood = {} -} +local administration = {} - -- Migration code: Remove this in v1.8. - -- Most recent group activity is now cached for group listings. -if not database.administration.activity then - database.administration.activity = {} - for k,v in pairs(database.administration.groups) do - table.insert(database.administration.activity, k) +function administration:init() + -- Build the administration db if nonexistent. + if not self.database.administration then + self.database.administration = { + admins = {}, + groups = {}, + activity = {} + } end -end - -- Migration code: Remove this in v1.9. - -- Groups have single governors now. -for k,v in pairs(database.administration.groups) do - if v.govs and table_size(v.govs) > 0 then - for key, val in pairs(v.govs) do - v.governor = key - break + self.admin_temp = { + help = {}, + flood = {} + } + + -- Migration code: Remove this in v1.8. + -- Most recent group activity is now cached for group listings. + if not self.database.administration.activity then + self.database.administration.activity = {} + for k,_ in pairs(self.database.administration.groups) do + table.insert(self.database.administration.activity, k) end end - v.govs = nil + + -- Migration code: Remove this in v1.9. + -- Groups have single governors now. + for _,group in pairs(self.database.administration.groups) do + if group.govs then + for gov, _ in pairs(group.govs) do + group.governor = gov + break + end + end + group.govs = nil + end + + drua.PORT = self.config.cli_port or 4567 + + administration.init_command(self) + end -drua = dofile('drua-tg/drua-tg.lua') -drua.PORT = config.cli_port or 4567 - -local flags = { +administration.flags = { [1] = { name = 'unlisted', desc = 'Removes this group from the group listing.', @@ -104,7 +115,7 @@ local flags = { } } -local antiflood = { +administration.antiflood = { text = 5, voice = 5, audio = 5, @@ -116,7 +127,7 @@ local antiflood = { sticker = 20 } -local ranks = { +administration.ranks = { [0] = 'Banned', [1] = 'Users', [2] = 'Moderators', @@ -125,32 +136,32 @@ local ranks = { [5] = 'Owner' } -local get_rank = function(target, chat) +function administration:get_rank(target, chat) target = tostring(target) if chat then chat = tostring(chat) end - if tonumber(target) == config.admin or tonumber(target) == bot.id then + if tonumber(target) == self.config.admin or tonumber(target) == self.info.id then return 5 end - if database.administration.admins[target] then + if self.database.administration.admins[target] then return 4 end - if chat and database.administration.groups[chat] then - if database.administration.groups[chat].governor == tonumber(target) then + if chat and self.database.administration.groups[chat] then + if self.database.administration.groups[chat].governor == tonumber(target) then return 3 - elseif database.administration.groups[chat].mods[target] then + elseif self.database.administration.groups[chat].mods[target] then return 2 - elseif database.administration.groups[chat].bans[target] then + elseif self.database.administration.groups[chat].bans[target] then return 0 end end - if database.blacklist[target] then + if self.database.blacklist[target] then return 0 end @@ -158,28 +169,28 @@ local get_rank = function(target, chat) end -local get_target = function(msg) +function administration:get_target(msg) - local target = user_from_message(msg) + local target = utilities.user_from_message(self, msg) if target.id then - target.rank = get_rank(target.id, msg.chat.id) + target.rank = administration.get_rank(self, target.id, msg.chat.id) end return target end -local mod_format = function(id) +function administration:mod_format(id) id = tostring(id) - local user = database.users[id] or { first_name = 'Unknown' } - local name = build_name(user.first_name, user.last_name) - name = markdown_escape(name) + local user = self.database.users[id] or { first_name = 'Unknown' } + local name = utilities.build_name(user.first_name, user.last_name) + name = utilities.markdown_escape(name) local output = '• ' .. name .. ' `[' .. id .. ']`\n' return output end -local get_desc = function(chat_id) +function administration:get_desc(chat_id) - local group = database.administration.groups[tostring(chat_id)] + local group = self.database.administration.groups[tostring(chat_id)] local t = {} if group.link then table.insert(t, '*Welcome to* [' .. group.name .. '](' .. group.link .. ')*!*') @@ -197,22 +208,22 @@ local get_desc = function(chat_id) table.insert(t, rulelist:trim()) end local flaglist = '' - for i = 1, #flags do + for i = 1, #administration.flags do if group.flags[i] then - flaglist = flaglist .. '• ' .. flags[i].short .. '\n' + flaglist = flaglist .. '• ' .. administration.flags[i].short .. '\n' end end if flaglist ~= '' then table.insert(t, '*Flags:*\n' .. flaglist:trim()) end if group.governor then - local gov = database.users[tostring(group.governor)] - local s = build_name(gov.first_name, gov.last_name):md_escape() .. ' `[' .. gov.id .. ']`' + local gov = self.database.users[tostring(group.governor)] + local s = utilities.md_escape(utilities.build_name(gov.first_name, gov.last_name)) .. ' `[' .. gov.id .. ']`' table.insert(t, '*Governor:* ' .. s) end local modstring = '' - for k,v in pairs(group.mods) do - modstring = modstring .. mod_format(k) + for k,_ in pairs(group.mods) do + modstring = modstring .. administration.mod_format(self, k) end if modstring ~= '' then table.insert(t, '*Moderators:*\n' .. modstring:trim()) @@ -221,962 +232,896 @@ local get_desc = function(chat_id) end -update_desc = function(chat) - local group = database.administration.groups[tostring(chat)] +function administration:update_desc(chat) + local group = self.database.administration.groups[tostring(chat)] local desc = 'Welcome to ' .. group.name .. '!\n' if group.motd then desc = desc .. group.motd .. '\n' end if group.governor then - local gov = database.users[tostring(group.governor)] - desc = desc .. '\nGovernor: ' .. build_name(gov.first_name, gov.last_name) .. ' [' .. gov.id .. ']\n' + local gov = self.database.users[tostring(group.governor)] + desc = desc .. '\nGovernor: ' .. utilities.build_name(gov.first_name, gov.last_name) .. ' [' .. gov.id .. ']\n' end - local s = '\n/desc@' .. bot.username .. ' for more information.' + local s = '\n/desc@' .. self.info.username .. ' for more information.' desc = desc:sub(1, 250-s:len()) .. s drua.channel_set_about(chat, desc) end -local commands = { +function administration.init_command(self_) + administration.commands = { - { -- antisquig - triggers = { - '[\216-\219][\128-\191]', -- arabic - '‮', -- rtl - '‏', -- other rtl + { -- antisquig + triggers = { + '[\216-\219][\128-\191]', -- arabic + '‮', -- rtl + '‏', -- other rtl + }, + + privilege = 0, + interior = true, + + action = function(self, msg, group) + if administration.get_rank(self, msg.from.id, msg.chat.id) > 1 then + return true + end + if not group.flags[2] then + return true + end + drua.kick_user(msg.chat.id, msg.from.id) + local output = administration.flags[2].kicked:gsub('GROUPNAME', msg.chat.title) + bindings.sendMessage(self, msg.from.id, output) + end }, - privilege = 0, - interior = true, + { -- generic + triggers = { '' }, - action = function(msg, group) - if get_rank(msg.from.id, msg.chat.id) > 1 then - return true - end - if not group.flags[2] then - return true - end - drua.kick_user(msg.chat.id, msg.from.id) - local output = flags[2].kicked:gsub('GROUPNAME', msg.chat.title) - sendMessage(msg.from.id, output) - end - }, + privilege = 0, + interior = true, - { -- generic - triggers = { '' }, + action = function(self, msg, group) - privilege = 0, - interior = true, - - action = function(msg, group) - - local rank = get_rank(msg.from.id, msg.chat.id) - - -- banned - if rank == 0 then - drua.kick_user(msg.chat.id, msg.from.id) - sendMessage(msg.from.id, 'Sorry, you are banned from ' .. msg.chat.title .. '.') - return - end - - if rank < 2 then - - -- antisquig Strict - if group.flags[3] == true then - if msg.from.name:match('[\216-\219][\128-\191]') or msg.from.name:match('‮') or msg.from.name:match('‏') then - drua.kick_user(msg.chat.id, msg.from.id) - local output = flags[3].kicked:gsub('GROUPNAME', msg.chat.title) - sendMessage(msg.from.id, output) - return - end - end - - -- antiflood - if group.flags[5] == true then - if not group.antiflood then - group.antiflood = JSON.decode(JSON.encode(antiflood)) - end - if not admin_temp.flood[msg.chat.id_str] then - admin_temp.flood[msg.chat.id_str] = {} - end - if not admin_temp.flood[msg.chat.id_str][msg.from.id_str] then - admin_temp.flood[msg.chat.id_str][msg.from.id_str] = 0 - end - if msg.sticker then -- Thanks Brazil for discarding switches. - admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.sticker - elseif msg.photo then - admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.photo - elseif msg.document then - admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.document - elseif msg.audio then - admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.audio - elseif msg.contact then - admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.contact - elseif msg.video then - admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.video - elseif msg.location then - admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.location - elseif msg.voice then - admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.voice - else - admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.text - end - if admin_temp.flood[msg.chat.id_str][msg.from.id_str] > 99 then - drua.kick_user(msg.chat.id, msg.from.id) - local output = flags[5].kicked:gsub('GROUPNAME', msg.chat.title) - sendMessage(msg.from.id, output) - admin_temp.flood[msg.chat.id_str][msg.from.id_str] = nil - return - end - end - - end - - if msg.new_chat_participant then - - msg.new_chat_participant.name = build_name(msg.new_chat_participant.first_name, msg.new_chat_participant.last_name) + local rank = administration.get_rank(self, msg.from.id, msg.chat.id) -- banned - if get_rank(msg.new_chat_participant.id, msg.chat.id) == 0 then - drua.kick_user(msg.chat.id, msg.new_chat_participant.id) - sendMessage(msg.new_chat_participant.id, 'Sorry, you are banned from ' .. msg.chat.title .. '.') + if rank == 0 then + drua.kick_user(msg.chat.id, msg.from.id) + bindings.sendMessage(self, msg.from.id, 'Sorry, you are banned from ' .. msg.chat.title .. '.') return end - -- antisquig Strict - if group.flags[3] == true then - if msg.new_chat_participant.name:match('[\216-\219][\128-\191]') or msg.new_chat_participant.name:match('‮') or msg.new_chat_participant.name:match('‏') then + if rank < 2 then + + -- antisquig Strict + if group.flags[3] == true then + if msg.from.name:match('[\216-\219][\128-\191]') or msg.from.name:match('‮') or msg.from.name:match('‏') then + drua.kick_user(msg.chat.id, msg.from.id) + local output = administration.flags[3].kicked:gsub('GROUPNAME', msg.chat.title) + bindings.sendMessage(self, msg.from.id, output) + return + end + end + + -- antiflood + if group.flags[5] == true then + if not group.antiflood then + group.antiflood = JSON.decode(JSON.encode(administration.antiflood)) + end + if not self.admin_temp.flood[msg.chat.id_str] then + self.admin_temp.flood[msg.chat.id_str] = {} + end + if not self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] then + self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] = 0 + end + if msg.sticker then -- Thanks Brazil for discarding switches. + self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] = self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.sticker + elseif msg.photo then + self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] = self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.photo + elseif msg.document then + self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] = self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.document + elseif msg.audio then + self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] = self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.audio + elseif msg.contact then + self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] = self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.contact + elseif msg.video then + self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] = self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.video + elseif msg.location then + self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] = self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.location + elseif msg.voice then + self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] = self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.voice + else + self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] = self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.text + end + if self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] > 99 then + drua.kick_user(msg.chat.id, msg.from.id) + local output = administration.flags[5].kicked:gsub('GROUPNAME', msg.chat.title) + bindings.sendMessage(msg.from.id, output) + self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] = nil + return + end + end + + end + + if msg.new_chat_participant then + + msg.new_chat_participant.name = utilities.build_name(msg.new_chat_participant.first_name, msg.new_chat_participant.last_name) + + -- banned + if administration.get_rank(self, msg.new_chat_participant.id, msg.chat.id) == 0 then drua.kick_user(msg.chat.id, msg.new_chat_participant.id) - local output = flags[3].kicked:gsub('GROUPNAME', msg.chat.title) - sendMessage(msg.new_chat_participant.id, output) + bindings.sendMessage(self, msg.new_chat_participant.id, 'Sorry, you are banned from ' .. msg.chat.title .. '.') return end - end - -- antibot - if msg.new_chat_participant.username and msg.new_chat_participant.username:match('bot$') then - if rank < 2 and group.flags[4] == true then - drua.kick_user(msg.chat.id, msg.new_chat_participant.id) + -- antisquig Strict + if group.flags[3] == true then + if msg.new_chat_participant.name:match('[\216-\219][\128-\191]') or msg.new_chat_participant.name:match('‮') or msg.new_chat_participant.name:match('‏') then + drua.kick_user(msg.chat.id, msg.new_chat_participant.id) + local output = administration.flags[3].kicked:gsub('GROUPNAME', msg.chat.title) + bindings.sendMessage(self, msg.new_chat_participant.id, output) + return + end + end + + -- antibot + if msg.new_chat_participant.username and msg.new_chat_participant.username:match('bot$') then + if rank < 2 and group.flags[4] == true then + drua.kick_user(msg.chat.id, msg.new_chat_participant.id) + return + end + else + local output = administration.get_desc(self, msg.chat.id) + bindings.sendMessage(self, msg.new_chat_participant.id, output, true, nil, true) return end - else - local output = get_desc(msg.chat.id) - sendMessage(msg.new_chat_participant.id, output, true, nil, true) - return - end - elseif msg.new_chat_title then + elseif msg.new_chat_title then - if rank < 3 then - drua.rename_chat(msg.chat.id, group.name) - else - group.name = msg.new_chat_title - if group.grouptype == 'supergroup' then - update_desc(msg.chat.id) - end - end - return - - elseif msg.new_chat_photo then - - if group.grouptype == 'group' then if rank < 3 then - drua.set_photo(msg.chat.id, group.photo) + drua.rename_chat(msg.chat.id, group.name) + else + group.name = msg.new_chat_title + if group.grouptype == 'supergroup' then + administration.update_desc(msg.chat.id) + end + end + return + + elseif msg.new_chat_photo then + + if group.grouptype == 'group' then + if rank < 3 then + drua.set_photo(msg.chat.id, group.photo) + else + group.photo = drua.get_photo(msg.chat.id) + end else group.photo = drua.get_photo(msg.chat.id) end - else - group.photo = drua.get_photo(msg.chat.id) - end - return + return - elseif msg.delete_chat_photo then + elseif msg.delete_chat_photo then - if group.grouptype == 'group' then - if rank < 3 then - drua.set_photo(msg.chat.id, group.photo) + if group.grouptype == 'group' then + if rank < 3 then + drua.set_photo(msg.chat.id, group.photo) + else + group.photo = nil + end else group.photo = nil end - else - group.photo = nil - end - return - - end - - -- Last active time for group listing. - for i,v in pairs(database.administration.activity) do - if v == msg.chat.id_str then - table.remove(database.administration.activity, i) - table.insert(database.administration.activity, 1, msg.chat.id_str) - end - end - - return true - - end - }, - - { -- groups - triggers = { - '^/groups$', - '^/groups@'..bot.username - }, - - command = 'groups', - privilege = 1, - interior = false, - - action = function(msg) - local output = '' - for i,v in ipairs(database.administration.activity) do - local group = database.administration.groups[v] - if not group.flags[1] then -- no unlisted groups - if group.link then - output = output .. '• [' .. group.name .. '](' .. group.link .. ')\n' - else - output = output .. '• ' .. group.name .. '\n' - end - end - end - if output == '' then - output = 'There are currently no listed groups.' - else - output = '*Groups:*\n' .. output - end - sendMessage(msg.chat.id, output, true, nil, true) - end - }, - - { -- ahelp - triggers = { - '^/ahelp$', - '^/ahelp@'..bot.username - }, - - command = 'ahelp', - privilege = 1, - interior = false, - - action = function(msg) - local rank = get_rank(msg.from.id, msg.chat.id) - local output = '*Commands for ' .. ranks[rank] .. ':*\n' - for i = 1, rank do - for ind, val in ipairs(admin_temp.help[i]) do - output = output .. '• /' .. val .. '\n' - end - end - if sendMessage(msg.from.id, output, true, nil, true) then - if msg.from.id ~= msg.chat.id then - sendReply(msg, 'I have sent you the requested information in a private message.') - end - else - sendMessage(msg.chat.id, output, true, nil, true) - end - end - }, - - { -- alist - triggers = { - '^/ops$', - '^/ops@'..bot.username, - '^/oplist$', - '^/oplist@'..bot.username - }, - - command = 'ops', - privilege = 1, - interior = true, - - action = function(msg, group) - local modstring = '' - for k,v in pairs(group.mods) do - modstring = modstring .. mod_format(k) - end - if modstring ~= '' then - modstring = '*Moderators for* _' .. msg.chat.title .. '_ *:*\n' .. modstring - end - local govstring = '' - if group.governor then - local gov = database.users[tostring(group.governor)] - govstring = '*Governor:* ' .. build_name(gov.first_name, gov.last_name):md_escape() .. ' `[' .. gov.id .. ']`' - end - local output = modstring:trim() ..'\n\n' .. govstring:trim() - if output == '\n\n' then - output = 'There are currently no moderators for this group.' - end - sendMessage(msg.chat.id, output, true, nil, true) - end - - }, - - { -- desc - triggers = { - '^/desc[ription]*$', - '^/desc[ription]*@'..bot.username - }, - - command = 'description', - privilege = 1, - interior = true, - - action = function(msg) - local output = get_desc(msg.chat.id) - if sendMessage(msg.from.id, output, true, nil, true) then - if msg.from.id ~= msg.chat.id then - sendReply(msg, 'I have sent you the requested information in a private message.') - end - else - sendMessage(msg.chat.id, output, true, nil, true) - end - end - }, - - { -- rules - triggers = { - '^/rules?', - '^/rules?@'..bot.username - }, - - command = 'rules', - privilege = 1, - interior = true, - - action = function(msg, group) - local output - local input = get_word(msg.text_lower, 2) - input = tonumber(input) - if #group.rules > 0 then - if input and group.rules[input] then - output = '*' .. input .. '.* ' .. group.rules[input] - else - output = '*Rules for* _' .. msg.chat.title .. '_ *:*\n' - for i,v in ipairs(group.rules) do - output = output .. '*' .. i .. '.* ' .. v .. '\n' - end - end - else - output = 'No rules have been set for ' .. msg.chat.title .. '.' - end - sendMessage(msg.chat.id, output, true, nil, true) - end - }, - - { -- motd - triggers = { - '^/motd$', - '^/motd@'..bot.username - }, - - command = 'motd', - privilege = 1, - interior = true, - - action = function(msg, group) - local output = 'No MOTD has been set for ' .. msg.chat.title .. '.' - if group.motd then - output = '*MOTD for* _' .. msg.chat.title .. '_ *:*\n' .. group.motd - end - sendMessage(msg.chat.id, output, true, nil, true) - end - }, - - { -- link - triggers = { - '^/link$', - '^/link@'..bot.username - }, - - command = 'link', - privilege = 1, - interior = true, - - action = function(msg, group) - local output = 'No link has been set for ' .. msg.chat.title .. '.' - if group.link then - output = '[' .. msg.chat.title .. '](' .. group.link .. ')' - end - sendMessage(msg.chat.id, output, true, nil, true) - end - }, - - { -- kick - triggers = { - '^/kick[@'..bot.username..']*' - }, - - command = 'kick ', - privilege = 2, - interior = true, - - action = function(msg) - local target = get_target(msg) - if target.err then - sendReply(msg, target.err) - return - elseif target.rank > 1 then - sendReply(msg, target.name .. ' is too privileged to be kicked.') - return - end - drua.kick_user(msg.chat.id, target.id) - sendMessage(msg.chat.id, target.name .. ' has been kicked.') - end - }, - - { -- ban - triggers = { - '^/ban', - '^/unban' - }, - - command = 'ban ', - privilege = 2, - interior = true, - - action = function(msg, group) - local target = get_target(msg) - if target.err then - sendReply(msg, target.err) - return - end - if target.rank > 1 then - sendReply(msg, target.name .. ' is too privileged to be banned.') - return - end - if group.bans[target.id_str] then - group.bans[target.id_str] = nil - sendReply(msg, target.name .. ' has been unbanned.') - else - group.bans[target.id_str] = true - drua.kick_user(msg.chat.id, target.id) - sendReply(msg, target.name .. ' has been banned.') - end - end - }, - - { -- changerule - triggers = { - '^/changerule', - '^/changerule@' .. bot.username - }, - - command = 'changerule ', - privilege = 3, - interior = true, - - action = function(msg, group) - local usage = 'usage: `/changerule `\n`/changerule -- `deletes.' - local input = msg.text:input() - if not input then - sendMessage(msg.chat.id, usage, true, msg.message_id, true) - return - end - local rule_num = input:match('^%d+') - if not rule_num then - local output = 'Please specify which rule you want to change.\n' .. usage - sendMessage(msg.chat.id, output, true, msg.message_id, true) - return - end - rule_num = tonumber(rule_num) - local rule_new = input:input() - if not rule_new then - local output = 'Please specify the new rule.\n' .. usage - sendMessage(msg.chat.id, output, true, msg.message_id, true) - return - end - if not group.rules then - local output = 'Sorry, there are no rules to change. Please use /setrules.\n' .. usage - sendMessage(msg.chat.id, output, true, msg.message_id, true) - return - end - if not group.rules[rule_num] then - rule_num = #group.rules + 1 - end - if rule_new == '--' or rule_new == '—' then - if group.rules[rule_num] then - table.remove(group.rules, rule_num) - sendReply(msg, 'That rule has been deleted.') - else - sendReply(msg, 'There is no rule with that number.') - end - return - end - group.rules[rule_num] = rule_new - local output = '*' .. rule_num .. '*. ' .. rule_new - sendMessage(msg.chat.id, output, true, nil, true) - end - }, - - { -- setrules - triggers = { - '^/setrules[@'..bot.username..']*' - }, - - command = 'setrules ', - privilege = 3, - interior = true, - - action = function(msg, group) - local input = msg.text:match('^/setrules[@'..bot.username..']*(.+)') - if not input then - sendMessage(msg.chat.id, '```\n/setrules [rule]\n\n[rule]\n...\n```', true, msg.message_id, true) - return - elseif input == ' --' or input == ' —' then - group.rules = {} - sendReply(msg, 'The rules have been cleared.') - return - end - group.rules = {} - input = input:trim() .. '\n' - local output = '*Rules for* _' .. msg.chat.title .. '_ *:*\n' - local i = 1 - for l in input:gmatch('(.-)\n') do - output = output .. '*' .. i .. '.* ' .. l .. '\n' - i = i + 1 - table.insert(group.rules, l:trim()) - end - sendMessage(msg.chat.id, output, true, nil, true) - end - }, - - { -- setmotd - triggers = { - '^/setmotd[@'..bot.username..']*' - }, - - command = 'setmotd ', - privilege = 3, - interior = true, - - action = function(msg, group) - local input = msg.text:input() - if not input then - if msg.reply_to_message and msg.reply_to_message.text then - input = msg.reply_to_message.text - else - sendReply(msg, 'Please specify the new message of the day.') return + + end + + -- Last active time for group listing. + for i,v in pairs(self.database.administration.activity) do + if v == msg.chat.id_str then + table.remove(self.database.administration.activity, i) + table.insert(self.database.administration.activity, 1, msg.chat.id_str) + end + end + + return true + + end + }, + + { -- groups + triggers = utilities.triggers(self_.info.username):t('groups').table, + + command = 'groups', + privilege = 1, + interior = false, + + action = function(self, msg) + local output = '' + for _,v in ipairs(self.database.administration.activity) do + local group = self.database.administration.groups[v] + if not group.flags[1] then -- no unlisted groups + if group.link then + output = output .. '• [' .. group.name .. '](' .. group.link .. ')\n' + else + output = output .. '• ' .. group.name .. '\n' + end + end + end + if output == '' then + output = 'There are currently no listed groups.' + else + output = '*Groups:*\n' .. output + end + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) + end + }, + + { -- ahelp + triggers = utilities.triggers(self_.info.username):t('ahelp').table, + + command = 'ahelp', + privilege = 1, + interior = false, + + action = function(self, msg) + local rank = administration.get_rank(self, msg.from.id, msg.chat.id) + local output = '*Commands for ' .. administration.ranks[rank] .. ':*\n' + for i = 1, rank do + for _, val in ipairs(self.admin_temp.help[i]) do + output = output .. '• /' .. val .. '\n' + end + end + if bindings.sendMessage(self, msg.from.id, output, true, nil, true) then + if msg.from.id ~= msg.chat.id then + bindings.sendReply(self, msg, 'I have sent you the requested information in a private message.') + end + else + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end end - if input == '--' or input == '—' then - group.motd = nil - sendReply(msg, 'The MOTD has been cleared.') - else - input = input:trim() - group.motd = input - local output = '*MOTD for* _' .. msg.chat.title .. '_ *:*\n' .. input - sendMessage(msg.chat.id, output, true, nil, true) - end - if group.grouptype == 'supergroup' then - update_desc(msg.chat.id) - end - end - }, - - { -- setlink - triggers = { - '^/setlink[@'..bot.username..']*' }, - command = 'setlink ', - privilege = 3, - interior = true, + { -- alist + triggers = utilities.triggers(self_.info.username):t('ops'):t('oplist').table, - action = function(msg, group) - local input = msg.text:input() - if not input then - sendReply(msg, 'Please specify the new link.') - return - elseif input == '--' or input == '—' then - group.link = drua.export_link(msg.chat.id) - sendReply(msg, 'The link has been regenerated.') - return + command = 'ops', + privilege = 1, + interior = true, + + action = function(self, msg, group) + local modstring = '' + for k,_ in pairs(group.mods) do + modstring = modstring .. administration.mod_format(self, k) + end + if modstring ~= '' then + modstring = '*Moderators for* _' .. msg.chat.title .. '_ *:*\n' .. modstring + end + local govstring = '' + if group.governor then + local gov = self.database.users[tostring(group.governor)] + govstring = '*Governor:* ' .. utilities.md_escape(utilities.build_name(gov.first_name, gov.last_name)) .. ' `[' .. gov.id .. ']`' + end + local output = modstring:trim() ..'\n\n' .. govstring:trim() + if output == '\n\n' then + output = 'There are currently no moderators for this group.' + end + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end - group.link = input - local output = '[' .. msg.chat.title .. '](' .. input .. ')' - sendMessage(msg.chat.id, output, true, nil, true) - end - }, - { -- alist - triggers = { - '^/alist$', - '^/alist@'..bot.username }, - command = 'alist', - privilege = 3, - interior = true, + { -- desc + triggers = utilities.triggers(self_.info.username):t('desc'):t('description').table, - action = function(msg) - local output = '*Administrators:*\n' - output = output .. mod_format(config.admin):gsub('\n', ' ★\n') - for k,v in pairs(database.administration.admins) do - output = output .. mod_format(k) + command = 'description', + privilege = 1, + interior = true, + + action = function(self, msg) + local output = administration.get_desc(self, msg.chat.id) + if bindings.sendMessage(self, msg.from.id, output, true, nil, true) then + if msg.from.id ~= msg.chat.id then + bindings.sendReply(self, msg, 'I have sent you the requested information in a private message.') + end + else + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) + end end - sendMessage(msg.chat.id, output, true, nil, true) - end - }, - - { -- flags - triggers = { - '^/flags?' }, - command = 'flag ', - privilege = 3, - interior = true, + { -- rules + triggers = utilities.triggers(self_.info.username):t('rules?', true).table, - action = function(msg, group) - local input = msg.text:input() - if input then - input = get_word(input, 1) + command = 'rules', + privilege = 1, + interior = true, + + action = function(self, msg, group) + local output + local input = utilities.get_word(msg.text_lower, 2) input = tonumber(input) - if not input or not flags[input] then input = false end - end - if not input then - local output = '*Flags for* _' .. msg.chat.title .. '_ *:*\n' - for i,v in ipairs(flags) do - local status = group.flags[i] or false - output = output .. '`[' .. i .. ']` *' .. v.name .. '*` = ' .. tostring(status) .. '`\n• ' .. v.desc .. '\n' - end - sendMessage(msg.chat.id, output, true, nil, true) - return - end - local output - if group.flags[input] == true then - group.flags[input] = false - sendReply(msg, flags[input].disabled) - else - group.flags[input] = true - sendReply(msg, flags[input].enabled) - end - end - }, - - { -- antiflood - triggers = { - '^/antiflood' - }, - - command = 'antiflood ', - privilege = 3, - interior = true, - - action = function(msg, group) - if not group.flags[5] then - sendMessage(msg.chat.id, 'antiflood is not enabled. Use `/flag 5` to enable it.', true, nil, true) - return - end - if not group.antiflood then - group.antiflood = JSON.decode(JSON.encode(antiflood)) - end - local input = msg.text_lower:input() - local output - if input then - local key, val = input:match('(%a+) (%d+)') - if not group.antiflood[key] or not tonumber(val) then - output = 'Not a valid message type or number.' + if #group.rules > 0 then + if input and group.rules[input] then + output = '*' .. input .. '.* ' .. group.rules[input] + else + output = '*Rules for* _' .. msg.chat.title .. '_ *:*\n' + for i,v in ipairs(group.rules) do + output = output .. '*' .. i .. '.* ' .. v .. '\n' + end + end else - group.antiflood[key] = val - output = '*' .. key:gsub('^%l', string.upper) .. '* messages are now worth *' .. val .. '* points.' - end - else - output = 'usage: `/antiflood `\nexample: `/antiflood text 5`\nUse this command to configure the point values for each message type. When a user reaches 100 points, he is kicked. The points are reset each minute. The current values are:\n' - for k,v in pairs(group.antiflood) do - output = output .. '*'..k..':* `'..v..'`\n' + output = 'No rules have been set for ' .. msg.chat.title .. '.' end + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end - sendMessage(msg.chat.id, output, true, msg.message_id, true) - end - }, - - { -- mod - triggers = { - '^/mod', - '^/demod' }, - command = 'mod ', - privilege = 3, - interior = true, + { -- motd + triggers = utilities.triggers(self_.info.username):t('motd').table, - action = function(msg, group) - local target = get_target(msg) - if target.err then - sendReply(msg, target.err) - return - end - if group.mods[target.id_str] then - if group.grouptype == 'supergroup' then - drua.channel_set_admin(msg.chat.id, target.id, 0) + command = 'motd', + privilege = 1, + interior = true, + + action = function(self, msg, group) + local output = 'No MOTD has been set for ' .. msg.chat.title .. '.' + if group.motd then + output = '*MOTD for* _' .. msg.chat.title .. '_ *:*\n' .. group.motd end - group.mods[target.id_str] = nil - sendReply(msg, target.name .. ' is no longer a moderator.') - else - if target.rank > 2 then - sendReply(msg, target.name .. ' is greater than a moderator.') + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) + end + }, + + { -- link + triggers = utilities.triggers(self_.info.username):t('link').table, + + command = 'link', + privilege = 1, + interior = true, + + action = function(self, msg, group) + local output = 'No link has been set for ' .. msg.chat.title .. '.' + if group.link then + output = '[' .. msg.chat.title .. '](' .. group.link .. ')' + end + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) + end + }, + + { -- kick + triggers = utilities.triggers(self_.info.username):t('kick', true).table, + + command = 'kick ', + privilege = 2, + interior = true, + + action = function(self, msg) + local target = administration.get_target(self, msg) + if target.err then + bindings.sendReply(self, msg, target.err) + return + elseif target.rank > 1 then + bindings.sendReply(self, msg, target.name .. ' is too privileged to be kicked.') return end - if group.grouptype == 'supergroup' then - drua.channel_set_admin(msg.chat.id, target.id, 2) - end - group.mods[target.id_str] = true - sendReply(msg, target.name .. ' is now a moderator.') + drua.kick_user(msg.chat.id, target.id) + bindings.sendMessage(self, msg.chat.id, target.name .. ' has been kicked.') end - end - }, - - { -- gov - triggers = { - '^/gov', - '^/degov' }, - command = 'gov ', - privilege = 4, - interior = true, + { -- ban + triggers = utilities.triggers(self_.info.username):t('ban', true):t('unban', true).table, - action = function(msg, group) - local target = get_target(msg) - if target.err then - sendReply(msg, target.err) - return + command = 'ban ', + privilege = 2, + interior = true, + + action = function(self, msg, group) + local target = administration.get_target(self, msg) + if target.err then + bindings.sendReply(self, msg, target.err) + return + end + if target.rank > 1 then + bindings.sendReply(self, msg, target.name .. ' is too privileged to be banned.') + return + end + if group.bans[target.id_str] then + group.bans[target.id_str] = nil + bindings.sendReply(self, msg, target.name .. ' has been unbanned.') + else + group.bans[target.id_str] = true + drua.kick_user(msg.chat.id, target.id) + bindings.sendReply(self, msg, target.name .. ' has been banned.') + end end - if group.governor and group.governor == target.id then - if group.grouptype == 'supergroup' then - drua.channel_set_admin(msg.chat.id, target.id, 0) + }, + + { -- changerule + triggers = utilities.triggers(self_.info.username):t('changerule', true).table, + + command = 'changerule ', + privilege = 3, + interior = true, + + action = function(self, msg, group) + local usage = 'usage: `/changerule `\n`/changerule -- `deletes.' + local input = utilities.input(msg.text) + if not input then + bindings.sendMessage(self, msg.chat.id, usage, true, msg.message_id, true) + return end - group.governor = config.admin - sendReply(msg, target.name .. ' is no longer the governor.') - else - if group.grouptype == 'supergroup' then - if group.governor then - drua.channel_set_admin(msg.chat.id, group.governor, 0) + local rule_num = input:match('^%d+') + if not rule_num then + local output = 'Please specify which rule you want to change.\n' .. usage + bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true) + return + end + rule_num = tonumber(rule_num) + local rule_new = utilities.input(input) + if not rule_new then + local output = 'Please specify the new rule.\n' .. usage + bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true) + return + end + if not group.rules then + local output = 'Sorry, there are no rules to change. Please use /setrules.\n' .. usage + bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true) + return + end + if not group.rules[rule_num] then + rule_num = #group.rules + 1 + end + if rule_new == '--' or rule_new == '—' then + if group.rules[rule_num] then + table.remove(group.rules, rule_num) + bindings.sendReply(self, msg, 'That rule has been deleted.') + else + bindings.sendReply(self, msg, 'There is no rule with that number.') end - drua.channel_set_admin(msg.chat.id, target.id, 2) + return end - if target.rank == 2 then + group.rules[rule_num] = rule_new + local output = '*' .. rule_num .. '*. ' .. rule_new + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) + end + }, + + { -- setrules + triggers = utilities.triggers(self_.info.username):t('setrules', true).table, + + command = 'setrules ', + privilege = 3, + interior = true, + + action = function(self, msg, group) + local input = msg.text:match('^/setrules[@'..self.info.username..']*(.+)') + if not input then + bindings.sendMessage(self, msg.chat.id, '```\n/setrules [rule]\n\n[rule]\n...\n```', true, msg.message_id, true) + return + elseif input == ' --' or input == ' —' then + group.rules = {} + bindings.sendReply(self, msg, 'The rules have been cleared.') + return + end + group.rules = {} + input = input:trim() .. '\n' + local output = '*Rules for* _' .. msg.chat.title .. '_ *:*\n' + local i = 1 + for l in input:gmatch('(.-)\n') do + output = output .. '*' .. i .. '.* ' .. l .. '\n' + i = i + 1 + table.insert(group.rules, l:trim()) + end + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) + end + }, + + { -- setmotd + triggers = utilities.triggers(self_.info.username):t('setmotd', true).table, + + command = 'setmotd ', + privilege = 3, + interior = true, + + action = function(self, msg, group) + local input = utilities.input(msg.text) + if not input then + if msg.reply_to_message and msg.reply_to_message.text then + input = msg.reply_to_message.text + else + bindings.sendReply(self, msg, 'Please specify the new message of the day.') + return + end + end + if input == '--' or input == '—' then + group.motd = nil + bindings.sendReply(self, msg, 'The MOTD has been cleared.') + else + input = input:trim() + group.motd = input + local output = '*MOTD for* _' .. msg.chat.title .. '_ *:*\n' .. input + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) + end + if group.grouptype == 'supergroup' then + administration.update_desc(self, msg.chat.id) + end + end + }, + + { -- setlink + triggers = utilities.triggers(self_.info.username):t('setlink', true).table, + + command = 'setlink ', + privilege = 3, + interior = true, + + action = function(self, msg, group) + local input = utilities.input(msg.text) + if not input then + bindings.sendReply(self, msg, 'Please specify the new link.') + return + elseif input == '--' or input == '—' then + group.link = drua.export_link(msg.chat.id) + bindings.sendReply(self, msg, 'The link has been regenerated.') + return + end + group.link = input + local output = '[' .. msg.chat.title .. '](' .. input .. ')' + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) + end + }, + + { -- alist + triggers = utilities.triggers(self_.info.username):t('alist').table, + + command = 'alist', + privilege = 3, + interior = true, + + action = function(self, msg) + local output = '*Administrators:*\n' + output = output .. administration.mod_format(self, self.config.admin):gsub('\n', ' ★\n') + for id,_ in pairs(self.database.administration.admins) do + output = output .. administration.mod_format(self, id) + end + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) + end + }, + + { -- flags + triggers = utilities.triggers(self_.info.username):t('flags?', true).table, + + command = 'flag ', + privilege = 3, + interior = true, + + action = function(self, msg, group) + local input = utilities.input(msg.text) + if input then + input = utilities.get_word(input, 1) + input = tonumber(input) + if not input or not administration.flags[input] then input = false end + end + if not input then + local output = '*Flags for* _' .. msg.chat.title .. '_ *:*\n' + for i,v in ipairs(administration.flags) do + local status = group.flags[i] or false + output = output .. '`[' .. i .. ']` *' .. v.name .. '*` = ' .. tostring(status) .. '`\n• ' .. v.desc .. '\n' + end + bindings.sendMessage(msg.chat.id, output, true, nil, true) + return + end + if group.flags[input] == true then + group.flags[input] = false + bindings.sendReply(self, msg, administration.flags[input].disabled) + else + group.flags[input] = true + bindings.sendReply(self, msg, administration.flags[input].enabled) + end + end + }, + + { -- antiflood + triggers = utilities.triggers(self_.info.username):t('antiflood', true).table, + + command = 'antiflood ', + privilege = 3, + interior = true, + + action = function(self, msg, group) + if not group.flags[5] then + bindings.sendMessage(self, msg.chat.id, 'antiflood is not enabled. Use `/flag 5` to enable it.', true, nil, true) + return + end + if not group.antiflood then + group.antiflood = JSON.decode(JSON.encode(administration.antiflood)) + end + local input = utilities.input(msg.text_lower) + local output + if input then + local key, val = input:match('(%a+) (%d+)') + if not group.antiflood[key] or not tonumber(val) then + output = 'Not a valid message type or number.' + else + group.antiflood[key] = val + output = '*' .. key:gsub('^%l', string.upper) .. '* messages are now worth *' .. val .. '* points.' + end + else + output = 'usage: `/antiflood `\nexample: `/antiflood text 5`\nUse this command to configure the point values for each message type. When a user reaches 100 points, he is kicked. The points are reset each minute. The current values are:\n' + for k,v in pairs(group.antiflood) do + output = output .. '*'..k..':* `'..v..'`\n' + end + end + bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true) + end + }, + + { -- mod + triggers = utilities.triggers(self_.info.username):t('mod', true):t('demod', true).table, + + command = 'mod ', + privilege = 3, + interior = true, + + action = function(self, msg, group) + local target = administration.get_target(self, msg) + if target.err then + bindings.sendReply(self, msg, target.err) + return + end + if group.mods[target.id_str] then + if group.grouptype == 'supergroup' then + drua.channel_set_admin(msg.chat.id, target.id, 0) + end group.mods[target.id_str] = nil + bindings.sendReply(self, msg, target.name .. ' is no longer a moderator.') + else + if target.rank > 2 then + bindings.sendReply(self, msg, target.name .. ' is greater than a moderator.') + return + end + if group.grouptype == 'supergroup' then + drua.channel_set_admin(msg.chat.id, target.id, 2) + end + group.mods[target.id_str] = true + bindings.sendReply(self, msg, target.name .. ' is now a moderator.') end - group.governor = target.id - sendReply(msg, target.name .. ' is the new governor.') end - if group.grouptype == 'supergroup' then - update_desc(msg.chat.id) - end - end - }, - - { -- hammer - triggers = { - '^/hammer', - '^/unhammer' }, - command = 'hammer ', - privilege = 4, - interior = false, + { -- gov + triggers = utilities.triggers(self_.info.username):t('gov', true):t('degov', true).table, - action = function(msg) - local target = get_target(msg) - if target.err then - sendReply(msg, target.err) - return - end - if target.rank > 3 then - sendReply(msg, target.name .. ' is too privileged to be globally banned.') - return - end - if database.blacklist[target.id_str] then - database.blacklist[target.id_str] = nil - sendReply(msg, target.name .. ' has been globally unbanned.') - else - database.blacklist[target.id_str] = true - for k,v in pairs(database.administration.groups) do - drua.kick_user(k, target.id) - end - sendReply(msg, target.name .. ' has been globally banned.') - end - end - }, + command = 'gov ', + privilege = 4, + interior = true, - { -- admin - triggers = { - '^/admin', - '^/deadmin' - }, - - command = 'admin 3 then + bindings.sendReply(self, msg, target.name .. ' is too privileged to be globally banned.') + return + end + if self.database.blacklist[target.id_str] then + self.database.blacklist[target.id_str] = nil + bindings.sendReply(self, msg, target.name .. ' has been globally unbanned.') + else + self.database.blacklist[target.id_str] = true + for k,_ in pairs(self.database.administration.groups) do + drua.kick_user(k, target.id) + end + bindings.sendReply(self, msg, target.name .. ' has been globally banned.') + end + end }, - command = 'gremove \\[chat]', - privilege = 5, - interior = true, + { -- admin + triggers = utilities.triggers(self_.info.username):t('admin', true):t('deadmin', true).table, - action = function(msg) - local input = msg.text:input() or msg.chat.id_str - if database.administration.groups[input] then - database.administration.groups[input] = nil - for i,v in ipairs(database.administration.activity) do - if v == input then - table.remove(database.administration.activity, i) + command = 'admin ', + privilege = 5, + interior = false, + + action = function(self, msg) + local target = administration.get_target(self, msg) + if target.err then + bindings.sendReply(self, msg, target.err) + return + end + if self.database.administration.admins[target.id_str] then + self.database.administration.admins[target.id_str] = nil + bindings.sendReply(self, msg, target.name .. ' is no longer an administrator.') + else + if target.rank == 5 then + bindings.sendReply(self, msg, target.name .. ' is greater than an administrator.') + return + end + for _,group in pairs(self.database.administration.groups) do + group.mods[target.id_str] = nil + end + self.database.administration.admins[target.id_str] = true + bindings.sendReply(self, msg, target.name .. ' is now an administrator.') + end + end + }, + + { -- gadd + triggers = utilities.triggers(self_.info.username):t('gadd').table, + + command = 'gadd', + privilege = 5, + interior = false, + + action = function(self, msg) + if self.database.administration.groups[msg.chat.id_str] then + bindings.sendReply(msg, 'I am already administrating this group.') + return + end + self.database.administration.groups[msg.chat.id_str] = { + mods = {}, + governor = msg.from.id, + bans = {}, + flags = {}, + rules = {}, + grouptype = msg.chat.type, + name = msg.chat.title, + link = drua.export_link(msg.chat.id), + photo = drua.get_photo(msg.chat.id), + founded = os.time() + } + for i,_ in ipairs(administration.flags) do + self.database.administration.groups[msg.chat.id_str].flags[i] = false + end + table.insert(self.database.administration.activity, msg.chat.id_str) + bindings.sendReply(self, msg, 'I am now administrating this group.') + end + }, + + { -- grem + triggers = utilities.triggers(self_.info.username):t('grem', true):t('gremove', true).table, + + command = 'gremove \\[chat]', + privilege = 5, + interior = true, + + action = function(self, msg) + local input = utilities.input(msg.text) or msg.chat.id_str + if self.database.administration.groups[input] then + self.database.administration.groups[input] = nil + for i,v in ipairs(self.database.administration.activity) do + if v == input then + table.remove(self.database.administration.activity, i) + end + end + bindings.sendReply(self, msg, 'I am no longer administrating that group.') + else + bindings.sendReply(self, msg, 'I do not administrate that group.') + end + end + }, + + { -- glist + triggers = utilities.triggers(self_.info.username):t('list', false).table, + + command = 'glist', + privilege = 5, + interior = false, + + action = function(self, msg) + local output = '' + if utilities.table_size(self.database.administration.groups) > 0 then + for k,v in pairs(self.database.administration.groups) do + output = output .. '[' .. utilities.md_escape(v.name) .. '](' .. v.link .. ') `[' .. k .. ']`\n' + if v.governor then + local gov = self.database.users[tostring(v.governor)] + output = output .. '★ ' .. utilities.md_escape(utilities.build_name(gov.first_name, gov.last_name)) .. ' `[' .. gov.id .. ']`\n' + end + end + else + output = 'There are no groups.' + end + if bindings.sendMessage(self, msg.from.id, output, true, nil, true) then + if msg.from.id ~= msg.chat.id then + bindings.sendReply(self, msg, 'I have sent you the requested information in a private message.') end end - sendReply(msg, 'I am no longer administrating that group.') - else - sendReply(msg, 'I do not administrate that group.') end - end - }, - - { -- glist - triggers = { - '^/glist$', - '^/glist@'..bot.username }, - command = 'glist', - privilege = 5, - interior = false, + { -- broadcast + triggers = utilities.triggers(self_.info.username):t('broadcast', true).table, - action = function(msg) - local output = '' - if table_size(database.administration.groups) > 0 then - for k,v in pairs(database.administration.groups) do - output = output .. '[' .. v.name:md_escape() .. '](' .. v.link .. ') `[' .. k .. ']`\n' - if v.governor then - local gov = database.users[tostring(v.governor)] - output = output .. '★ ' .. build_name(gov.first_name, gov.last_name):md_escape() .. ' `[' .. gov.id .. ']`\n' - end + command = 'broadcast ', + privilege = 5, + interior = false, + + action = function(self, msg) + local input = utilities.input(msg.text) + if not input then + bindings.sendReply(self, msg, 'Give me something to broadcast.') + return end - else - output = 'There are no groups.' - end - if sendMessage(msg.from.id, output, true, nil, true) then - if msg.from.id ~= msg.chat.id then - sendReply(msg, 'I have sent you the requested information in a private message.') + input = '*Admin Broadcast:*\n' .. input + for id,_ in pairs(self.database.administration.groups) do + bindings.sendMessage(self, id, input, true, nil, true) end end - end - }, + } - { -- broadcast - triggers = { - '^/broadcast' - }, - - command = 'broadcast ', - privilege = 5, - interior = false, - - action = function(msg) - local input = msg.text:input() - if not input then - sendReply(msg, 'Give me something to broadcast.') - return - end - input = '*Admin Broadcast:*\n' .. input - for k,v in pairs(database.administration.groups) do - sendMessage(k, input, true, nil, true) - end - end } -} + -- Generate trigger table. + administration.triggers = {} + for _, command in ipairs(administration.commands) do + for _, trigger in ipairs(command.triggers) do + table.insert(administration.triggers, trigger) + end + end - -- Generate trigger table. -local triggers = {} -for i,v in ipairs(commands) do - for ind, val in ipairs(v.triggers) do - table.insert(triggers, val) + self_.database.administration.help = {} + for i,_ in ipairs(administration.ranks) do + self_.admin_temp.help[i] = {} + end + for _,v in ipairs(administration.commands) do + if v.command then + table.insert(self_.admin_temp.help[v.privilege], v.command) + end end end -database.administration.help = {} -for i,v in ipairs(ranks) do - admin_temp.help[i] = {} -end -for i,v in ipairs(commands) do - if v.command then - table.insert(admin_temp.help[v.privilege], v.command) - end -end - -local action = function(msg) - for i,v in ipairs(commands) do - for key,val in pairs(v.triggers) do - if msg.text_lower:match(val) then - if v.interior and not database.administration.groups[msg.chat.id_str] then +function administration:action(msg) + for _,command in ipairs(administration.commands) do + for _,trigger in pairs(command.triggers) do + if msg.text_lower:match(trigger) then + if command.interior and not self.database.administration.groups[msg.chat.id_str] then break end - if get_rank(msg.from.id, msg.chat.id) < v.privilege then + if administration.get_rank(self, msg.from.id, msg.chat.id) < command.privilege then break end - local res = v.action(msg, database.administration.groups[msg.chat.id_str]) + local res = command.action(self, msg, self.database.administration.groups[msg.chat.id_str]) if res ~= true then return res end @@ -1186,17 +1131,11 @@ local action = function(msg) return true end -local cron = function() - admin_temp.flood = {} +function administration:cron() + self.temp.flood = {} end -local command = 'groups' -local doc = '`Returns a list of administrated groups.\nUse /ahelp for more administrative commands.`' +administration.command = 'groups' +administration.doc = '`Returns a list of administrated groups.\nUse /ahelp for more administrative commands.`' -return { - action = action, - triggers = triggers, - cron = cron, - doc = doc, - command = command -} +return administration diff --git a/plugins/apod.lua b/plugins/apod.lua index ee6c90a..f8c56db 100755 --- a/plugins/apod.lua +++ b/plugins/apod.lua @@ -1,5 +1,13 @@ -local command = 'apod [date]' -local doc = [[``` +local apod = {} + +local HTTPS = require('ssl.https') +local JSON = require('cjson') +local URL = require('socket.url') +local bindings = require('bindings') +local utilities = require('utilities') + +apod.command = 'apod [date]' +apod.doc = [[``` /apod [query] Returns the Astronomy Picture of the Day. If the query is a date, in the format YYYY-MM-DD, the APOD of that day is returned. @@ -10,31 +18,29 @@ Returns the explanation of the APOD. Source: nasa.gov ```]] -local triggers = { - '^/apod[@'..bot.username..']*', - '^/apodhd[@'..bot.username..']*', - '^/apodtext[@'..bot.username..']*' -} +function apod:init() + apod.triggers = utilities.triggers(self.info.username) + :t('apod', true):t('apodhd', true):t('apodtext', true).table +end -local action = function(msg) +function apod:action(msg) - if not config.nasa_api_key then - config.nasa_api_key = 'DEMO_KEY' + if not self.config.nasa_api_key then + self.config.nasa_api_key = 'DEMO_KEY' end - local input = msg.text:input() - local caption = '' + local input = utilities.input(msg.text) local date = '*' local disable_page_preview = false - local url = 'https://api.nasa.gov/planetary/apod?api_key=' .. config.nasa_api_key + local url = 'https://api.nasa.gov/planetary/apod?api_key=' .. self.config.nasa_api_key if input then if input:match('(%d+)%-(%d+)%-(%d+)$') then url = url .. '&date=' .. URL.escape(input) date = date .. input else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, apod.doc, true, msg.message_id, true) return end else @@ -45,14 +51,14 @@ local action = function(msg) local jstr, res = HTTPS.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) if jdat.error then - sendReply(msg, config.errors.results) + bindings.sendReply(msg, self.config.errors.results) return end @@ -62,7 +68,7 @@ local action = function(msg) img_url = jdat.hdurl or jdat.url end - output = date .. '[' .. jdat.title .. '](' .. img_url .. ')' + local output = date .. '[' .. jdat.title .. '](' .. img_url .. ')' if string.match(msg.text, '^/apodtext*') then output = output .. '\n' .. jdat.explanation @@ -73,13 +79,8 @@ local action = function(msg) output = output .. '\nCopyright: ' .. jdat.copyright end - sendMessage(msg.chat.id, output, disable_page_preview, nil, true) + bindings.sendMessage(self, msg.chat.id, output, disable_page_preview, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return apod diff --git a/plugins/bandersnatch.lua b/plugins/bandersnatch.lua index 5950ebe..0411494 100755 --- a/plugins/bandersnatch.lua +++ b/plugins/bandersnatch.lua @@ -1,13 +1,17 @@ -local command = 'bandersnatch' -local doc = [[``` +local bandersnatch = {} + +local bindings = require('bindings') +local utilities = require('utilities') + +bandersnatch.command = 'bandersnatch' +bandersnatch.doc = [[``` Shun the frumious Bandersnatch. Alias: /bc ```]] -local triggers = { - '^/bandersnatch[@'..bot.username..']*', - '^/bc[@'..bot.username..']*' -} +function bandersnatch:init() + bandersnatch.triggers = utilities.triggers(self.info.username):trigger('bandersnatch'):trigger('bc').table +end local fullnames = { "Wimbledon Tennismatch", "Rinkydink Curdlesnoot", "Butawhiteboy Cantbekhan", "Benadryl Claritin", "Bombadil Rivendell", "Wanda's Crotchfruit", "Biblical Concubine", "Syphilis Cankersore", "Buckminster Fullerene", "Bourgeoisie Capitalist" } @@ -15,7 +19,7 @@ local firstnames = { "Bumblebee", "Bandersnatch", "Broccoli", "Rinkydink", "Bomb local lastnames = { "Coddleswort", "Crumplesack", "Curdlesnoot", "Calldispatch", "Humperdinck", "Rivendell", "Cuttlefish", "Lingerie", "Vegemite", "Ampersand", "Cumberbund", "Candycrush", "Clombyclomp", "Cragglethatch", "Nottinghill", "Cabbagepatch", "Camouflage","Creamsicle", "Curdlemilk", "Upperclass", "Frumblesnatch", "Crumplehorn", "Talisman", "Candlestick", "Chesterfield", "Bumbersplat", "Scratchnsniff", "Snugglesnatch", "Charizard", "Carrotstick", "Cumbercooch", "Crackerjack", "Crucifix", "Cuckatoo", "Cockletit", "Collywog", "Capncrunch", "Covergirl", "Cumbersnatch", "Countryside","Coggleswort", "Splishnsplash", "Copperwire", "Animorph", "Curdledmilk", "Cheddarcheese", "Cottagecheese", "Crumplehorn", "Snickersbar", "Banglesnatch", "Stinkyrash", "Cameltoe", "Chickenbroth", "Concubine", "Candygram", "Moldyspore", "Chuckecheese", "Cankersore", "Crimpysnitch", "Wafflesmack", "Chowderpants", "Toodlesnoot", "Clavichord", "Cuckooclock", "Oxfordshire", "Cumbersome", "Chickenstrips", "Battleship", "Commonwealth", "Cunningsnatch", "Custardbath", "Kryptonite", "Curdlesnoot", "Cummerbund", "Coochyrash", "Crackerdong", "Crackerdong", "Curdledong", "Crackersprout", "Crumplebutt", "Colonist", "Coochierash", "Thundersnatch" } -local action = function(msg) +function bandersnatch:action(msg) local message @@ -25,13 +29,8 @@ local action = function(msg) message = firstnames[math.random(#firstnames)] .. ' ' .. lastnames[math.random(#lastnames)] end - sendReply(msg, message) + bindings.sendReply(self, msg, message) end -return { - action = action, - triggers = triggers, - command = command, - desc = desc -} +return bandersnatch diff --git a/plugins/bible.lua b/plugins/bible.lua index 03aca67..a556d48 100755 --- a/plugins/bible.lua +++ b/plugins/bible.lua @@ -1,54 +1,54 @@ -if not config.biblia_api_key then - print('Missing config value: biblia_api_key.') - print('bible.lua will not be enabled.') - return +local bible = {} + +local HTTP = require('socket.http') +local URL = require('socket.url') +local bindings = require('bindings') +local utilities = require('utilities') + +function bible:init() + if not self.config.biblia_api_key then + print('Missing config value: biblia_api_key.') + print('bible.lua will not be enabled.') + return + end + + bible.triggers = utilities.triggers(self.info.username):t('bible', true):t('b', true).table end -local command = 'bible ' -local doc = [[``` +bible.command = 'bible ' +bible.doc = [[``` /bible Returns a verse from the American Standard Version of the Bible, or an apocryphal verse from the King James Version. Results from biblia.com. Alias: /b ```]] -local triggers = { - '^/bible*[@'..bot.username..']*', - '^/b[@'..bot.username..']* ', - '^/b[@'..bot.username..']*$' -} +function bible:action(msg) -local action = function(msg) - - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, self.doc, true, msg.message_id, true) return end - local url = 'http://api.biblia.com/v1/bible/content/ASV.txt?key=' .. config.biblia_api_key .. '&passage=' .. URL.escape(input) + local url = 'http://api.biblia.com/v1/bible/content/ASV.txt?key=' .. self.config.biblia_api_key .. '&passage=' .. URL.escape(input) local message, res = HTTP.request(url) if not message or res ~= 200 or message:len() == 0 then - url = 'http://api.biblia.com/v1/bible/content/KJVAPOC.txt?key=' .. config.biblia_api_key .. '&passage=' .. URL.escape(input) + url = 'http://api.biblia.com/v1/bible/content/KJVAPOC.txt?key=' .. self.config.biblia_api_key .. '&passage=' .. URL.escape(input) message, res = HTTP.request(url) end if not message or res ~= 200 or message:len() == 0 then - message = config.errors.results + message = self.config.errors.results end if message:len() > 4000 then message = 'The text is too long to post here. Try being more specific.' end - sendReply(msg, message) + bindings.sendReply(self, msg, message) end -return { - action = action, - triggers = triggers, - command = command, - doc = doc -} +return bible diff --git a/plugins/blacklist.lua b/plugins/blacklist.lua index 9af0ed5..4a77457 100755 --- a/plugins/blacklist.lua +++ b/plugins/blacklist.lua @@ -1,24 +1,31 @@ -- This plugin will allow the admin to blacklist users who will be unable to -- use the bot. This plugin should be at the top of your plugin list in config. -if not database.blacklist then - database.blacklist = {} +local blacklist = {} + +local bindings = require('bindings') +local utilities = require('utilities') + +function blacklist:init() + if not self.database.blacklist then + self.database.blacklist = {} + end end -local triggers = { +blacklist.triggers = { '' } - local action = function(msg) +function blacklist:action(msg) - if database.blacklist[msg.from.id_str] then return end - if database.blacklist[msg.chat.id_str] then return end + if self.database.blacklist[msg.from.id_str] then return end + if self.database.blacklist[msg.chat.id_str] then return end if not msg.text:match('^/blacklist') then return true end - if msg.from.id ~= config.admin then return end + if msg.from.id ~= self.config.admin then return end - local target = user_from_message(msg) + local target = utilities.user_from_message(self, msg) if target.err then - sendReply(msg, target.err) + bindings.sendReply(self, msg, target.err) return end @@ -26,17 +33,14 @@ local triggers = { target.name = 'Group' end - if database.blacklist[tostring(target.id)] then - database.blacklist[tostring(target.id)] = nil - sendReply(msg, target.name .. ' has been removed from the blacklist.') + if self.database.blacklist[tostring(target.id)] then + self.database.blacklist[tostring(target.id)] = nil + bindings.sendReply(self, msg, target.name .. ' has been removed from the blacklist.') else - database.blacklist[tostring(target.id)] = true - sendReply(msg, target.name .. ' has been added to the blacklist.') + self.database.blacklist[tostring(target.id)] = true + bindings.sendReply(self, msg, target.name .. ' has been added to the blacklist.') end end - return { - action = action, - triggers = triggers -} + return blacklist diff --git a/plugins/calc.lua b/plugins/calc.lua index 0d854d1..53a5bfd 100755 --- a/plugins/calc.lua +++ b/plugins/calc.lua @@ -1,21 +1,28 @@ -local command = 'calc ' -local doc = [[``` +local calc = {} + +local URL = require('socket.url') +local HTTPS = require('ssl.https') +local bindings = require('bindings') +local utilities = require('utilities') + +calc.command = 'calc ' +calc.doc = [[``` /calc Returns solutions to mathematical expressions and conversions between common units. Results provided by mathjs.org. ```]] -local triggers = { - '^/calc[@'..bot.username..']*' -} +function calc:init() + calc.triggers = utilities.triggers(self.info.username):t('calc', true).table +end -local action = function(msg) +function calc:action(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(msg.chat.id, calc.doc, true, msg.message_id, true) return end end @@ -24,19 +31,14 @@ local action = function(msg) local output = HTTPS.request(url) if not output then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end output = '`' .. output .. '`' - sendMessage(msg.chat.id, output, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true) end -return { - action = action, - triggers = triggers, - command = command, - doc = doc -} +return calc diff --git a/plugins/cats.lua b/plugins/cats.lua index 53a15c6..d72f885 100755 --- a/plugins/cats.lua +++ b/plugins/cats.lua @@ -1,38 +1,39 @@ -if not config.thecatapi_key then - print('Missing config value: thecatapi_key.') - print('cats.lua will be enabled, but there are more features with a key.') +local cats = {} + +local HTTP = require('socket.http') +local bindings = require('bindings') +local utilities = require('utilities') + +function bindings:init() + if not self.config.thecatapi_key then + print('Missing config value: thecatapi_key.') + print('cats.lua will be enabled, but there are more features with a key.') + end end -local command = 'cat' -local doc = '`Returns a cat!`' +cats.command = 'cat' +cats.doc = '`Returns a cat!`' -local triggers = { - '^/cat[@'..bot.username..']*$' -} +cats.triggers = utilities.triggers():t('cat') -local action = function(msg) +function cats:action(msg) local url = 'http://thecatapi.com/api/images/get?format=html&type=jpg' - if config.thecatapi_key then - url = url .. '&api_key=' .. config.thecatapi_key + if self.config.thecatapi_key then + url = url .. '&api_key=' .. self.config.thecatapi_key end local str, res = HTTP.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(msg, self.config.errors.connection) return end str = str:match('') local output = '[Cat!]('..str..')' - sendMessage(msg.chat.id, output, false, nil, true) + bindings.sendMessage(self, msg.chat.id, output, false, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return cats diff --git a/plugins/dice.lua b/plugins/dice.lua index 7ae3345..0da32f5 100755 --- a/plugins/dice.lua +++ b/plugins/dice.lua @@ -10,7 +10,7 @@ local triggers = { local action = function(msg) - local input = msg.text_lower:input() + local input = utilities.input(msg.text_lower) if not input then sendMessage(msg.chat.id, doc, true, msg.message_id, true) return diff --git a/plugins/dilbert.lua b/plugins/dilbert.lua index 2511da0..5b53b70 100644 --- a/plugins/dilbert.lua +++ b/plugins/dilbert.lua @@ -16,7 +16,7 @@ local action = function(msg) sendChatAction(msg.chat.id, 'upload_photo') - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then input = os.date('%F') end if not input:match('^%d%d%d%d%-%d%d%-%d%d$') then input = os.date('%F') end diff --git a/plugins/echo.lua b/plugins/echo.lua index c52d78b..d0e5731 100755 --- a/plugins/echo.lua +++ b/plugins/echo.lua @@ -10,7 +10,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then sendMessage(msg.chat.id, doc, true, msg.message_id, true) diff --git a/plugins/gImages.lua b/plugins/gImages.lua index f01c233..99c8c88 100755 --- a/plugins/gImages.lua +++ b/plugins/gImages.lua @@ -27,7 +27,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text diff --git a/plugins/gMaps.lua b/plugins/gMaps.lua index b2acc34..1b49d8c 100755 --- a/plugins/gMaps.lua +++ b/plugins/gMaps.lua @@ -13,7 +13,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text diff --git a/plugins/gSearch.lua b/plugins/gSearch.lua index 23f9c2b..bf906e9 100755 --- a/plugins/gSearch.lua +++ b/plugins/gSearch.lua @@ -14,7 +14,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text diff --git a/plugins/hearthstone.lua b/plugins/hearthstone.lua index 8370702..9de002d 100755 --- a/plugins/hearthstone.lua +++ b/plugins/hearthstone.lua @@ -96,7 +96,7 @@ end local action = function(msg) - local input = msg.text_lower:input() + local input = utilities.input(msg.text_lower) if not input then sendMessage(msg.chat.id, doc, true, msg.message_id, true) return diff --git a/plugins/help.lua b/plugins/help.lua index c0589dd..155689a 100755 --- a/plugins/help.lua +++ b/plugins/help.lua @@ -22,7 +22,7 @@ local triggers = { local action = function(msg) - local input = msg.text_lower:input() + local input = utilities.input(msg.text_lower) -- Attempts to send the help message via PM. -- If msg is from a group, it tells the group whether the PM was successful. diff --git a/plugins/imdb.lua b/plugins/imdb.lua index 45cb543..d5756b0 100755 --- a/plugins/imdb.lua +++ b/plugins/imdb.lua @@ -10,7 +10,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text diff --git a/plugins/lastfm.lua b/plugins/lastfm.lua index ee07874..49f52fe 100755 --- a/plugins/lastfm.lua +++ b/plugins/lastfm.lua @@ -24,7 +24,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if string.match(msg.text, '^/lastfm') then sendMessage(msg.chat.id, doc, true, msg.message_id, true) diff --git a/plugins/librefm.lua b/plugins/librefm.lua index 32e0b97..ddd5d96 100644 --- a/plugins/librefm.lua +++ b/plugins/librefm.lua @@ -19,7 +19,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if string.match(msg.text, '^/librefm') then sendMessage(msg.chat.id, doc, true, msg.message_id, true) diff --git a/plugins/luarun.lua b/plugins/luarun.lua index a4cd585..e56a912 100644 --- a/plugins/luarun.lua +++ b/plugins/luarun.lua @@ -8,7 +8,7 @@ local action = function(msg) return end - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then sendReply(msg, 'Please enter a string to load.') return diff --git a/plugins/me.lua b/plugins/me.lua index 68ece71..9c7c62e 100644 --- a/plugins/me.lua +++ b/plugins/me.lua @@ -7,7 +7,7 @@ local action = function(msg) local target = database.users[msg.from.id_str] - if msg.from.id == config.admin and (msg.reply_to_message or msg.text:input()) then + if msg.from.id == config.admin and (msg.reply_to_message or utilities.input(msg.text)) then target = user_from_message(msg) if target.err then sendReply(msg, target.err) diff --git a/plugins/moderation.lua b/plugins/moderation.lua index c8be00b..182f5b4 100755 --- a/plugins/moderation.lua +++ b/plugins/moderation.lua @@ -59,7 +59,7 @@ local commands = { ['^/modcast[@'..bot.username..']*'] = function(msg) - local output = msg.text:input() + local output = utilities.input(msg.text) if not output then return 'You must include a message.' end @@ -149,7 +149,7 @@ local commands = { return config.moderation.errors.not_admin end - local modid = msg.text:input() + local modid = utilities.input(msg.text) if not modid then if msg.reply_to_message then @@ -184,7 +184,7 @@ local commands = { end end - local userid = msg.text:input() + local userid = utilities.input(msg.text) local usernm = userid if msg.reply_to_message then @@ -216,7 +216,7 @@ local commands = { end end - local userid = msg.text:input() + local userid = utilities.input(msg.text) local usernm = userid if msg.reply_to_message then diff --git a/plugins/nick.lua b/plugins/nick.lua index d8b97a1..74b6b71 100755 --- a/plugins/nick.lua +++ b/plugins/nick.lua @@ -22,7 +22,7 @@ local action = function(msg) end local output - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then if database.users[target.id_str].nickname then output = target.name .. '\'s nickname is "' .. database.users[target.id_str].nickname .. '".' diff --git a/plugins/pokedex.lua b/plugins/pokedex.lua index 2a7e57a..1b06c9b 100755 --- a/plugins/pokedex.lua +++ b/plugins/pokedex.lua @@ -12,7 +12,7 @@ local triggers = { local action = function(msg) - local input = msg.text_lower:input() + local input = utilities.input(msg.text_lower) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text diff --git a/plugins/preview.lua b/plugins/preview.lua index 234a7bd..8ba335c 100644 --- a/plugins/preview.lua +++ b/plugins/preview.lua @@ -10,7 +10,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then sendMessage(msg.chat.id, doc, true, nil, true) diff --git a/plugins/reddit.lua b/plugins/reddit.lua index 7d8a16e..037a14c 100755 --- a/plugins/reddit.lua +++ b/plugins/reddit.lua @@ -15,12 +15,12 @@ local triggers = { local action = function(msg) msg.text_lower = msg.text_lower:gsub('/r/', '/r r/') - local input = msg.text_lower:input() + local input = utilities.input(msg.text_lower) if msg.text_lower:match('^/r/') then msg.text_lower = msg.text_lower:gsub('/r/', '/r r/') input = get_word(msg.text_lower, 1) else - input = msg.text_lower:input() + input = utilities.input(msg.text_lower) end local url diff --git a/plugins/setandget.lua b/plugins/setandget.lua index 79245cf..b34b52a 100644 --- a/plugins/setandget.lua +++ b/plugins/setandget.lua @@ -15,7 +15,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) database.setandget[msg.chat.id_str] = database.setandget[msg.chat.id_str] or {} if msg.text_lower:match('^/set') then @@ -26,7 +26,7 @@ local action = function(msg) end local name = get_word(input:lower(), 1) - local value = input:input() + local value = utilities.input(input) if not name or not value then sendMessage(msg.chat.id, doc, true, nil, true) diff --git a/plugins/shell.lua b/plugins/shell.lua index 5c218aa..1622d08 100644 --- a/plugins/shell.lua +++ b/plugins/shell.lua @@ -8,7 +8,7 @@ local action = function(msg) return end - local input = msg.text:input() + local input = utilities.input(msg.text) input = input:gsub('—', '--') if not input then diff --git a/plugins/shout.lua b/plugins/shout.lua index 24c2f3e..873d7ac 100644 --- a/plugins/shout.lua +++ b/plugins/shout.lua @@ -10,7 +10,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then sendMessage(msg.chat.id, doc, true, msg.message_id, true) diff --git a/plugins/slap.lua b/plugins/slap.lua index 3e9c894..819df66 100755 --- a/plugins/slap.lua +++ b/plugins/slap.lua @@ -94,7 +94,7 @@ local slaps = { local action = function(msg) - local victim = msg.text:input() + local victim = utilities.input(msg.text) if msg.reply_to_message then if database.users[tostring(msg.reply_to_message.from.id)].nickname then victim = database.users[tostring(msg.reply_to_message.from.id)].nickname diff --git a/plugins/time.lua b/plugins/time.lua index 1accc2e..05c7c2b 100755 --- a/plugins/time.lua +++ b/plugins/time.lua @@ -10,7 +10,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text diff --git a/plugins/translate.lua b/plugins/translate.lua index b955be6..2be913b 100755 --- a/plugins/translate.lua +++ b/plugins/translate.lua @@ -11,7 +11,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text diff --git a/plugins/urbandictionary.lua b/plugins/urbandictionary.lua index 9cbef94..9b2f94d 100755 --- a/plugins/urbandictionary.lua +++ b/plugins/urbandictionary.lua @@ -14,7 +14,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text diff --git a/plugins/weather.lua b/plugins/weather.lua index 3f42618..8199624 100755 --- a/plugins/weather.lua +++ b/plugins/weather.lua @@ -16,7 +16,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text diff --git a/plugins/wikipedia.lua b/plugins/wikipedia.lua index 4d94f57..4dfd882 100755 --- a/plugins/wikipedia.lua +++ b/plugins/wikipedia.lua @@ -14,7 +14,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text diff --git a/plugins/xkcd.lua b/plugins/xkcd.lua index 9e4ac97..a8c0903 100755 --- a/plugins/xkcd.lua +++ b/plugins/xkcd.lua @@ -10,7 +10,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) local jstr, res = HTTP.request('http://xkcd.com/info.0.json') if res ~= 200 then diff --git a/plugins/youtube.lua b/plugins/youtube.lua index b1e6b10..0bbbe49 100755 --- a/plugins/youtube.lua +++ b/plugins/youtube.lua @@ -21,7 +21,7 @@ local triggers = { local action = function(msg) - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text diff --git a/utilities.lua b/utilities.lua index 2e5fe94..8527602 100755 --- a/utilities.lua +++ b/utilities.lua @@ -1,13 +1,17 @@ -- utilities.lua -- Functions shared among plugins. - -- you're welcome, brayden :^) -HTTP = HTTP or require('socket.http') -HTTPS = HTTPS or require('ssl.https') -JSON = JSON or require('cjson') +local utilities = {} + +local HTTP = require('socket.http') +local ltn12 = require('ltn12') +local HTTPS = require('ssl.https') +local URL = require('socket.url') +local JSON = require('cjson') +local bindings = require('bindings') -- get the indexed word in a string -get_word = function(s, i) +function utilities.get_word(s, i) s = s or '' i = i or 1 @@ -23,7 +27,7 @@ end -- Like get_word(), but better. -- Returns the actual index. -function string:index() +function utilities.index(s) local t = {} for w in s:gmatch('%g+') do table.insert(t, w) @@ -32,16 +36,16 @@ function string:index() end -- Returns the string after the first space. -function string:input() - if not self:find(' ') then +function utilities.input(s) + if not s:find(' ') then return false end - return self:sub(self:find(' ')+1) + return s:sub(s:find(' ')+1) end -- I swear, I copied this from PIL, not yago! :) -function string:trim() -- Trims whitespace from a string. - local s = self:gsub('^%s*(.-)%s*$', '%1') +function utilities.trim(str) -- Trims whitespace from a string. + local s = str:gsub('^%s*(.-)%s*$', '%1') return s end @@ -75,7 +79,7 @@ local lc_list = { } -- Replaces letters with corresponding Cyrillic characters. -latcyr = function(str) +function utilities.latcyr(str) for k,v in pairs(lc_list) do str = str:gsub(k, v) end @@ -83,7 +87,7 @@ latcyr = function(str) end -- Loads a JSON file as a table. -load_data = function(filename) +function utilities.load_data(filename) local f = io.open(filename) if not f then @@ -98,7 +102,7 @@ load_data = function(filename) end -- Saves a table to a JSON file. -save_data = function(filename, data) +function utilities.save_data(filename, data) local s = JSON.encode(data) local f = io.open(filename, 'w') @@ -108,18 +112,18 @@ save_data = function(filename, data) end -- Gets coordinates for a location. Used by gMaps.lua, time.lua, weather.lua. -get_coords = function(input) +function utilities:get_coords(input) local url = 'http://maps.googleapis.com/maps/api/geocode/json?address=' .. URL.escape(input) local jstr, res = HTTP.request(url) if res ~= 200 then - return config.errors.connection + return self.config.errors.connection end local jdat = JSON.decode(jstr) if jdat.status == 'ZERO_RESULTS' then - return config.errors.results + return self.config.errors.results end return { @@ -130,10 +134,10 @@ get_coords = function(input) end -- Get the number of values in a key/value table. -table_size = function(tab) +function utilities.table_size(tab) local i = 0 - for k,v in pairs(tab) do + for _,_ in pairs(tab) do i = i + 1 end return i @@ -141,7 +145,7 @@ table_size = function(tab) end -- Just an easy way to get a user's full name. -build_name = function(first, last) +function utilities.build_name(first, last) if last then return first .. ' ' .. last else @@ -149,10 +153,10 @@ build_name = function(first, last) end end -resolve_username = function(input) +function utilities:resolve_username(input) input = input:gsub('^@', '') - for k,v in pairs(database.users) do + for _,v in pairs(self.database.users) do if v.username and v.username:lower() == input:lower() then return v end @@ -160,22 +164,22 @@ resolve_username = function(input) end -user_from_message = function(msg) +function utilities:user_from_message(msg) - local input = msg.text_lower:input() + local input = utilities.input(msg.text_lower) local target = {} if msg.reply_to_message then target = msg.reply_to_message.from elseif input and tonumber(input) then target.id = input - if database.users[input] then - for k,v in pairs(database.users[input]) do + if self.database.users[input] then + for k,v in pairs(self.database.users[input]) do target[k] = v end end elseif input and input:match('^@') then local uname = input:gsub('^@', '') - for k,v in pairs(database.users) do + for _,v in pairs(self.database.users) do if v.username and uname == v.username:lower() then for key, val in pairs(v) do target[key] = val @@ -195,21 +199,21 @@ user_from_message = function(msg) if not target.first_name then target.first_name = 'User' end - target.name = build_name(target.first_name, target.last_name) + target.name = utilities.build_name(target.first_name, target.last_name) return target end -handle_exception = function(err, message) +function utilities:handle_exception(err, message) if not err then err = '' end - local output = '\n[' .. os.date('%F %T', os.time()) .. ']\n' .. bot.username .. ': ' .. err .. '\n' .. message .. '\n' + local output = '\n[' .. os.date('%F %T', os.time()) .. ']\n' .. self.info.username .. ': ' .. err .. '\n' .. message .. '\n' - if config.log_chat then + if self.config.log_chat then output = '```' .. output .. '```' - sendMessage(config.log_chat, output, true, nil, true) + bindings.sendMessage(self, self.config.log_chat, output, true, nil, true) else print(output) end @@ -218,7 +222,7 @@ end -- Okay, this one I actually did copy from yagop. -- https://github.com/yagop/telegram-bot/blob/master/bot/utils.lua -download_file = function(url, filename) +function utilities.download_file(url, filename) local respbody = {} local options = { @@ -227,7 +231,7 @@ download_file = function(url, filename) redirect = true } - local response = nil + local response if url:match('^https') then options.redirect = false @@ -252,7 +256,7 @@ download_file = function(url, filename) end -markdown_escape = function(text) +function utilities.markdown_escape(text) text = text:gsub('_', '\\_') text = text:gsub('%[', '\\[') @@ -262,11 +266,30 @@ markdown_escape = function(text) end -function string:md_escape() - local text = self - text = text:gsub('_', '\\_') - text = text:gsub('%[', '\\[') - text = text:gsub('%*', '\\*') - text = text:gsub('`', '\\`') - return text +function utilities.md_escape(s) + s = s:gsub('_', '\\_') + s = s:gsub('%[', '\\[') + s = s:gsub('%*', '\\*') + s = s:gsub('`', '\\`') + return s +end + +utilities.INVOCATION_PATTERN = '/' + +utilities.triggers_metatable = {} +function utilities.triggers_metatable:t(pattern, has_args) + self.table:insert('^'..utilities.INVOCATION_PATTERN..pattern..'$') + self.table:insert('^'..utilities.INVOCATION_PATTERN..pattern..'@'..self.username..'$') + if has_args then + self.table:insert('^'..utilities.INVOCATION_PATTERN..pattern..'%s+[^%s]*') + self.table:insert('^'..utilities.INVOCATION_PATTERN..pattern..'@'..self.username..'%s+[^%s]*') + end + return self +end + +function utilities.triggers(username) + local self = setmetatable({}, utilities.triggers_metatable) + self.username = username + self.table = {} + return self end From 24deaec7596fa6ff4df3a681178d2407c7aab177 Mon Sep 17 00:00:00 2001 From: Brayden Banks Date: Sun, 10 Apr 2016 21:04:47 -0700 Subject: [PATCH 2/9] *Should* have a working local refactor now. --- README.md | 14 +-- bot.lua | 26 ++--- plugins/about.lua | 3 +- plugins/bible.lua | 2 +- plugins/cats.lua | 2 +- plugins/chatter.lua | 63 ++++++------ plugins/commit.lua | 26 ++--- plugins/control.lua | 34 ++++--- plugins/currency.lua | 37 +++---- plugins/dice.lua | 36 +++---- plugins/dilbert.lua | 39 ++++---- plugins/echo.lua | 30 +++--- plugins/eightball.lua | 27 +++--- plugins/floodcontrol.lua | 35 ++++--- plugins/fortune.lua | 38 ++++---- plugins/gImages.lua | 60 ++++++------ plugins/gMaps.lua | 34 +++---- plugins/gSearch.lua | 42 ++++---- plugins/greetings.lua | 82 ++++++++-------- plugins/hackernews.lua | 35 ++++--- plugins/hearthstone.lua | 75 +++++++------- plugins/help.lua | 43 +++++---- plugins/imdb.lua | 35 ++++--- plugins/lastfm.lua | 78 +++++++-------- plugins/librefm.lua | 67 ++++++------- plugins/luarun.lua | 24 ++--- plugins/me.lua | 29 +++--- plugins/moderation.lua | 188 +++++++++++++++++++----------------- plugins/nick.lua | 36 +++---- plugins/patterns.lua | 15 +-- plugins/ping.lua | 21 ++-- plugins/pokedex.lua | 39 ++++---- plugins/preview.lua | 35 +++---- plugins/pun.lua | 26 ++--- plugins/reactions.lua | 61 +++++++----- plugins/reddit.lua | 42 ++++---- plugins/setandget.lua | 55 ++++++----- plugins/shell.lua | 24 ++--- plugins/shout.lua | 30 +++--- plugins/slap.lua | 38 ++++---- plugins/time.lua | 38 ++++---- plugins/translate.lua | 38 ++++---- plugins/urbandictionary.lua | 38 ++++---- plugins/weather.lua | 50 +++++----- plugins/whoami.lua | 34 +++---- plugins/wikipedia.lua | 52 +++++----- plugins/xkcd.lua | 42 ++++---- plugins/youtube.lua | 49 +++++----- utilities.lua | 11 ++- 49 files changed, 1026 insertions(+), 952 deletions(-) diff --git a/README.md b/README.md index 5c7ec4e..b61e7af 100755 --- a/README.md +++ b/README.md @@ -53,13 +53,13 @@ Most plugins are intended for public use, but a few are for other purposes, like A plugin can have five components, and two of them are required: -| Component | Description | Required? | -|:----------|:-----------------------------------------------------|:----------| -| action | Main function. Expects `msg` table as an argument. | Y | -| triggers | Table of triggers for the plugin. Uses Lua patterns. | Y | -| cron | Optional function to be called every minute. | N | -| command | Basic command and syntax. Listed in the help text. | N | -| doc | Usage for the plugin. Returned by "/help $command". | N | +| Component | Description | Required? | +|:----------|:---------------------------------------------|:----------| +| action | Main function. Expects `msg` table as an argument. | Y | +| triggers | Table of triggers for the plugin. Uses Lua patterns. | Y | +| cron | Optional function to be called every minute. | N | +| command | Basic command and syntax. Listed in the help text. | N | +| doc | Usage for the plugin. Returned by "/help $command". | N | The `on_msg_receive()` function adds a few variables to the `msg` table for your convenience. These are self-explanatory: `msg.from.id_str`, `msg.to.id_str`, `msg.chat.id_str`, `msg.text_lower`, `msg.from.name`. diff --git a/bot.lua b/bot.lua index 915d8f7..4ce00c2 100755 --- a/bot.lua +++ b/bot.lua @@ -1,5 +1,7 @@ local bot = {} +local instance = {} + local bindings = require('bindings') -- Load Telegram bindings. local utilities = require('utilities') -- Load miscellaneous and cross-plugin functions. @@ -115,30 +117,30 @@ function bot:on_msg_receive(msg) -- The fn run whenever a message is received. end -bot.init(bot) -- Actually start the script. Run the bot_init function. +bot.init(instance) -- Actually start the script. Run the bot_init function. -while bot.is_started do -- Start a loop while the bot should be running. +while instance.is_started do -- Start a loop while the bot should be running. do - local res = bindings.getUpdates(bot, bot.last_update+1) -- Get the latest updates! + local res = bindings.getUpdates(instance, instance.last_update+1) -- Get the latest updates! if res then for _,v in ipairs(res.result) do -- Go through every new message. - bot.last_update = v.update_id - bot.on_msg_receive(bot, v.message) + instance.last_update = v.update_id + bot.on_msg_receive(instance, v.message) end else - print(bot.config.errors.connection) + print(instance.config.errors.connection) end end - if bot.last_cron ~= os.date('%M') then -- Run cron jobs every minute. - bot.last_cron = os.date('%M') - utilities.save_data(bot.info.username..'.db', bot.database) -- Save the database. - for i,v in ipairs(bot.plugins) do + if instance.last_cron ~= os.date('%M') then -- Run cron jobs every minute. + instance.last_cron = os.date('%M') + utilities.save_data(instance.info.username..'.db', instance.database) -- Save the database. + for i,v in ipairs(instance.plugins) do if v.cron then -- Call each plugin's cron function, if it has one. local res, err = pcall(function() v.cron() end) if not res then - utilities.handle_exception(bot, err, 'CRON: ' .. i) + utilities.handle_exception(instance, err, 'CRON: ' .. i) end end end @@ -147,5 +149,5 @@ while bot.is_started do -- Start a loop while the bot should be running. end -- Save the database before exiting. -utilities.save_data(bot.info.username..'.db', bot.database) +utilities.save_data(instance.info.username..'.db', instance.database) print('Halted.') diff --git a/plugins/about.lua b/plugins/about.lua index f64ac50..0e9667a 100755 --- a/plugins/about.lua +++ b/plugins/about.lua @@ -1,5 +1,6 @@ local about = {} +local bot = require('bot') local bindings = require('bindings') about.command = 'about' @@ -15,7 +16,7 @@ function about:action(msg) -- other plugins. if msg.forward_from then return end - local message = self.config.about_text .. '\nBased on @otouto v'..self.version..' by topkecleon.' + local message = self.config.about_text .. '\nBased on @otouto v'..bot.version..' by topkecleon.' if msg.new_chat_participant and msg.new_chat_participant.id == self.info.id then bindings.sendMessage(self, msg.chat.id, message, true) diff --git a/plugins/bible.lua b/plugins/bible.lua index a556d48..ce315cb 100755 --- a/plugins/bible.lua +++ b/plugins/bible.lua @@ -26,7 +26,7 @@ function bible:action(msg) local input = utilities.input(msg.text) if not input then - bindings.sendMessage(self, msg.chat.id, self.doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, bible.doc, true, msg.message_id, true) return end diff --git a/plugins/cats.lua b/plugins/cats.lua index d72f885..9e05146 100755 --- a/plugins/cats.lua +++ b/plugins/cats.lua @@ -14,7 +14,7 @@ end cats.command = 'cat' cats.doc = '`Returns a cat!`' -cats.triggers = utilities.triggers():t('cat') +cats.triggers = utilities.triggers():t('cat').table function cats:action(msg) diff --git a/plugins/chatter.lua b/plugins/chatter.lua index 6f532d9..c050a5c 100755 --- a/plugins/chatter.lua +++ b/plugins/chatter.lua @@ -1,24 +1,33 @@ -- Put this absolutely at the end, even after greetings.lua. -if not config.simsimi_key then - print('Missing config value: simsimi_key.') - print('chatter.lua will not be enabled.') - return +local chatter = {} + +local HTTP = require('socket.http') +local URL = require('socket.url') +local JSON = require('cjson') +local bindings = require('bindings') + +function chatter:init() + if not self.config.simsimi_key then + print('Missing config value: simsimi_key.') + print('chatter.lua will not be enabled.') + return + end + + chatter.triggers = { + '', + '^' .. self.info.first_name .. ',', + '^@' .. self.info.username .. ',' + } end -local triggers = { - '', - '^' .. bot.first_name .. ',', - '^@' .. bot.username .. ',' -} - -local action = function(msg) +function chatter:action(msg) if msg.text == '' then return end -- This is awkward, but if you have a better way, please share. - if msg.text_lower:match('^' .. bot.first_name .. ',') then - elseif msg.text_lower:match('^@' .. bot.username .. ',') then + if msg.text_lower:match('^' .. self.info.first_name .. ',') + or msg.text_lower:match('^@' .. self.info.username .. ',') then elseif msg.text:match('^/') then return true -- Uncomment the following line for Al Gore-like reply chatter. @@ -28,40 +37,41 @@ local action = function(msg) return true end - sendChatAction(msg.chat.id, 'typing') + bindings.sendChatAction(self, msg.chat.id, 'typing') local input = msg.text_lower - input = input:gsub(bot.first_name, 'simsimi') - input = input:gsub('@'..bot.username, 'simsimi') - - if config.simsimi_trial then + input = input:gsub(self.info.first_name, 'simsimi') + input = input:gsub('@'..self.info.username, 'simsimi') + + local sandbox + if self.config.simsimi_trial then sandbox = 'sandbox.' else sandbox = '' -- NO Sandbox end - local url = 'http://' ..sandbox.. 'api.simsimi.com/request.p?key=' ..config.simsimi_key.. '&lc=' ..config.lang.. '&ft=1.0&text=' .. URL.escape(input) + local url = 'http://' ..sandbox.. 'api.simsimi.com/request.p?key=' ..self.config.simsimi_key.. '&lc=' ..self.config.lang.. '&ft=1.0&text=' .. URL.escape(input) local jstr, res = HTTP.request(url) if res ~= 200 then - sendMessage(msg.chat.id, config.errors.chatter_connection) + bindings.sendMessage(self, msg.chat.id, self.config.errors.chatter_connection) return end local jdat = JSON.decode(jstr) if not jdat.response then - sendMessage(msg.chat.id, config.errors.chatter_response) + bindings.sendMessage(self, msg.chat.id, self.config.errors.chatter_response) return end local message = jdat.response if message:match('^I HAVE NO RESPONSE.') then - message = config.errors.chatter_response + message = self.config.errors.chatter_response end -- Let's clean up the response a little. Capitalization & punctuation. local filter = { - ['%aimi?%aimi?'] = bot.first_name, + ['%aimi?%aimi?'] = self.info.first_name, ['^%s*(.-)%s*$'] = '%1', ['^%l'] = string.upper, ['USER'] = msg.from.first_name @@ -75,11 +85,8 @@ local action = function(msg) message = message .. '.' end - sendMessage(msg.chat.id, message) + bindings.sendMessage(self, msg.chat.id, message) end -return { - action = action, - triggers = triggers -} +return chatter diff --git a/plugins/commit.lua b/plugins/commit.lua index e0e73f4..32e7369 100755 --- a/plugins/commit.lua +++ b/plugins/commit.lua @@ -1,11 +1,16 @@ -- Commits from https://github.com/ngerakines/commitment. -local command = 'commit' -local doc = '`Returns a commit message from whatthecommit.com.`' +local commit = {} -local triggers = { - '^/commit[@'..bot.username..']*' -} +local bindings = require('bindings') +local utilities = require('utilities') + +commit.command = 'commit' +commit.doc = '`Returns a commit message from whatthecommit.com.`' + +function commit:init() + commit.triggers = utilities.triggers(self.info.username):t('commit').table +end local commits = { "One does not simply merge into master", @@ -416,15 +421,10 @@ local commits = { "fml" } -local action = function(msg) +function commit:action(msg) - sendMessage(msg.chat.id, '`'..commits[math.random(#commits)]..'`', true, nil, true) + bindings.sendMessage(self, msg.chat.id, '`'..commits[math.random(#commits)]..'`', true, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return commit diff --git a/plugins/control.lua b/plugins/control.lua index 663cc1e..a0dd221 100644 --- a/plugins/control.lua +++ b/plugins/control.lua @@ -1,28 +1,30 @@ -local triggers = { - '^/reload[@'..bot.username..']*', - '^/halt[@'..bot.username..']*' -} +local control = {} -local action = function(msg) +local bot = require('bot') +local bindings = require('bindings') +local utilities = require('utilities') - if msg.from.id ~= config.admin then +function control:init() + control.triggers = utilities.triggers(self.info.username):t('reload'):t('halt').table +end + +function control:action(msg) + + if msg.from.id ~= self.config.admin then return end if msg.date < os.time() then return end - if msg.text:match('^/reload') then - bot_init() - sendReply(msg, 'Bot reloaded!') - elseif msg.text:match('^/halt') then - is_started = false - sendReply(msg, 'Stopping bot!') + if msg.text:match('^'..utilities.INVOCATION_PATTERN..'reload') then + bot.init(self) + bindings.sendReply(self, msg, 'Bot reloaded!') + elseif msg.text:match('^'..utilities.INVOCATION_PATTERN..'halt') then + self.is_started = false + bindings.sendReply(self, msg, 'Stopping bot!') end end -return { - action = action, - triggers = triggers -} +return control diff --git a/plugins/currency.lua b/plugins/currency.lua index aea0fa6..d6e32ca 100755 --- a/plugins/currency.lua +++ b/plugins/currency.lua @@ -1,26 +1,32 @@ -local command = 'cash [amount] to ' -local doc = [[``` +local currency = {} + +local HTTPS = require('ssl.https') +local bindings = require('bindings') +local utilities = require('utilities') + +currency.command = 'cash [amount] to ' +currency.doc = [[``` /cash [amount] to Example: /cash 5 USD to EUR Returns exchange rates for various currencies. Source: Google Finance. ```]] -local triggers = { - '^/cash[@'..bot.username..']*' -} +function currency:init() + currency.triggers = utilities.triggers(self.info.username):t('cash', true).table +end -local action = function(msg) +function currency:action(msg) local input = msg.text:upper() if not input:match('%a%a%a TO %a%a%a') then - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, currency.doc, true, msg.message_id, true) return end local from = input:match('(%a%a%a) TO') local to = input:match('TO (%a%a%a)') - local amount = get_word(input, 2) + local amount = utilities.get_word(input, 2) amount = tonumber(amount) or 1 local result = 1 @@ -28,16 +34,16 @@ local action = function(msg) if from ~= to then - local url = url .. '?from=' .. from .. '&to=' .. to .. '&a=' .. amount + url = url .. '?from=' .. from .. '&to=' .. to .. '&a=' .. amount local str, res = HTTPS.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end str = str:match('(.*) %u+') if not str then - sendReply(msg, config.errors.results) + bindings.sendReply(self, msg, self.config.errors.results) return end @@ -49,13 +55,8 @@ local action = function(msg) output = output .. os.date('!%F %T UTC') .. '\nSource: Google Finance' output = '`' .. output .. '`' - sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return currency diff --git a/plugins/dice.lua b/plugins/dice.lua index 0da32f5..296743f 100755 --- a/plugins/dice.lua +++ b/plugins/dice.lua @@ -1,18 +1,23 @@ -local command = 'roll ' -local doc = [[``` +local dice = {} + +local bindings = require('bindings') +local utilities = require('utilities') + +dice.command = 'roll ' +dice.doc = [[``` /roll Returns a set of dice rolls, where n is the number of rolls and r is the range. If only a range is given, returns only one roll. ```]] -local triggers = { - '^/roll[@'..bot.username..']*' -} +function dice:init() + dice.triggers = utilities.triggers(self.info.username):t('roll', true).table +end -local action = function(msg) +function dice:action(msg) local input = utilities.input(msg.text_lower) if not input then - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(msg.chat.id, dice.doc, true, msg.message_id, true) return end @@ -23,7 +28,7 @@ local action = function(msg) count = 1 range = input:match('^d?([%d]+)$') else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, dice.doc, true, msg.message_id, true) return end @@ -31,27 +36,22 @@ local action = function(msg) range = tonumber(range) if range < 2 then - sendReply(msg, 'The minimum range is 2.') + bindings.sendReply(self, msg, 'The minimum range is 2.') return end if range > 1000 or count > 1000 then - sendReply(msg, 'The maximum range and count are 1000.') + bindings.sendReply(self, msg, 'The maximum range and count are 1000.') return end local output = '*' .. count .. 'd' .. range .. '*\n`' - for i = 1, count do + for _ = 1, count do output = output .. math.random(range) .. '\t' end output = output .. '`' - sendMessage(msg.chat.id, output, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return dice diff --git a/plugins/dilbert.lua b/plugins/dilbert.lua index 5b53b70..ea227e5 100644 --- a/plugins/dilbert.lua +++ b/plugins/dilbert.lua @@ -1,20 +1,25 @@ -dilbert = dilbert or {} +local dilbert = {} -local command = 'dilbert [date]' -local doc = [[``` +local HTTP = require('socket.http') +local URL = require('socket.url') +local bindings = require('bindings') +local utilities = require('utilities') + +dilbert.command = 'dilbert [date]' +dilbert.doc = [[``` /dilbert [YYYY-MM-DD] Returns the latest Dilbert strip or that of the provided date. Dates before the first strip will return the first strip. Dates after the last trip will return the last strip. Source: dilbert.com ```]] -local triggers = { - '^/dilbert[@'..bot.username..']*' -} +function dilbert:init() + dilbert.triggers = utilities.triggers(self.info.username):t('dilbert', true).table +end -local action = function(msg) +function dilbert:action(msg) - sendChatAction(msg.chat.id, 'upload_photo') + bindings.sendChatAction(msg.chat.id, 'upload_photo') local input = utilities.input(msg.text) if not input then input = os.date('%F') end @@ -23,24 +28,22 @@ local action = function(msg) local url = 'http://dilbert.com/strip/' .. URL.escape(input) local str, res = HTTP.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end - if not dilbert[input] then + local strip_file = io.open('/tmp/' .. input .. '.gif') + if not strip_file then local strip_url = str:match('') - dilbert[input] = download_file(strip_url, '/tmp/' .. input .. '.gif') + strip_file = utilities.download_file(strip_url, '/tmp/' .. input .. '.gif') end local strip_title = str:match('') - sendPhoto(msg.chat.id, dilbert[input], strip_title) + bindings.sendPhoto(self, msg.chat.id, strip_file, strip_title) + + strip_file:close() end -return { - command = command, - doc = doc, - triggers = triggers, - action = action -} +return dilbert diff --git a/plugins/echo.lua b/plugins/echo.lua index d0e5731..26be359 100755 --- a/plugins/echo.lua +++ b/plugins/echo.lua @@ -1,35 +1,35 @@ -local command = 'echo ' -local doc = [[``` +local echo = {} + +local bindings = require('bindings') +local utilities = require('utilities') + +echo.command = 'echo ' +echo.doc = [[``` /echo Repeats a string of text. ```]] -local triggers = { - '^/echo[@'..bot.username..']*' -} +function echo:init() + echo.triggers = utilities.triggers(self.info.username):t('echo').table +end -local action = function(msg) +function echo:action(msg) local input = utilities.input(msg.text) if not input then - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, echo.doc, true, msg.message_id, true) else local output if msg.chat.type == 'supergroup' then output = 'Echo:\n"' .. input .. '"' else - output = latcyr(input) + output = utilities.latcyr(input) end - sendMessage(msg.chat.id, output, true) + bindings.sendMessage(self, msg.chat.id, output, true) end end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return echo diff --git a/plugins/eightball.lua b/plugins/eightball.lua index 4c82ef6..f839f9c 100755 --- a/plugins/eightball.lua +++ b/plugins/eightball.lua @@ -1,10 +1,14 @@ -local command = '8ball' -local doc = '`Returns an answer from a magic 8-ball!`' +local eightball = {} -local triggers = { - '^/8ball', - 'y/n%p?$' -} +local bindings = require('bindings') +local utilities = require('utilities') + +eightball.command = '8ball' +eightball.doc = '`Returns an answer from a magic 8-ball!`' + +function eightball:init() + eightball.triggers = utilities.triggers(self.info.username, {'[Yy]/[Nn]%p*$'}):t('8ball', true).table +end local ball_answers = { "It is certain.", @@ -37,7 +41,7 @@ local yesno_answers = { 'No.' } -local action = function(msg) +function eightball:action(msg) if msg.reply_to_message then msg = msg.reply_to_message @@ -51,13 +55,8 @@ local action = function(msg) message = ball_answers[math.random(#ball_answers)] end - sendReply(msg, message) + bindings.sendReply(self, msg, message) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return eightball diff --git a/plugins/floodcontrol.lua b/plugins/floodcontrol.lua index a25bb6c..7b03b14 100755 --- a/plugins/floodcontrol.lua +++ b/plugins/floodcontrol.lua @@ -1,22 +1,29 @@ -- Liberbot-compliant floodcontrol. -- Put this after moderation.lua or blacklist.lua. -floodcontrol = floodcontrol or {} +local floodcontrol = {} -local triggers = { +local JSON = require('cjson') +local utilities = require('utilities') + +function floodcontrol:init() + self.floodcontrol = floodcontrol or {} +end + +floodcontrol.triggers = { '' } -local action = function(msg) +function floodcontrol:action(msg) - if floodcontrol[-msg.chat.id] then + if self.floodcontrol[-msg.chat.id] then return end - local input = msg.text_lower:match('^/floodcontrol[@'..bot.username..']* (.+)') + local input = msg.text_lower:match('^/floodcontrol (.+)') or msg.text_lower:match('^/floodcontrol@'..self.info.username..' (.+)') if not input then return true end - if msg.from.id ~= 100547061 and msg.from.id ~= config.admin then + if msg.from.id ~= 100547061 and msg.from.id ~= self.config.admin then return -- Only run for Liberbot or the admin. end @@ -29,25 +36,21 @@ local action = function(msg) input.duration = 600 end - floodcontrol[input.groupid] = os.time() + input.duration + self.floodcontrol[input.groupid] = os.time() + input.duration local output = input.groupid .. ' silenced for ' .. input.duration .. ' seconds.' - handle_exception('floodcontrol.lua', output) + utilities.handle_exception(self, 'floodcontrol.lua', output) end -local cron = function() +function floodcontrol:cron() - for k,v in pairs(floodcontrol) do + for k,v in pairs(self.floodcontrol) do if os.time() > v then - floodcontrol[k] = nil + self.floodcontrol[k] = nil end end end -return { - action = action, - triggers = triggers, - cron = cron -} +return floodcontrol diff --git a/plugins/fortune.lua b/plugins/fortune.lua index a340b1a..aa1621e 100755 --- a/plugins/fortune.lua +++ b/plugins/fortune.lua @@ -1,29 +1,29 @@ -- Requires that the "fortune" program is installed on your computer. -local s = io.popen('fortune'):read('*all') -if s:match('not found$') then - print('fortune is not installed on this computer.') - print('fortune.lua will not be enabled.') - return +local fortune = {} + +local bindings = require('bindings') +local utilities = require('utilities') + +function fortune:init() + local s = io.popen('fortune'):read('*all') + if s:match('not found$') then + print('fortune is not installed on this computer.') + print('fortune.lua will not be enabled.') + return + end + + fortune.triggers = utilities.triggers(self.info.username):t('fortune').table end -local command = 'fortune' -local doc = '`Returns a UNIX fortune.`' +fortune.command = 'fortune' +fortune.doc = '`Returns a UNIX fortune.`' -local triggers = { - '^/fortune[@'..bot.username..']*' -} - -local action = function(msg) +function fortune:action(msg) local message = io.popen('fortune'):read('*all') - sendMessage(msg.chat.id, message) + bindings.sendMessage(self, msg.chat.id, message) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return fortune diff --git a/plugins/gImages.lua b/plugins/gImages.lua index 99c8c88..777385f 100755 --- a/plugins/gImages.lua +++ b/plugins/gImages.lua @@ -1,43 +1,48 @@ -- You need a Google API key and a Google Custom Search Engine set up to use this, in config.google_api_key and config.google_cse_key, respectively. -- You must also sign up for the CSE in the Google Developer Concsole, and enable image results. -if not config.google_api_key then - print('Missing config value: google_api_key.') - print('gImages.lua will not be enabled.') - return -elseif not config.google_cse_key then - print('Missing config value: google_cse_key.') - print('gImages.lua will not be enabled.') - return +local gImages = {} + +local HTTPS = require('ssl.https') +local URL = require('socket.url') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +function gImages:init() + if not self.config.google_api_key then + print('Missing config value: google_api_key.') + print('gImages.lua will not be enabled.') + return + elseif not self.config.google_cse_key then + print('Missing config value: google_cse_key.') + print('gImages.lua will not be enabled.') + return + end + + gImages.triggers = utilities.triggers():t('image', true):t('i', true):t('insfw', true).table end -local command = 'image ' -local doc = [[``` +gImages.command = 'image ' +gImages.doc = [[``` /image Returns a randomized top result from Google Images. Safe search is enabled by default; use "/insfw" to disable it. NSFW results will not display an image preview. Alias: /i ```]] -local triggers = { - '^/image[@'..bot.username..']*', - '^/i[@'..bot.username..']* ', - '^/i[@'..bot.username..']*$', - '^/insfw[@'..bot.username..']*' -} - -local action = function(msg) +function gImages:action(msg) local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, gImages.doc, true, msg.message_id, true) return end end - local url = 'https://www.googleapis.com/customsearch/v1?&searchType=image&imgSize=xlarge&alt=json&num=8&start=1&key=' .. config.google_api_key .. '&cx=' .. config.google_cse_key + local url = 'https://www.googleapis.com/customsearch/v1?&searchType=image&imgSize=xlarge&alt=json&num=8&start=1&key=' .. self.config.google_api_key .. '&cx=' .. self.config.google_cse_key if not string.match(msg.text, '^/i[mage]*nsfw') then url = url .. '&safe=high' @@ -47,13 +52,13 @@ local action = function(msg) local jstr, res = HTTPS.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) if jdat.searchInformation.totalResults == '0' then - sendReply(msg, config.errors.results) + bindings.sendReply(self, msg, self.config.errors.results) return end @@ -64,16 +69,11 @@ local action = function(msg) if msg.text:match('nsfw') then - sendReply(msg, result) + bindings.sendReply(self, msg, output) else - sendMessage(msg.chat.id, output, false, nil, true) + bindings.sendMessage(self, msg.chat.id, output, false, nil, true) end end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return gImages diff --git a/plugins/gMaps.lua b/plugins/gMaps.lua index 1b49d8c..672db06 100755 --- a/plugins/gMaps.lua +++ b/plugins/gMaps.lua @@ -1,41 +1,39 @@ -local command = 'location ' -local doc = [[``` +local gMaps = {} + +local bindings = require('bindings') +local utilities = require('utilities') + +gMaps.command = 'location ' +gMaps.doc = [[``` /location Returns a location from Google Maps. Alias: /loc ```]] -local triggers = { - '^/location[@'..bot.username..']*', - '^/loc[@'..bot.username..']* ', - '^/loc[@'..bot.username..']*$' -} +function gMaps:init() + gMaps.triggers = utilities.triggers(self.info.username):t('location', true):t('loc', true).table +end -local action = function(msg) +function gMaps:action(msg) local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, gMaps.doc, true, msg.message_id, true) return end end - local coords = get_coords(input) + local coords = utilities.get_coords(self, input) if type(coords) == 'string' then - sendReply(msg, coords) + bindings.sendReply(self, msg, coords) return end - sendLocation(msg.chat.id, coords.lat, coords.lon, msg.message_id) + bindings.sendLocation(self, msg.chat.id, coords.lat, coords.lon, msg.message_id) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return gMaps diff --git a/plugins/gSearch.lua b/plugins/gSearch.lua index bf906e9..4f40e70 100755 --- a/plugins/gSearch.lua +++ b/plugins/gSearch.lua @@ -1,25 +1,30 @@ -local command = 'google ' -local doc = [[``` +local gSearch = {} + +local HTTPS = require('ssl.https') +local URL = require('socket.url') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +gSearch.command = 'google ' +gSearch.doc = [[``` /google Returns four (if group) or eight (if private message) results from Google. Safe search is enabled by default, use "/gnsfw" to disable it. Alias: /g ```]] -local triggers = { - '^/g[@'..bot.username..']*$', - '^/g[@'..bot.username..']* ', - '^/google[@'..bot.username..']*', - '^/gnsfw[@'..bot.username..']*' -} +function gSearch:init() + gSearch.triggers = utilities.triggers(self.info.username):t('g', true):t('google', true):t('gnsfw', true).table +end -local action = function(msg) +function gSearch:action(msg) local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, gSearch.doc, true, msg.message_id, true) return end end @@ -40,22 +45,22 @@ local action = function(msg) local jstr, res = HTTPS.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) if not jdat.responseData then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end if not jdat.responseData.results[1] then - sendReply(msg, config.errors.results) + bindings.sendReply(self, msg, self.config.errors.results) return end local output = '*Google results for* _' .. input .. '_ *:*\n' - for i,v in ipairs(jdat.responseData.results) do + for i,_ in ipairs(jdat.responseData.results) do local title = jdat.responseData.results[i].titleNoFormatting:gsub('%[.+%]', ''):gsub('&', '&') --[[ if title:len() > 48 then @@ -70,13 +75,8 @@ local action = function(msg) end end - sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return gSearch diff --git a/plugins/greetings.lua b/plugins/greetings.lua index 29753ae..5e0dcb7 100755 --- a/plugins/greetings.lua +++ b/plugins/greetings.lua @@ -2,47 +2,54 @@ -- If you want to configure your own greetings, copy the following table -- (without the "config.") to your config.lua file. -if not config.greetings then - config.greetings = { - ['Hello, #NAME.'] = { - 'hello', - 'hey', - 'sup', - 'hi', - 'good morning', - 'good day', - 'good afternoon', - 'good evening' - }, - ['Goodbye, #NAME.'] = { - 'bye', - 'later', - 'see ya', - 'good night' - }, - ['Welcome back, #NAME.'] = { - 'i\'m home', - 'i\'m back' - }, - ['You\'re welcome, #NAME.'] = { - 'thanks', - 'thank you' +local greetings = {} + +local bindings = require('bindings') +local utilities = require('utilities') + +function greetings:init() + if not self.config.greetings then + self.config.greetings = { + ['Hello, #NAME.'] = { + 'hello', + 'hey', + 'sup', + 'hi', + 'good morning', + 'good day', + 'good afternoon', + 'good evening' + }, + ['Goodbye, #NAME.'] = { + 'bye', + 'later', + 'see ya', + 'good night' + }, + ['Welcome back, #NAME.'] = { + 'i\'m home', + 'i\'m back' + }, + ['You\'re welcome, #NAME.'] = { + 'thanks', + 'thank you' + } } + end + + greetings.triggers = { + self.info.first_name .. '%p*$' } end -local triggers = { - bot.first_name .. '%p*$' -} +function greetings:action(msg) -local action = function(msg) + local nick = self.database.users[msg.from.id_str].nickname or msg.from.first_name - local nick = database.users[msg.from.id_str].nickname or msg.from.first_name - - for k,v in pairs(config.greetings) do - for key,val in pairs(v) do - if msg.text_lower:match(val..',? '..bot.first_name) then - sendMessage(msg.chat.id, latcyr(k:gsub('#NAME', nick))) + for trigger,responses in pairs(self.config.greetings) do + for _,response in pairs(responses) do + if msg.text_lower:match(response..',? '..self.info.first_name) then + bindings.sendMessage(self, msg.chat.id, utilities.latcyr(trigger:gsub('#NAME', nick))) return end end @@ -52,7 +59,4 @@ local action = function(msg) end -return { - action = action, - triggers = triggers -} +return greetings diff --git a/plugins/hackernews.lua b/plugins/hackernews.lua index 1747bc8..f68a458 100755 --- a/plugins/hackernews.lua +++ b/plugins/hackernews.lua @@ -1,21 +1,25 @@ -local command = 'hackernews' -local doc = [[``` +local hackernews = {} + +local HTTPS = require('ssl.https') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +hackernews.command = 'hackernews' +hackernews.doc = [[``` Returns four (if group) or eight (if private message) top stories from Hacker News. Alias: /hn ```]] -local triggers = { - '^/hackernews[@'..bot.username..']*', - '^/hn[@'..bot.username..']*' -} +hackernews.triggers = utilities.triggers():t('hackernews', true):t('hn', true).table -local action = function(msg) +function hackernews:action(msg) - sendChatAction(msg.chat.id, 'typing') + bindings.sendChatAction(self, msg.chat.id, 'typing') local jstr, res = HTTPS.request('https://hacker-news.firebaseio.com/v0/topstories.json') if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end @@ -31,7 +35,7 @@ local action = function(msg) local res_url = 'https://hacker-news.firebaseio.com/v0/item/' .. jdat[i] .. '.json' jstr, res = HTTPS.request(res_url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local res_jdat = JSON.decode(jstr) @@ -41,7 +45,7 @@ local action = function(msg) end local url = res_jdat.url if not url then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end if url:find('%(') then @@ -52,13 +56,8 @@ local action = function(msg) end - sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return hackernews diff --git a/plugins/hearthstone.lua b/plugins/hearthstone.lua index 9de002d..7e2ab13 100755 --- a/plugins/hearthstone.lua +++ b/plugins/hearthstone.lua @@ -1,45 +1,50 @@ -- Plugin for the Hearthstone database provided by hearthstonejson.com. -if not database.hearthstone or os.time() > database.hearthstone.expiration then +local hearthstone = {} - print('Downloading Hearthstone database...') +local HTTPS = require('ssl.https') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') - database.hearthstone = { - expiration = os.time() + 600000 - } +function hearthstone:init() + if not self.database.hearthstone or os.time() > self.database.hearthstone.expiration then - local jstr, res = HTTPS.request('http://hearthstonejson.com/json/AllSets.json') - if res ~= 200 then - print('Error connecting to hearthstonejson.com.') - print('hearthstone.lua will not be enabled.') - return - end - local jdat = JSON.decode(jstr) + print('Downloading Hearthstone database...') - for k,v in pairs(jdat) do - for key,val in pairs(v) do - table.insert(database.hearthstone, val) + self.database.hearthstone = { + expiration = os.time() + 600000 + } + + local jstr, res = HTTPS.request('http://hearthstonejson.com/json/AllSets.json') + if res ~= 200 then + print('Error connecting to hearthstonejson.com.') + print('hearthstone.lua will not be enabled.') + return end + local jdat = JSON.decode(jstr) + + for _,v in pairs(jdat) do + for _,val in pairs(v) do + table.insert(self.database.hearthstone, val) + end + end + + print('Download complete! It will be stored for a week.') + end - print('Download complete! It will be stored for a week.') - + hearthstone.triggers = utilities.triggers(self.info.username):t('hearthstone', true):t('hs').table end -local command = 'hearthstone ' -local doc = [[``` +hearthstone.command = 'hearthstone ' +hearthstone.doc = [[``` /hearthstone Returns Hearthstone card info. Alias: /hs ```]] -local triggers = { - '^/hearthstone[@'..bot.username..']*', - '^/hs[@'..bot.username..']*$', - '^/hs[@'..bot.username..']* ' -} - -local format_card = function(card) +local function format_card(card) local ctype = card.type if card.race then @@ -70,6 +75,7 @@ local format_card = function(card) stats = card.health .. 'h' end + -- unused? local info = '' if card.text then info = card.text:gsub('',''):gsub('%$','') @@ -94,16 +100,16 @@ local format_card = function(card) end -local action = function(msg) +function hearthstone:action(msg) local input = utilities.input(msg.text_lower) if not input then - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, hearthstone.doc, true, msg.message_id, true) return end local output = '' - for k,v in pairs(database.hearthstone) do + for _,v in pairs(self.database.hearthstone) do if type(v) == 'table' and string.lower(v.name):match(input) then output = output .. format_card(v) .. '\n\n' end @@ -111,17 +117,12 @@ local action = function(msg) output = output:trim() if output:len() == 0 then - sendReply(msg, config.errors.results) + bindings.sendReply(self, msg, self.config.errors.results) return end - sendMessage(msg.chat.id, output, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return hearthstone diff --git a/plugins/help.lua b/plugins/help.lua index 155689a..bb923fc 100755 --- a/plugins/help.lua +++ b/plugins/help.lua @@ -1,12 +1,21 @@ -- This plugin should go at the end of your plugin list in -- config.lua, but not after greetings.lua. +local help = {} + +local bindings = require('bindings') +local utilities = require('utilities') + local help_text = '*Available commands:*' -for i,v in ipairs(plugins) do - if v.command then - help_text = help_text .. '\n• /' .. v.command:gsub('%[', '\\[') +function help:init() + for _,plugin in ipairs(self.plugins) do + if plugin.command then + help_text = help_text .. '\n• /' .. plugin.command:gsub('%[', '\\[') + end end + + help.triggers = utilities.triggers():t('help', true):t('h', true).table end help_text = help_text .. [[ @@ -15,40 +24,32 @@ help_text = help_text .. [[ Arguments: \[optional] ]] -local triggers = { - '^/help[@'..bot.username..']*', - '^/h[@'..bot.username..']*$' -} - -local action = function(msg) +function help:action(msg) local input = utilities.input(msg.text_lower) -- Attempts to send the help message via PM. -- If msg is from a group, it tells the group whether the PM was successful. if not input then - local res = sendMessage(msg.from.id, help_text, true, nil, true) + local res = bindings.sendMessage(self, msg.from.id, help_text, true, nil, true) if not res then - sendReply(msg, 'Please message me privately for a list of commands.') + bindings.sendReply(self, msg, 'Please message me privately for a list of commands.') elseif msg.chat.type ~= 'private' then - sendReply(msg, 'I have sent you the requested information in a private message.') + bindings.sendReply(self, msg, 'I have sent you the requested information in a private message.') end return end - for i,v in ipairs(plugins) do - if v.command and get_word(v.command, 1) == input and v.doc then - local output = '*Help for* _' .. get_word(v.command, 1) .. '_ *:*\n' .. v.doc - sendMessage(msg.chat.id, output, true, nil, true) + for _,plugin in ipairs(self.plugins) do + if plugin.command and utilities.get_word(plugin.command, 1) == input and plugin.doc then + local output = '*Help for* _' .. utilities.get_word(plugin.command, 1) .. '_ *:*\n' .. plugin.doc + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) return end end - sendReply(msg, 'Sorry, there is no help for that command.') + bindings.sendReply(self, msg, 'Sorry, there is no help for that command.') end -return { - action = action, - triggers = triggers -} +return help diff --git a/plugins/imdb.lua b/plugins/imdb.lua index d5756b0..9eeaf23 100755 --- a/plugins/imdb.lua +++ b/plugins/imdb.lua @@ -1,21 +1,29 @@ -local command = 'imdb ' -local doc = [[``` +local imdb = {} + +local HTTP = require('socket.http') +local URL = require('socket.url') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +imdb.command = 'imdb ' +imdb.doc = [[``` /imdb Returns an IMDb entry. ```]] -local triggers = { - '^/imdb[@'..bot.username..']*' -} +function imdb:init() + imdb.triggers = utilities.triggers(self.info.username):t('imdb', true).table +end -local action = function(msg) +function imdb:action(msg) local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, imdb.doc, true, msg.message_id, true) return end end @@ -24,14 +32,14 @@ local action = function(msg) local jstr, res = HTTP.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) if jdat.Response ~= 'True' then - sendReply(msg, config.errors.results) + bindings.sendReply(self, msg, self.config.errors.results) return end @@ -40,13 +48,8 @@ local action = function(msg) output = output .. jdat.imdbRating ..'/10 | '.. jdat.Runtime ..' | '.. jdat.Genre ..'\n' output = output .. jdat.Plot - sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return imdb diff --git a/plugins/lastfm.lua b/plugins/lastfm.lua index 49f52fe..1afd121 100755 --- a/plugins/lastfm.lua +++ b/plugins/lastfm.lua @@ -1,14 +1,23 @@ -if not config.lastfm_api_key then - print('Missing config value: lastfm_api_key.') - print('lastfm.lua will not be enabled.') - return -end +local lastfm = {} local HTTP = require('socket.http') -HTTP.TIMEOUT = 1 +local URL = require('socket.url') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') -local command = 'lastfm' -local doc = [[``` +function lastfm:init() + if not self.config.lastfm_api_key then + print('Missing config value: lastfm_api_key.') + print('lastfm.lua will not be enabled.') + return + end + + lastfm.triggers = utilities.triggers(self.info.username):t('lastfm', true):t('np', true):t('fmset', true).table +end + +bindings.command = 'lastfm' +bindings.doc = [[``` /np [username] Returns what you are or were last listening to. If you specify a username, info will be returned for that username. @@ -16,66 +25,64 @@ Returns what you are or were last listening to. If you specify a username, info Sets your last.fm username. Otherwise, /np will use your Telegram username. Use "/fmset --" to delete it. ```]] -local triggers = { - '^/lastfm[@'..bot.username..']*', - '^/np[@'..bot.username..']*', - '^/fmset[@'..bot.username..']*' -} - -local action = function(msg) +function lastfm:action(msg) local input = utilities.input(msg.text) if string.match(msg.text, '^/lastfm') then - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, lastfm.doc, true, msg.message_id, true) return elseif string.match(msg.text, '^/fmset') then if not input then - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, lastfm.doc, true, msg.message_id, true) elseif input == '--' or input == '—' then - database.users[msg.from.id_str].lastfm = nil - sendReply(msg, 'Your last.fm username has been forgotten.') + self.database.users[msg.from.id_str].lastfm = nil + bindings.sendReply(self, msg, 'Your last.fm username has been forgotten.') else - database.users[msg.from.id_str].lastfm = input - sendReply(msg, 'Your last.fm username has been set to "' .. input .. '".') + self.database.users[msg.from.id_str].lastfm = input + bindings.sendReply(self, msg, 'Your last.fm username has been set to "' .. input .. '".') end return end - local url = 'http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&format=json&limit=1&api_key=' .. config.lastfm_api_key .. '&user=' + local url = 'http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&format=json&limit=1&api_key=' .. self.config.lastfm_api_key .. '&user=' local username local output = '' if input then username = input - elseif database.users[msg.from.id_str].lastfm then - username = database.users[msg.from.id_str].lastfm + elseif self.database.users[msg.from.id_str].lastfm then + username = self.database.users[msg.from.id_str].lastfm elseif msg.from.username then username = msg.from.username output = '\n\nYour username has been set to ' .. username .. '.\nTo change it, use /fmset .' - database.users[msg.from.id_str].lastfm = username + self.database.users[msg.from.id_str].lastfm = username else - sendReply(msg, 'Please specify your last.fm username or set it with /fmset.') + bindings.sendReply(self, msg, 'Please specify your last.fm username or set it with /fmset.') return end url = url .. URL.escape(username) - jstr, res = HTTP.request(url) + local jstr, res + utilities.with_http_timeout( + 1, function () + jstr, res = HTTP.request(url) + end) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) if jdat.error then - sendReply(msg, 'Please specify your last.fm username or set it with /fmset.') + bindings.sendReply(self, msg, 'Please specify your last.fm username or set it with /fmset.') return end - local jdat = jdat.recenttracks.track[1] or jdat.recenttracks.track + jdat = jdat.recenttracks.track[1] or jdat.recenttracks.track if not jdat then - sendReply(msg, 'No history for this user.' .. output) + bindings.sendReply(self, msg, 'No history for this user.' .. output) return end @@ -95,13 +102,8 @@ local action = function(msg) end message = message .. title .. ' - ' .. artist .. output - sendMessage(msg.chat.id, message) + bindings.sendMessage(self, msg.chat.id, message) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return lastfm diff --git a/plugins/librefm.lua b/plugins/librefm.lua index ddd5d96..458335d 100644 --- a/plugins/librefm.lua +++ b/plugins/librefm.lua @@ -1,9 +1,21 @@ -if not database.librefm then - database.librefm = {} +local librefm = {} + +local HTTPS = require('ssl.https') +local URL = require('socket.url') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +function librefm:init() + if not self.database.librefm then + self.database.librefm = {} + end + + librefm.triggers = utilities.triggers(self.info.username):t('librefm', true):t('lnp', true):t('lfmset', true) end -local command = 'librefm' -local doc = [[``` +librefm.command = 'librefm' +librefm.doc = [[``` /lnp [username] Returns what you are or were last listening to. If you specify a username, info will be returned for that username. @@ -11,28 +23,22 @@ Returns what you are or were last listening to. If you specify a username, info Sets your libre.fm username. Otherwise, /np will use your Telegram username. Use "/fmset -" to delete it. ```]] -local triggers = { - '^/librefm[@'..bot.username..']*', - '^/lnp[@'..bot.username..']*', - '^/lfmset[@'..bot.username..']*' -} - -local action = function(msg) +function librefm:action(msg) local input = utilities.input(msg.text) if string.match(msg.text, '^/librefm') then - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, librefm.doc, true, msg.message_id, true) return elseif string.match(msg.text, '^/lfmset') then if not input then - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, librefm.doc, true, msg.message_id, true) elseif input == '-' then - database.lastfm[msg.from.id_str] = nil - sendReply(msg, 'Your libre.fm username has been forgotten.') + self.database.lastfm[msg.from.id_str] = nil + bindings.sendReply(self, msg, 'Your libre.fm username has been forgotten.') else - database.lastfm[msg.from.id_str] = input - sendReply(msg, 'Your libre.fm username has been set to "' .. input .. '".') + self.database.lastfm[msg.from.id_str] = input + bindings.sendReply(self, msg, 'Your libre.fm username has been set to "' .. input .. '".') end return end @@ -43,34 +49,34 @@ local action = function(msg) local output = '' if input then username = input - elseif database.lastfm[msg.from.id_str] then - username = database.lastfm[msg.from.id_str] + elseif self.database.lastfm[msg.from.id_str] then + username = self.database.lastfm[msg.from.id_str] elseif msg.from.username then username = msg.from.username output = '\n\nYour username has been set to ' .. username .. '.\nTo change it, use /lfmset .' - database.lastfm[msg.from.id_str] = username + self.database.lastfm[msg.from.id_str] = username else - sendReply(msg, 'Please specify your libre.fm username or set it with /lfmset.') + bindings.sendReply(self, msg, 'Please specify your libre.fm username or set it with /lfmset.') return end url = url .. URL.escape(username) - jstr, res = HTTPS.request(url) + local jstr, res = HTTPS.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) if jdat.error then - sendReply(msg, 'Please specify your libre.fm username or set it with /lfmset.') + bindings.sendReply(self, msg, 'Please specify your libre.fm username or set it with /lfmset.') return end - local jdat = jdat.recenttracks.track[1] or jdat.recenttracks.track + jdat = jdat.recenttracks.track[1] or jdat.recenttracks.track if not jdat then - sendReply(msg, 'No history for this user.' .. output) + bindings.sendReply(self, msg, 'No history for this user.' .. output) return end @@ -90,13 +96,8 @@ local action = function(msg) end message = message .. title .. ' - ' .. artist .. output - sendMessage(msg.chat.id, message) + bindings.sendMessage(self, msg.chat.id, message) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return librefm diff --git a/plugins/luarun.lua b/plugins/luarun.lua index e56a912..9200246 100644 --- a/plugins/luarun.lua +++ b/plugins/luarun.lua @@ -1,16 +1,21 @@ -local triggers = { - '^/lua[@'..bot.username..']*' -} +local luarun = {} -local action = function(msg) +local bindings = require('bindings') +local utilities = require('utilities') - if msg.from.id ~= config.admin then +function luarun:init() + luarun.triggers = utilities.triggers(self.info.username):t('lua', true).table +end + +function luarun:action(msg) + + if msg.from.id ~= self.config.admin then return end local input = utilities.input(msg.text) if not input then - sendReply(msg, 'Please enter a string to load.') + bindings.sendReply(self, msg, 'Please enter a string to load.') return end @@ -22,12 +27,9 @@ local action = function(msg) else output = '```\n' .. tostring(output) .. '\n```' end - sendMessage(msg.chat.id, output, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true) end -return { - action = action, - triggers = triggers -} +return luarun diff --git a/plugins/me.lua b/plugins/me.lua index 9c7c62e..7b93984 100644 --- a/plugins/me.lua +++ b/plugins/me.lua @@ -1,16 +1,20 @@ -local triggers = { - '^/me', - '^/me@'..bot.username -} +local me = {} -local action = function(msg) +local bindings = require('bindings') +local utilities = require('utilities') - local target = database.users[msg.from.id_str] +function me:init() + me.triggers = utilities.triggers(self.info.username):t('me', true).table +end - if msg.from.id == config.admin and (msg.reply_to_message or utilities.input(msg.text)) then - target = user_from_message(msg) +function me:action(msg) + + local target = self.database.users[msg.from.id_str] + + if msg.from.id == self.config.admin and (msg.reply_to_message or utilities.input(msg.text)) then + target = utilities.user_from_message(self, msg) if target.err then - sendReply(msg, target.err) + bindings.sendReply(self, msg, target.err) return end end @@ -19,11 +23,8 @@ local action = function(msg) for k,v in pairs(target) do output = output .. '*' .. k .. ':* `' .. tostring(v) .. '`\n' end - sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end -return { - triggers = triggers, - action = action -} +return me diff --git a/plugins/moderation.lua b/plugins/moderation.lua index 182f5b4..c8417f1 100755 --- a/plugins/moderation.lua +++ b/plugins/moderation.lua @@ -3,17 +3,18 @@ -- Put this near the top, after blacklist. -- If you want to enable antisquig, put that at the top, before blacklist. -if not database.moderation then - database.moderation = {} -end +local moderation = {} + +local bindings = require('bindings') +local utilities = require('utilities') local antisquig = {} local commands = { - ['^/modhelp[@'..bot.username..']*$'] = function(msg) + ['^/modhelp$'] = function(self, msg) - if not database.moderation[msg.chat.id_str] then return end + if not self.database.moderation[msg.chat.id_str] then return end local output = [[ *Users:* @@ -30,17 +31,17 @@ local commands = { ]] output = output:gsub('\t', '') - sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end, - ['^/modlist[@'..bot.username..']*$'] = function(msg) + ['^/modlist$'] = function(self, msg) - if not database.moderation[msg.chat.id_str] then return end + if not self.database.moderation[msg.chat.id_str] then return end local output = '' - for k,v in pairs(database.moderation[msg.chat.id_str]) do + for k,v in pairs(self.database.moderation[msg.chat.id_str]) do output = output .. '• ' .. v .. ' (' .. k .. ')\n' end @@ -48,76 +49,76 @@ local commands = { output = '*Moderators for* _' .. msg.chat.title .. '_ *:*\n' .. output end - output = output .. '*Administrators for* _' .. config.moderation.realm_name .. '_ *:*\n' - for k,v in pairs(config.moderation.admins) do + output = output .. '*Administrators for* _' .. self.config.moderation.realm_name .. '_ *:*\n' + for k,v in pairs(self.config.moderation.admins) do output = output .. '• ' .. v .. ' (' .. k .. ')\n' end - sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end, - ['^/modcast[@'..bot.username..']*'] = function(msg) + ['^/modcast'] = function(self, msg) local output = utilities.input(msg.text) if not output then return 'You must include a message.' end - if msg.chat.id ~= config.moderation.admin_group then + if msg.chat.id ~= self.config.moderation.admin_group then return 'This command must be run in the administration group.' end - if not config.moderation.admins[msg.from.id_str] then - return config.moderation.errors.not_admin + if not self.config.moderation.admins[msg.from.id_str] then + return self.config.moderation.errors.not_admin end output = '*Admin Broadcast:*\n' .. output - for k,v in pairs(database.moderation) do - sendMessage(k, output, true, nil, true) + for k,_ in pairs(self.database.moderation) do + bindings.sendMessage(self, k, output, true, nil, true) end return 'Your broadcast has been sent.' end, - ['^/modadd[@'..bot.username..']*$'] = function(msg) + ['^/modadd$'] = function(self, msg) - if not config.moderation.admins[msg.from.id_str] then - return config.moderation.errors.not_admin + if not self.config.moderation.admins[msg.from.id_str] then + return self.config.moderation.errors.not_admin end - if database.moderation[msg.chat.id_str] then + if self.database.moderation[msg.chat.id_str] then return 'I am already moderating this group.' end - database.moderation[msg.chat.id_str] = {} + self.database.moderation[msg.chat.id_str] = {} return 'I am now moderating this group.' end, - ['^/modrem[@'..bot.username..']*$'] = function(msg) + ['^/modrem$'] = function(self, msg) - if not config.moderation.admins[msg.from.id_str] then - return config.moderation.errors.not_admin + if not self.config.moderation.admins[msg.from.id_str] then + return self.config.moderation.errors.not_admin end - if not database.moderation[msg.chat.id_str] then - return config.moderation.errors.moderation + if not self.database.moderation[msg.chat.id_str] then + return self.config.moderation.errors.moderation end - database.moderation[msg.chat.id_str] = nil + self.database.moderation[msg.chat.id_str] = nil return 'I am no longer moderating this group.' end, - ['^/modprom[@'..bot.username..']*$'] = function(msg) + ['^/modprom$'] = function(self, msg) - if not database.moderation[msg.chat.id_str] then return end + if not self.database.moderation[msg.chat.id_str] then return end - if not config.moderation.admins[msg.from.id_str] then - return config.moderation.errors.not_admin + if not self.config.moderation.admins[msg.from.id_str] then + return self.config.moderation.errors.not_admin end if not msg.reply_to_message then @@ -127,26 +128,26 @@ local commands = { local modid = tostring(msg.reply_to_message.from.id) local modname = msg.reply_to_message.from.first_name - if config.moderation.admins[modid] then + if self.config.moderation.admins[modid] then return modname .. ' is already an administrator.' end - if database.moderation[msg.chat.id_str][modid] then + if self.database.moderation[msg.chat.id_str][modid] then return modname .. ' is already a moderator.' end - database.moderation[msg.chat.id_str][modid] = modname + self.database.moderation[msg.chat.id_str][modid] = modname return modname .. ' is now a moderator.' end, - ['^/moddem[@'..bot.username..']*'] = function(msg) + ['^/moddem'] = function(self, msg) - if not database.moderation[msg.chat.id_str] then return end + if not self.database.moderation[msg.chat.id_str] then return end - if not config.moderation.admins[msg.from.id_str] then - return config.moderation.errors.not_admin + if not self.config.moderation.admins[msg.from.id_str] then + return self.config.moderation.errors.not_admin end local modid = utilities.input(msg.text) @@ -159,28 +160,28 @@ local commands = { end end - if config.moderation.admins[modid] then - return config.moderation.admins[modid] .. ' is an administrator.' + if self.config.moderation.admins[modid] then + return self.config.moderation.admins[modid] .. ' is an administrator.' end - if not database.moderation[msg.chat.id_str][modid] then + if not self.database.moderation[msg.chat.id_str][modid] then return 'User is not a moderator.' end - local modname = database.moderation[msg.chat.id_str][modid] - database.moderation[msg.chat.id_str][modid] = nil + local modname = self.database.moderation[msg.chat.id_str][modid] + self.database.moderation[msg.chat.id_str][modid] = nil return modname .. ' is no longer a moderator.' end, - ['/modkick[@'..bot.username..']*'] = function(msg) + ['/modkick'] = function(self, msg) - if not database.moderation[msg.chat.id_str] then return end + if not self.database.moderation[msg.chat.id_str] then return end - if not database.moderation[msg.chat.id_str][msg.from.id_str] then - if not config.moderation.admins[msg.from.id_str] then - return config.moderation.errors.not_mod + if not self.database.moderation[msg.chat.id_str][msg.from.id_str] then + if not self.config.moderation.admins[msg.from.id_str] then + return self.config.moderation.errors.not_mod end end @@ -196,23 +197,23 @@ local commands = { return 'Kicks must be done via reply or specification of a user/bot\'s ID or username.' end - if database.moderation[msg.chat.id_str][userid] or config.moderation.admins[userid] then + if self.database.moderation[msg.chat.id_str][userid] or self.config.moderation.admins[userid] then return 'You cannot kick a moderator.' end - sendMessage(config.moderation.admin_group, '/kick ' .. userid .. ' from ' .. math.abs(msg.chat.id)) + bindings.sendMessage(self, self.config.moderation.admin_group, '/kick ' .. userid .. ' from ' .. math.abs(msg.chat.id)) - sendMessage(config.moderation.admin_group, usernm .. ' kicked from ' .. msg.chat.title .. ' by ' .. msg.from.first_name .. '.') + bindings.sendMessage(self, self.config.moderation.admin_group, usernm .. ' kicked from ' .. msg.chat.title .. ' by ' .. msg.from.first_name .. '.') end, - ['^/modban[@'..bot.username..']*'] = function(msg) + ['^/modban'] = function(self, msg) - if not database.moderation[msg.chat.id_str] then return end + if not self.database.moderation[msg.chat.id_str] then return end - if not database.moderation[msg.chat.id_str][msg.from.id_str] then - if not config.moderation.admins[msg.from.id_str] then - return config.moderation.errors.not_mod + if not self.database.moderation[msg.chat.id_str][msg.from.id_str] then + if not self.config.moderation.admins[msg.from.id_str] then + return self.config.moderation.errors.not_mod end end @@ -228,51 +229,64 @@ local commands = { return 'Kicks must be done via reply or specification of a user/bot\'s ID or username.' end - if database.moderation[msg.chat.id_str][userid] or config.moderation.admins[userid] then + if self.database.moderation[msg.chat.id_str][userid] or self.config.moderation.admins[userid] then return 'You cannot ban a moderator.' end - sendMessage(config.moderation.admin_group, '/ban ' .. userid .. ' from ' .. math.abs(msg.chat.id)) + bindings.sendMessage(self.config.moderation.admin_group, '/ban ' .. userid .. ' from ' .. math.abs(msg.chat.id)) - sendMessage(config.moderation.admin_group, usernm .. ' banned from ' .. msg.chat.title .. ' by ' .. msg.from.first_name .. '.') + bindings.sendMessage(self.config.moderation.admin_group, usernm .. ' banned from ' .. msg.chat.title .. ' by ' .. msg.from.first_name .. '.') end } -if config.moderation.antisquig then - commands['[\216-\219][\128-\191]'] = function(msg) +function moderation:init() + if not self.database.moderation then + self.database.moderation = {} + end - if not database.moderation[msg.chat.id_str] then return true end - if config.moderation.admins[msg.from.id_str] then return true end - if database.moderation[msg.chat.id_str][msg.from.id_str] then return true end + if self.config.moderation.antisquig then + commands['[\216-\219][\128-\191]'] = function(msg) + + if not self.database.moderation[msg.chat.id_str] then return true end + if self.config.moderation.admins[msg.from.id_str] then return true end + if self.database.moderation[msg.chat.id_str][msg.from.id_str] then return true end + + if antisquig[msg.from.id] == true then + return + end + antisquig[msg.from.id] = true + + bindings.sendReply(self, msg, self.config.moderation.errors.antisquig) + bindings.sendMessage(self, self.config.moderation.admin_group, '/kick ' .. msg.from.id .. ' from ' .. math.abs(msg.chat.id)) + bindings.sendMessage(self, self.config.moderation.admin_group, 'ANTISQUIG: ' .. msg.from.first_name .. ' kicked from ' .. msg.chat.title .. '.') - if antisquig[msg.from.id] == true then - return end - antisquig[msg.from.id] = true - - sendReply(msg, config.moderation.errors.antisquig) - sendMessage(config.moderation.admin_group, '/kick ' .. msg.from.id .. ' from ' .. math.abs(msg.chat.id)) - sendMessage(config.moderation.admin_group, 'ANTISQUIG: ' .. msg.from.first_name .. ' kicked from ' .. msg.chat.title .. '.') + end + moderation.triggers = {} + for trigger,_ in pairs(commands) do + if trigger[-1] == '$' then + moderation.triggers:insert(trigger:sub(1, -2)..'@'..self.info.username..'$') + else + moderation.triggers:insert(trigger..'%s+[^%s]*') + moderation.triggers:insert(trigger..'@'..self.info.username..'%s+[^%s]*') + moderation.triggers:insert(trigger..'$') + moderation.triggers:insert(trigger..'@'..self.info.username..'$') + end end end -local triggers = {} -for k,v in pairs(commands) do - table.insert(triggers, k) -end +function moderation:action(msg) -local action = function(msg) - - for k,v in pairs(commands) do - if string.match(msg.text_lower, k) then - local output = v(msg) + for trigger,command in pairs(commands) do + if string.match(msg.text_lower, trigger) then + local output = command(self, msg) if output == true then return true elseif output then - sendReply(msg, output) + bindings.sendReply(self, msg, output) end return end @@ -286,14 +300,10 @@ end -- That user will not be kicked again as long as his ID is in the table. -- The table is emptied every five seconds. -- Thus the bot will not spam the group or admin group when a user posts more than one infringing messages. -local cron = function() +function moderation:cron() antisquig = {} end -return { - action = action, - triggers = triggers, - cron = cron -} +return moderation diff --git a/plugins/nick.lua b/plugins/nick.lua index 74b6b71..603a04e 100755 --- a/plugins/nick.lua +++ b/plugins/nick.lua @@ -1,18 +1,23 @@ -local command = 'nick ' -local doc = [[``` +local nick = {} + +local bindings = require('bindings') +local utilities = require('utilities') + +nick.command = 'nick ' +nick.doc = [[``` /nick Set your nickname. Use "/nick --" to delete it. ```]] -local triggers = { - '^/nick[@'..bot.username..']*' -} +function nick:init() + nick.triggers = utilities.triggers(self.info.nick):t('nick', true).table +end -local action = function(msg) +function nick:action(msg) local target = msg.from - if msg.from.id == config.admin and msg.reply_to_message then + if msg.from.id == self.config.admin and msg.reply_to_message then target = msg.reply_to_message.from target.id_str = tostring(target.id) target.name = target.first_name @@ -24,28 +29,23 @@ local action = function(msg) local output local input = utilities.input(msg.text) if not input then - if database.users[target.id_str].nickname then - output = target.name .. '\'s nickname is "' .. database.users[target.id_str].nickname .. '".' + if self.database.users[target.id_str].nickname then + output = target.name .. '\'s nickname is "' .. self.database.users[target.id_str].nickname .. '".' else output = target.name .. ' currently has no nickname.' end elseif string.len(input) > 32 then output = 'The character limit for nicknames is 32.' elseif input == '--' or input == '—' then - database.users[target.id_str].nickname = nil + self.database.users[target.id_str].nickname = nil output = target.name .. '\'s nickname has been deleted.' else - database.users[target.id_str].nickname = input + self.database.users[target.id_str].nickname = input output = target.name .. '\'s nickname has been set to "' .. input .. '".' end - sendReply(msg, output) + bindings.sendReply(self, msg, output) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return nick diff --git a/plugins/patterns.lua b/plugins/patterns.lua index 74c024c..4000c60 100644 --- a/plugins/patterns.lua +++ b/plugins/patterns.lua @@ -1,11 +1,15 @@ -- Shout-out to Kenny, as I didn't want to write this until -- he upset himself over the very thought of me doing so. -local triggers = { +local patterns = {} + +local bindings = require('bindings') + +patterns.triggers = { '^/?s/.-/.-/?$' } -local action = function(msg) +function patterns:action(msg) if not msg.reply_to_message then return end local output = msg.reply_to_message.text or '' @@ -13,11 +17,8 @@ local action = function(msg) if not m2 then return true end output = output:gsub(m1, m2) output = 'Did you mean:\n"' .. output:sub(1, 4000) .. '"' - sendReply(msg.reply_to_message, output) + bindings.sendReply(self, msg.reply_to_message, output) end -return { - triggers = triggers, - action = action -} +return patterns diff --git a/plugins/ping.lua b/plugins/ping.lua index d39e961..5e4f8c8 100755 --- a/plugins/ping.lua +++ b/plugins/ping.lua @@ -1,15 +1,16 @@ -- Actually the simplest plugin ever! -local triggers = { - '^/ping[@'..bot.username..']*', - '^/annyong[@'..bot.username..']*' -} +local ping = {} -local action = function(msg) - sendMessage(msg.chat.id, msg.text_lower:match('^/ping') and 'Pong!' or 'Annyong.') +local utilities = require('utilities') +local bindings = require('bindings') + +function ping:init() + ping.triggers = utilities.triggers(self.info.username):t('ping'):t('annyong').table end -return { - action = action, - triggers = triggers -} +function ping:action(msg) + bindings.sendMessage(self, msg.chat.id, msg.text_lower:match('^/ping') and 'Pong!' or 'Annyong.') +end + +return ping diff --git a/plugins/pokedex.lua b/plugins/pokedex.lua index 1b06c9b..054fc6c 100755 --- a/plugins/pokedex.lua +++ b/plugins/pokedex.lua @@ -1,23 +1,29 @@ -local command = 'pokedex ' -local doc = [[``` +local pokedex = {} + +local HTTP = require('socket.http') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +pokedex.command = 'pokedex ' +pokedex.doc = [[``` /pokedex Returns a Pokedex entry from pokeapi.co. Alias: /dex ```]] -local triggers = { - '^/pokedex[@'..bot.username..']*', - '^/dex[@'..bot.username..']*' -} +function pokedex:init() + pokedex.triggers = utilities.triggers(self.info.username):t('pokedex', true):t('dex', true).table +end -local action = function(msg) +function pokedex:action(msg) local input = utilities.input(msg.text_lower) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, pokedex.doc, true, msg.message_id, true) return end end @@ -27,23 +33,23 @@ local action = function(msg) local dex_url = url .. '/api/v1/pokemon/' .. input local dex_jstr, res = HTTP.request(dex_url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local dex_jdat = JSON.decode(dex_jstr) local desc_url = url .. dex_jdat.descriptions[math.random(#dex_jdat.descriptions)].resource_uri - local desc_jstr, res = HTTP.request(desc_url) + local desc_jstr, _ = HTTP.request(desc_url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local desc_jdat = JSON.decode(desc_jstr) local poke_type - for i,v in ipairs(dex_jdat.types) do + for _,v in ipairs(dex_jdat.types) do local type_name = v.name:gsub("^%l", string.upper) if not poke_type then poke_type = type_name @@ -56,13 +62,8 @@ local action = function(msg) local output = '*' .. dex_jdat.name .. '*\n#' .. dex_jdat.national_id .. ' | ' .. poke_type .. '\n_' .. desc_jdat.description:gsub('POKMON', 'Pokémon'):gsub('Pokmon', 'Pokémon') .. '_' - sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(msg.chat.id, output, true, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return pokedex diff --git a/plugins/preview.lua b/plugins/preview.lua index 8ba335c..3a6fb0e 100644 --- a/plugins/preview.lua +++ b/plugins/preview.lua @@ -1,47 +1,48 @@ -local command = 'preview ' -local doc = [[``` +local preview = {} + +local HTTP = require('socket.http') +local bindings = require('bindings') +local utilities = require('utilities') + +preview.command = 'preview ' +preview.doc = [[``` /preview Returns a full-message, "unlinked" preview. ```]] -local triggers = { - '^/preview' -} +function preview:init() + preview.triggers = utilities.triggers(self.info.username):t('preview').table +end -local action = function(msg) +function preview:action(msg) local input = utilities.input(msg.text) if not input then - sendMessage(msg.chat.id, doc, true, nil, true) + bindings.sendMessage(self, msg.chat.id, preview.doc, true, nil, true) return end - input = get_word(input, 1) + input = utilities.get_word(input, 1) if not input:match('^https?://.+') then input = 'http://' .. input end local res = HTTP.request(input) if not res then - sendReply(msg, 'Please provide a valid link.') + bindings.sendReply(self, msg, 'Please provide a valid link.') return end if res:len() == 0 then - sendReply(msg, 'Sorry, the link you provided is not letting us make a preview.') + bindings.sendReply(self, msg, 'Sorry, the link you provided is not letting us make a preview.') return end -- Invisible zero-width, non-joiner. local output = '[​](' .. input .. ')' - sendMessage(msg.chat.id, output, false, nil, true) + bindings.sendMessage(self, msg.chat.id, output, false, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return preview diff --git a/plugins/pun.lua b/plugins/pun.lua index 715205f..f7c7c95 100755 --- a/plugins/pun.lua +++ b/plugins/pun.lua @@ -1,9 +1,14 @@ -local command = 'pun' -local doc = '`Returns a pun.`' +local pun = {} -local triggers = { - '^/pun[@'..bot.username..']*' -} +local bindings = require('bindings') +local utilities = require('utilities') + +pun.command = 'pun' +pun.doc = '`Returns a pun.`' + +function pun:init() + pun.triggers = utilities.triggers(self.info.username):t('pun').table +end local puns = { "The person who invented the door-knock won the No-bell prize.", @@ -129,15 +134,10 @@ local puns = { "In democracy, it's your vote that counts. In feudalism, it's your count that votes." } -local action = function(msg) +function pun:action(msg) - sendReply(msg, puns[math.random(#puns)]) + bindings.sendReply(self, msg, puns[math.random(#puns)]) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return pun diff --git a/plugins/reactions.lua b/plugins/reactions.lua index e3d4ba6..4ea2c55 100755 --- a/plugins/reactions.lua +++ b/plugins/reactions.lua @@ -3,38 +3,47 @@ -- You must never restructure. You must never disable this plugin. -- ~ Drew, creator, a year later. -local command = 'reactions' -local doc = '`Returns a list of "reaction" emoticon commands.`' +local reactions = {} -local triggers = { - ['¯\\_(ツ)_/¯'] = '/shrug', - ['( ͡° ͜ʖ ͡°)'] = '/lenny', - ['(╯°□°)╯︵ ┻━┻'] = '/flip', - ['┌(┌ ^o^)┐'] = '/homo', - ['ಠ_ಠ'] = '/look', - ['SHOTS FIRED'] = '/shots?' +local bindings = require('bindings') +local utilities = require('utilities') + +reactions.command = 'reactions' +reactions.doc = '`Returns a list of "reaction" emoticon commands.`' + +local mapping = { + ['shrug'] = '¯\\_(ツ)_/¯', + ['lenny'] = '( ͡° ͜ʖ ͡°)', + ['flip'] = '(╯°□°)╯︵ ┻━┻', + ['homo'] = '┌(┌ ^o^)┐', + ['look'] = 'ಠ_ಠ', + ['shots?'] = 'SHOTS FIRED' } - -- Generate a "help" message triggered by "/reactions". -local help = 'Reactions:\n' -for k,v in pairs(triggers) do - help = help .. '• ' .. v:gsub('%a%?', '') .. ': ' .. k .. '\n' - v = v .. '[@'..bot.username..']*' -end -triggers[help] = '^/reactions$' +local help -local action = function(msg) - for k,v in pairs(triggers) do - if string.match(msg.text_lower, v) then - sendMessage(msg.chat.id, k) +function reactions:init() + -- Generate a "help" message triggered by "/reactions". + local help = 'Reactions:\n' + reactions.triggers = utilities.triggers(self.info.username):t('reactions').table + for trigger,reaction in pairs(mapping) do + help = help .. '• ' .. trigger:gsub('.%?', '') .. ': ' .. reaction .. '\n' + reactions.triggers:insert(utilities.INVOCATION_PATTERN..trigger) + reactions.triggers:insert(utilities.INVOCATION_PATTERN..trigger..'@'..self.username) + end +end + +function reactions:action(msg) + if string.match(msg.text_lower, utilities.INVOCATION_PATTERN..'help') then + bindings.sendMessage(self, msg.chat.id, help) + return + end + for trigger,reaction in pairs(mapping) do + if string.match(msg.text_lower, utilities.INVOCATION_PATTERN..trigger) then + bindings.sendMessage(self, msg.chat.id, reaction) return end end end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return reactions diff --git a/plugins/reddit.lua b/plugins/reddit.lua index 037a14c..113a3a0 100755 --- a/plugins/reddit.lua +++ b/plugins/reddit.lua @@ -1,24 +1,29 @@ -local command = 'reddit [r/subreddit | query]' -local doc = [[``` +local reddit = {} + +local HTTP = require('socket.http') +local URL = require('socket.url') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +reddit.command = 'reddit [r/subreddit | query]' +reddit.doc = [[``` /reddit [r/subreddit | query] Returns the four (if group) or eight (if private message) top posts for the given subreddit or query, or from the frontpage. Aliases: /r, /r/[subreddit] ```]] -local triggers = { - '^/reddit[@'..bot.username..']*', - '^/r[@'..bot.username..']*$', - '^/r[@'..bot.username..']* ', - '^/r/' -} +function reddit:init() + reddit.triggers = utilities.triggers(self.info.username):t('reddit', true):t('r', true):t('r/', true).table +end -local action = function(msg) +function reddit:action(msg) msg.text_lower = msg.text_lower:gsub('/r/', '/r r/') - local input = utilities.input(msg.text_lower) + local input if msg.text_lower:match('^/r/') then msg.text_lower = msg.text_lower:gsub('/r/', '/r r/') - input = get_word(msg.text_lower, 1) + input = utilities.get_word(msg.text_lower, 1) else input = utilities.input(msg.text_lower) end @@ -45,18 +50,18 @@ local action = function(msg) local jstr, res = HTTP.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) if #jdat.data.children == 0 then - sendReply(msg, config.errors.results) + bindings.sendReply(self, msg, self.config.errors.results) return end local output = '' - for i,v in ipairs(jdat.data.children) do + for _,v in ipairs(jdat.data.children) do local title = v.data.title:gsub('%[', '('):gsub('%]', ')'):gsub('&', '&') if title:len() > 48 then title = title:sub(1,45) .. '...' @@ -73,13 +78,8 @@ local action = function(msg) output = source .. output - sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return reddit diff --git a/plugins/setandget.lua b/plugins/setandget.lua index b34b52a..e24cc9f 100644 --- a/plugins/setandget.lua +++ b/plugins/setandget.lua @@ -1,75 +1,74 @@ -database.setandget = database.setandget or {} +local setandget = {} -local command = 'set ' -local doc = [[``` +local bindings = require('bindings') +local utilities = require('utilities') + +function setandget:init() + self.database.setandget = self.database.setandget or {} + setandget.triggers = utilities.triggers(self.info.username):t('set', true):t('get', true).table +end + +setandget.command = 'set ' +setandget.doc = [[``` /set Stores a value with the given name. Use "/set --" to delete the stored value. /get [name] Returns the stored value or a list of stored values. ```]] -local triggers = { - '^/set', - '^/get' -} -local action = function(msg) +function setandget:action(msg) local input = utilities.input(msg.text) - database.setandget[msg.chat.id_str] = database.setandget[msg.chat.id_str] or {} + self.database.setandget[msg.chat.id_str] = self.database.setandget[msg.chat.id_str] or {} if msg.text_lower:match('^/set') then if not input then - sendMessage(msg.chat.id, doc, true, nil, true) + bindings.sendMessage(self, msg.chat.id, setandget.doc, true, nil, true) return end - local name = get_word(input:lower(), 1) + local name = utilities.get_word(input:lower(), 1) local value = utilities.input(input) if not name or not value then - sendMessage(msg.chat.id, doc, true, nil, true) + bindings.sendMessage(self, msg.chat.id, setandget.doc, true, nil, true) elseif value == '--' or value == '—' then - database.setandget[msg.chat.id_str][name] = nil - sendMessage(msg.chat.id, 'That value has been deleted.') + self.database.setandget[msg.chat.id_str][name] = nil + bindings.sendMessage(self, msg.chat.id, 'That value has been deleted.') else - database.setandget[msg.chat.id_str][name] = value - sendMessage(msg.chat.id, '"' .. name .. '" has been set to "' .. value .. '".', true) + self.database.setandget[msg.chat.id_str][name] = value + bindings.sendMessage(self, msg.chat.id, '"' .. name .. '" has been set to "' .. value .. '".', true) end elseif msg.text_lower:match('^/get') then if not input then local output - if table_size(database.setandget[msg.chat.id_str]) == 0 then + if utilities.table_size(self.database.setandget[msg.chat.id_str]) == 0 then output = 'No values have been stored here.' else output = '*List of stored values:*\n' - for k,v in pairs(database.setandget[msg.chat.id_str]) do + for k,v in pairs(self.database.setandget[msg.chat.id_str]) do output = output .. '• ' .. k .. ': `' .. v .. '`\n' end end - sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) return end local output - if database.setandget[msg.chat.id_str][input:lower()] then - output = '`' .. database.setandget[msg.chat.id_str][input:lower()] .. '`' + if self.database.setandget[msg.chat.id_str][input:lower()] then + output = '`' .. self.database.setandget[msg.chat.id_str][input:lower()] .. '`' else output = 'There is no value stored by that name.' end - sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return setandget diff --git a/plugins/shell.lua b/plugins/shell.lua index 1622d08..b1b90b0 100644 --- a/plugins/shell.lua +++ b/plugins/shell.lua @@ -1,10 +1,15 @@ -local triggers = { - '^/run[@'..bot.username..']*' -} +local shell = {} -local action = function(msg) +local bindings = require('bindings') +local utilities = require('utilities') - if msg.from.id ~= config.admin then +function shell:init() + shell.triggers = utilities.bindings(self.info.username):t('run', true).table +end + +function shell:action(msg) + + if msg.from.id ~= self.config.admin then return end @@ -12,7 +17,7 @@ local action = function(msg) input = input:gsub('—', '--') if not input then - sendReply(msg, 'Please specify a command to run.') + bindings.sendReply(self, msg, 'Please specify a command to run.') return end @@ -22,11 +27,8 @@ local action = function(msg) else output = '```\n' .. output .. '\n```' end - sendMessage(msg.chat.id, output, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true) end -return { - action = action, - triggers = triggers -} +return shell diff --git a/plugins/shout.lua b/plugins/shout.lua index 873d7ac..ca9b887 100644 --- a/plugins/shout.lua +++ b/plugins/shout.lua @@ -1,19 +1,24 @@ -local command = 'shout ' -local doc = [[``` +local shout = {} + +local bindings = require('bindings') +local utilities = require('utilities') + +shout.command = 'shout ' +shout.doc = [[``` /shout Shouts something. ```]] -local triggers = { - '^/shout[@'..bot.username..']*' -} +function shout:init() + shout.triggers = utilities.triggers(self.info.username):t('shout', true) +end -local action = function(msg) +function shout:action(msg) local input = utilities.input(msg.text) if not input then - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, shout.doc, true, msg.message_id, true) return end input = input:trim() @@ -31,20 +36,15 @@ local action = function(msg) output = output .. '\n' for match in input:sub(2):gmatch('([%z\1-\127\194-\244][\128-\191]*)') do local spacing = '' - for i = 1, inc do + for _ = 1, inc do spacing = spacing .. ' ' end inc = inc + 1 output = output .. match .. ' ' .. spacing .. match .. '\n' end output = '```\n' .. output:trim() .. '\n```' - sendMessage(msg.chat.id, output, true, false, true) + bindings.sendMessage(self, msg.chat.id, output, true, false, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return shout diff --git a/plugins/slap.lua b/plugins/slap.lua index 819df66..91a1920 100755 --- a/plugins/slap.lua +++ b/plugins/slap.lua @@ -1,12 +1,17 @@ -local command = 'slap [target]' -local doc = [[``` +local slap = {} + +local bindings = require('bindings') +local utilities = require('utilities') + +slap.command = 'slap [target]' +slap.doc = [[``` /slap [target] Slap somebody. ```]] -local triggers = { - '^/slap[@'..bot.username..']*' -} +function slap:init() + slap.triggers = utilities.triggers(self.info.username):t('slap', true).table +end local slaps = { 'VICTIM was shot by VICTOR.', @@ -92,40 +97,35 @@ local slaps = { 'Cowards die many times before their death. VICTIM never tasted death but once.' } -local action = function(msg) +function slap:action(msg) local victim = utilities.input(msg.text) if msg.reply_to_message then - if database.users[tostring(msg.reply_to_message.from.id)].nickname then - victim = database.users[tostring(msg.reply_to_message.from.id)].nickname + if self.database.users[tostring(msg.reply_to_message.from.id)].nickname then + victim = self.database.users[tostring(msg.reply_to_message.from.id)].nickname else victim = msg.reply_to_message.from.first_name end end local victor = msg.from.first_name - if database.users[msg.from.id_str].nickname then - victor = database.users[msg.from.id_str].nickname + if self.database.users[msg.from.id_str].nickname then + victor = self.database.users[msg.from.id_str].nickname end if not victim then victim = victor - victor = bot.first_name + victor = self.info.first_name end local message = slaps[math.random(#slaps)] message = message:gsub('VICTIM', victim) message = message:gsub('VICTOR', victor) - message = latcyr(message) + message = utilities.latcyr(message) - sendMessage(msg.chat.id, message) + bindings.sendMessage(self, msg.chat.id, message) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return slap diff --git a/plugins/time.lua b/plugins/time.lua index 05c7c2b..fe17cdb 100755 --- a/plugins/time.lua +++ b/plugins/time.lua @@ -1,28 +1,35 @@ -local command = 'time ' -local doc = [[``` +local time = {} + +local HTTPS = require('ssl.https') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +time.command = 'time ' +time.doc = [[``` /time Returns the time, date, and timezone for the given location. ```]] -local triggers = { - '^/time[@'..bot.username..']*' -} +function time:init() + time.triggers = utilities.triggers(self.info.username):t('time', true).table +end -local action = function(msg) +function time:action(msg) local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, time.doc, true, msg.message_id, true) return end end - local coords = get_coords(input) + local coords = utilities.get_coords(self, input) if type(coords) == 'string' then - sendReply(msg, coords) + bindings.sendReply(self, msg, coords) return end @@ -30,26 +37,21 @@ local action = function(msg) local jstr, res = HTTPS.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) - local timestamp = os.time() + jdat.rawOffset + jdat.dstOffset + config.time_offset + local timestamp = os.time() + jdat.rawOffset + jdat.dstOffset + self.config.time_offset local utcoff = (jdat.rawOffset + jdat.dstOffset) / 3600 if utcoff == math.abs(utcoff) then utcoff = '+' .. utcoff end local message = os.date('%I:%M %p\n', timestamp) .. os.date('%A, %B %d, %Y\n', timestamp) .. jdat.timeZoneName .. ' (UTC' .. utcoff .. ')' - sendReply(msg, message) + bindings.sendReply(self.msg, message) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return time diff --git a/plugins/translate.lua b/plugins/translate.lua index 2be913b..f881c2d 100755 --- a/plugins/translate.lua +++ b/plugins/translate.lua @@ -1,50 +1,52 @@ -local command = 'translate [text]' -local doc = [[``` +local translate = {} + +local HTTPS = require('ssl.https') +local URL = require('socket.url') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +translate.command = 'translate [text]' +translate.doc = [[``` /translate [text] Translates input or the replied-to message into the bot's language. ```]] -local triggers = { - '^/translate[@'..bot.username..']*', - '^/tl[@'..bot.username..']*' -} +function translate:init() + translate.triggers = utilities.triggers(self.info.username):t('translate', true):t('tl', true).table +end -local action = function(msg) +function translate:action(msg) local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, translate.doc, true, msg.message_id, true) return end end - local url = 'https://translate.yandex.net/api/v1.5/tr.json/translate?key=' .. config.yandex_key .. '&lang=' .. config.lang .. '&text=' .. URL.escape(input) + local url = 'https://translate.yandex.net/api/v1.5/tr.json/translate?key=' .. self.config.yandex_key .. '&lang=' .. self.config.lang .. '&text=' .. URL.escape(input) local str, res = HTTPS.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(str) if jdat.code ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local output = jdat.text[1] output = 'Translation:\n"' .. output .. '"' - sendReply(msg.reply_to_message or msg, output) + bindings.sendReply(self, msg.reply_to_message or msg, output) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return translate diff --git a/plugins/urbandictionary.lua b/plugins/urbandictionary.lua index 9b2f94d..4b34a37 100755 --- a/plugins/urbandictionary.lua +++ b/plugins/urbandictionary.lua @@ -1,25 +1,30 @@ -local command = 'urbandictionary ' -local doc = [[``` +local urbandictionary = {} + +local HTTP = require('socket.http') +local URL = require('socket.url') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +urbandictionary.command = 'urbandictionary ' +urbandictionary.doc = [[``` /urbandictionary Returns a definition from Urban Dictionary. Aliases: /ud, /urban ```]] -local triggers = { - '^/urbandictionary[@'..bot.username..']*', - '^/ud[@'..bot.username..']*$', - '^/ud[@'..bot.username..']* ', - '^/urban[@'..bot.username..']*' -} +function urbandictionary:init() + urbandictionary.triggers = utilities.triggers(self.info.username):t('urbandictionary', true):t('ud', true):t('urban', true).table +end -local action = function(msg) +function urbandictionary:action(msg) local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, urbandictionary.doc, true, msg.message_id, true) return end end @@ -28,13 +33,13 @@ local action = function(msg) local jstr, res = HTTP.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) if jdat.result_type == "no_results" then - sendReply(msg, config.errors.results) + bindings.sendReply(self, msg, self.config.errors.results) return end @@ -45,13 +50,8 @@ local action = function(msg) output = output:gsub('%[', ''):gsub('%]', '') - sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return urbandictionary diff --git a/plugins/weather.lua b/plugins/weather.lua index 8199624..0e4414c 100755 --- a/plugins/weather.lua +++ b/plugins/weather.lua @@ -1,48 +1,55 @@ -if not config.owm_api_key then - print('Missing config value: owm_api_key.') - print('weather.lua will not be enabled.') - return +local weather = {} + +local HTTP = require('socket.http') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +function weather:init() + if not self.config.owm_api_key then + print('Missing config value: owm_api_key.') + print('weather.lua will not be enabled.') + return + end + + weather.triggers = utilities.triggers(self.info.username):t('weather', true).table end -local command = 'weather ' -local doc = [[``` +weather.command = 'weather ' +weather.doc = [[``` /weather Returns the current weather conditions for a given location. ```]] -local triggers = { - '^/weather[@'..bot.username..']*' -} - -local action = function(msg) +function weather:action(msg) local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, weather.doc, true, msg.message_id, true) return end end - local coords = get_coords(input) + local coords = utilities.get_coords(self, input) if type(coords) == 'string' then - sendReply(msg, coords) + bindings.sendReply(self, msg, coords) return end - local url = 'http://api.openweathermap.org/data/2.5/weather?APPID=' .. config.owm_api_key .. '&lat=' .. coords.lat .. '&lon=' .. coords.lon + local url = 'http://api.openweathermap.org/data/2.5/weather?APPID=' .. self.config.owm_api_key .. '&lat=' .. coords.lat .. '&lon=' .. coords.lon local jstr, res = HTTP.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) if jdat.cod ~= 200 then - sendReply(msg, 'Error: City not found.') + bindings.sendReply(self, msg, 'Error: City not found.') return end @@ -50,13 +57,8 @@ local action = function(msg) local fahrenheit = string.format('%.2f', celsius * (9/5) + 32) local message = celsius .. '°C | ' .. fahrenheit .. '°F, ' .. jdat.weather[1].description .. '.' - sendReply(msg, message) + bindings.sendReply(self, msg, message) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return weather diff --git a/plugins/whoami.lua b/plugins/whoami.lua index c7fc247..ed26d92 100755 --- a/plugins/whoami.lua +++ b/plugins/whoami.lua @@ -1,18 +1,23 @@ -local command = 'whoami' -local doc = [[``` +local whoami = {} + +local bindings = require('bindings') +local utilities = require('utilities') + +whoami.command = 'whoami' +whoami.doc = [[``` Returns user and chat info for you or the replied-to message. Alias: /who ```]] -local triggers = { - '^/who[ami]*[@'..bot.username..']*$' -} +function whoami:init() + whoami.triggers = utilities.triggers(self.info.username):t('who', true):t('whoami').table +end -local action = function(msg) +function whoami:action(msg) if msg.reply_to_message then msg = msg.reply_to_message - msg.from.name = build_name(msg.from.first_name, msg.from.last_name) + msg.from.name = utilities.build_name(self, msg.from.first_name, msg.from.last_name) end local chat_id = math.abs(msg.chat.id) @@ -22,7 +27,7 @@ local action = function(msg) local user = 'You are @%s, also known as *%s* `[%s]`' if msg.from.username then - user = user:format(markdown_escape(msg.from.username), msg.from.name, msg.from.id) + user = user:format(utilities.markdown_escape(msg.from.username), msg.from.name, msg.from.id) else user = 'You are *%s* `[%s]`,' user = user:format(msg.from.name, msg.from.id) @@ -30,9 +35,9 @@ local action = function(msg) local group = '@%s, also known as *%s* `[%s]`.' if msg.chat.type == 'private' then - group = group:format(markdown_escape(bot.username), bot.first_name, bot.id) + group = group:format(utilities.markdown_escape(self.info.username), self.info.first_name, self.info.id) elseif msg.chat.username then - group = group:format(markdown_escape(msg.chat.username), msg.chat.title, chat_id) + group = group:format(utilities.markdown_escape(msg.chat.username), msg.chat.title, chat_id) else group = '*%s* `[%s]`.' group = group:format(msg.chat.title, chat_id) @@ -40,13 +45,8 @@ local action = function(msg) local output = user .. ', and you are messaging ' .. group - sendMessage(msg.chat.id, output, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return whoami diff --git a/plugins/wikipedia.lua b/plugins/wikipedia.lua index 4dfd882..1066f75 100755 --- a/plugins/wikipedia.lua +++ b/plugins/wikipedia.lua @@ -1,25 +1,30 @@ -local command = 'wikipedia ' -local doc = [[``` +local wikipedia = {} + +local HTTPS = require('ssl.https') +local URL = require('socket.url') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +wikipedia.command = 'wikipedia ' +wikipedia.doc = [[``` /wikipedia Returns an article from Wikipedia. Aliases: /w, /wiki ```]] -local triggers = { - '^/wikipedia[@'..bot.username..']*', - '^/wiki[@'..bot.username..']*', - '^/w[@'..bot.username..']*$', - '^/w[@'..bot.username..']* ' -} +function wikipedia:init() + wikipedia.triggers = utilities.triggers(self.info.username):t('wikipedia', true):t('wiki', true):t('w', true).table +end -local action = function(msg) +function wikipedia:action(msg) local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, wikipedia.doc, true, msg.message_id, true) return end end @@ -29,17 +34,17 @@ local action = function(msg) local jstr, res = HTTPS.request(gurl .. URL.escape(input)) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) if not jdat.responseData then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end if not jdat.responseData.results[1] then - sendReply(msg, config.errors.results) + bindings.sendReply(self, msg, self.config.errors.results) return end @@ -49,18 +54,18 @@ local action = function(msg) -- 'https://en.wikipedia.org/wiki/':len() == 30 jstr, res = HTTPS.request(wurl .. url:sub(31)) if res ~= 200 then - sendReply(msg, config.error.connection) + bindings.sendReply(self, msg, self.config.error.connection) return end + local _ local text = JSON.decode(jstr).query.pages - for k,v in pairs(text) do - text = v.extract - break -- Seriously, there's probably a way more elegant solution. - end + _, text = next(text) if not text then - sendReply(msg, config.errors.results) + bindings.sendReply(self, msg, self.config.errors.results) return + else + text = text.extract end text = text:gsub('', '') @@ -78,13 +83,8 @@ local action = function(msg) output = output .. '[Read more.](' .. url .. ')' end - sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return wikipedia diff --git a/plugins/xkcd.lua b/plugins/xkcd.lua index a8c0903..d6b3c20 100755 --- a/plugins/xkcd.lua +++ b/plugins/xkcd.lua @@ -1,20 +1,29 @@ -local command = 'xkcd [query]' -local doc = [[``` +local xkcd = {} + +local HTTP = require('socket.http') +local HTTPS = require('ssl.https') +local URL = require('socket.url') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +xkcd.command = 'xkcd [query]' +xkcd.doc = [[``` /xkcd [query] Returns an xkcd strip and its alt text. If there is no query, it will be randomized. ```]] -local triggers = { - '^/xkcd[@'..bot.username..']*' -} +function xkcd:init() + xkcd.triggers = utilities.triggers(self.info.username):t('xkcd', true).table +end -local action = function(msg) +function xkcd:action(msg) local input = utilities.input(msg.text) local jstr, res = HTTP.request('http://xkcd.com/info.0.json') if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end @@ -23,14 +32,14 @@ local action = function(msg) if input then local url = 'https://ajax.googleapis.com/ajax/services/search/web?v=1.0&safe=active&q=site%3axkcd%2ecom%20' .. URL.escape(input) - local jstr, res = HTTPS.request(url) + jstr, res = HTTPS.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) if #jdat.responseData.results == 0 then - sendReply(msg, config.errors.results) + bindings.sendReply(self, msg, self.config.errors.results) return end res_url = jdat.responseData.results[1].url .. 'info.0.json' @@ -38,22 +47,17 @@ local action = function(msg) res_url = 'http://xkcd.com/' .. math.random(latest) .. '/info.0.json' end - local jstr, res = HTTP.request(res_url) + jstr, res = HTTP.request(res_url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) local output = '[' .. jdat.num .. '](' .. jdat.img .. ')\n' .. jdat.alt - sendMessage(msg.chat.id, output, false, nil, true) + bindings.sendMessage(self, msg.chat.id, output, false, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return xkcd diff --git a/plugins/youtube.lua b/plugins/youtube.lua index 0bbbe49..63a7e49 100755 --- a/plugins/youtube.lua +++ b/plugins/youtube.lua @@ -1,47 +1,55 @@ -- Thanks to @TiagoDanin for writing the original plugin. -if not config.google_api_key then - print('Missing config value: google_api_key.') - print('youtube.lua will not be enabled.') - return +local youtube = {} + +local HTTPS = require('ssl.https') +local URL = require('socket.url') +local JSON = require('cjson') +local bindings = require('bindings') +local utilities = require('utilities') + +function youtube:init() + if not self.config.google_api_key then + print('Missing config value: google_api_key.') + print('youtube.lua will not be enabled.') + return + end end -local command = 'youtube ' -local doc = [[``` +youtube.command = 'youtube ' +youtube.doc = [[``` /youtube Returns the top result from YouTube. Alias: /yt ```]] -local triggers = { - '^/youtube[@'..bot.username..']*', - '^/yt[@'..bot.username..']*$', - '^/yt[@'..bot.username..']* ' -} +function youtube:init() + youtube.triggers = utilities.triggers(self.info.username):t('youtube', true):t('yt', true).table +end -local action = function(msg) +function youtube:action(msg) local input = utilities.input(msg.text) if not input then if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text else - sendMessage(msg.chat.id, doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, youtube.doc, true, msg.message_id, true) return end end - local url = 'https://www.googleapis.com/youtube/v3/search?key=' .. config.google_api_key .. '&type=video&part=snippet&maxResults=4&q=' .. URL.escape(input) + local url = 'https://www.googleapis.com/youtube/v3/search?key=' .. self.config.google_api_key .. '&type=video&part=snippet&maxResults=4&q=' .. URL.escape(input) local jstr, res = HTTPS.request(url) if res ~= 200 then - sendReply(msg, config.errors.connection) + bindings.sendReply(self, msg, self.config.errors.connection) return end local jdat = JSON.decode(jstr) if jdat.pageInfo.totalResults == 0 then - sendReply(msg, config.errors.results) + bindings.sendReply(self, msg, self.config.errors.results) return end @@ -50,13 +58,8 @@ local action = function(msg) vid_title = vid_title:gsub('%(.+%)',''):gsub('%[.+%]','') local output = '[' .. vid_title .. '](' .. vid_url .. ')' - sendMessage(msg.chat.id, output, false, nil, true) + bindings.sendMessage(self, msg.chat.id, output, false, nil, true) end -return { - action = action, - triggers = triggers, - doc = doc, - command = command -} +return youtube diff --git a/utilities.lua b/utilities.lua index 8527602..a9efe17 100755 --- a/utilities.lua +++ b/utilities.lua @@ -287,9 +287,16 @@ function utilities.triggers_metatable:t(pattern, has_args) return self end -function utilities.triggers(username) +function utilities.triggers(username, trigger_table) local self = setmetatable({}, utilities.triggers_metatable) self.username = username - self.table = {} + self.table = trigger_table or {} return self end + +function utilities.with_http_timeout(timeout, fun) + local original = HTTP.TIMEOUT + HTTP.TIMEOUT = timeout + fun() + HTTP.TIMEOUT = original +end From 0e8a2693fbcba74d5696e1cb28e2d87b2776e13a Mon Sep 17 00:00:00 2001 From: Brayden Date: Mon, 11 Apr 2016 08:02:21 -0700 Subject: [PATCH 3/9] Make plugin.cron be called with the instance --- bot.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bot.lua b/bot.lua index 4ce00c2..b82b8b8 100755 --- a/bot.lua +++ b/bot.lua @@ -138,7 +138,7 @@ while instance.is_started do -- Start a loop while the bot should be running. utilities.save_data(instance.info.username..'.db', instance.database) -- Save the database. for i,v in ipairs(instance.plugins) do if v.cron then -- Call each plugin's cron function, if it has one. - local res, err = pcall(function() v.cron() end) + local res, err = pcall(function() v.cron(instance) end) if not res then utilities.handle_exception(instance, err, 'CRON: ' .. i) end From fbe933f5ecadc2c1ac20ea1858b587a10df6bdda Mon Sep 17 00:00:00 2001 From: Brayden Banks Date: Mon, 11 Apr 2016 20:55:46 -0700 Subject: [PATCH 4/9] Final(?) fixes. --- plugins/administration.lua | 2 +- plugins/cats.lua | 6 +++--- plugins/dice.lua | 2 +- plugins/dilbert.lua | 2 +- plugins/floodcontrol.lua | 2 +- plugins/gImages.lua | 4 ++-- plugins/hackernews.lua | 4 +++- plugins/help.lua | 2 +- plugins/pokedex.lua | 2 +- plugins/shout.lua | 2 +- plugins/youtube.lua | 6 ++---- 11 files changed, 17 insertions(+), 17 deletions(-) diff --git a/plugins/administration.lua b/plugins/administration.lua index 3d56316..9e61c76 100644 --- a/plugins/administration.lua +++ b/plugins/administration.lua @@ -1132,7 +1132,7 @@ function administration:action(msg) end function administration:cron() - self.temp.flood = {} + self.admin_temp.flood = {} end administration.command = 'groups' diff --git a/plugins/cats.lua b/plugins/cats.lua index 9e05146..a43b97c 100755 --- a/plugins/cats.lua +++ b/plugins/cats.lua @@ -4,18 +4,18 @@ local HTTP = require('socket.http') local bindings = require('bindings') local utilities = require('utilities') -function bindings:init() +function cats:init() if not self.config.thecatapi_key then print('Missing config value: thecatapi_key.') print('cats.lua will be enabled, but there are more features with a key.') end + + cats.triggers = utilities.triggers(self.info.username):t('cat').table end cats.command = 'cat' cats.doc = '`Returns a cat!`' -cats.triggers = utilities.triggers():t('cat').table - function cats:action(msg) local url = 'http://thecatapi.com/api/images/get?format=html&type=jpg' diff --git a/plugins/dice.lua b/plugins/dice.lua index 296743f..2e5689b 100755 --- a/plugins/dice.lua +++ b/plugins/dice.lua @@ -17,7 +17,7 @@ function dice:action(msg) local input = utilities.input(msg.text_lower) if not input then - bindings.sendMessage(msg.chat.id, dice.doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, dice.doc, true, msg.message_id, true) return end diff --git a/plugins/dilbert.lua b/plugins/dilbert.lua index ea227e5..e3b9fac 100644 --- a/plugins/dilbert.lua +++ b/plugins/dilbert.lua @@ -19,7 +19,7 @@ end function dilbert:action(msg) - bindings.sendChatAction(msg.chat.id, 'upload_photo') + bindings.sendChatAction(self, msg.chat.id, 'upload_photo') local input = utilities.input(msg.text) if not input then input = os.date('%F') end diff --git a/plugins/floodcontrol.lua b/plugins/floodcontrol.lua index 7b03b14..1af204d 100755 --- a/plugins/floodcontrol.lua +++ b/plugins/floodcontrol.lua @@ -7,7 +7,7 @@ local JSON = require('cjson') local utilities = require('utilities') function floodcontrol:init() - self.floodcontrol = floodcontrol or {} + self.floodcontrol = self.floodcontrol or {} end floodcontrol.triggers = { diff --git a/plugins/gImages.lua b/plugins/gImages.lua index 777385f..ab36742 100755 --- a/plugins/gImages.lua +++ b/plugins/gImages.lua @@ -1,5 +1,5 @@ -- You need a Google API key and a Google Custom Search Engine set up to use this, in config.google_api_key and config.google_cse_key, respectively. - -- You must also sign up for the CSE in the Google Developer Concsole, and enable image results. + -- You must also sign up for the CSE in the Google Developer Console, and enable image results. local gImages = {} @@ -20,7 +20,7 @@ function gImages:init() return end - gImages.triggers = utilities.triggers():t('image', true):t('i', true):t('insfw', true).table + gImages.triggers = utilities.triggers(self.info.username):t('image', true):t('i', true):t('insfw', true).table end gImages.command = 'image ' diff --git a/plugins/hackernews.lua b/plugins/hackernews.lua index f68a458..1029094 100755 --- a/plugins/hackernews.lua +++ b/plugins/hackernews.lua @@ -11,7 +11,9 @@ Returns four (if group) or eight (if private message) top stories from Hacker Ne Alias: /hn ```]] -hackernews.triggers = utilities.triggers():t('hackernews', true):t('hn', true).table +function hackernews:init() + hackernews.triggers = utilities.triggers(self.info.username):t('hackernews', true):t('hn', true).table +end function hackernews:action(msg) diff --git a/plugins/help.lua b/plugins/help.lua index bb923fc..a84bf78 100755 --- a/plugins/help.lua +++ b/plugins/help.lua @@ -15,7 +15,7 @@ function help:init() end end - help.triggers = utilities.triggers():t('help', true):t('h', true).table + help.triggers = utilities.triggers(self.info.username):t('help', true):t('h', true).table end help_text = help_text .. [[ diff --git a/plugins/pokedex.lua b/plugins/pokedex.lua index 054fc6c..9e9f128 100755 --- a/plugins/pokedex.lua +++ b/plugins/pokedex.lua @@ -62,7 +62,7 @@ function pokedex:action(msg) local output = '*' .. dex_jdat.name .. '*\n#' .. dex_jdat.national_id .. ' | ' .. poke_type .. '\n_' .. desc_jdat.description:gsub('POKMON', 'Pokémon'):gsub('Pokmon', 'Pokémon') .. '_' - bindings.sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end diff --git a/plugins/shout.lua b/plugins/shout.lua index ca9b887..eb08293 100644 --- a/plugins/shout.lua +++ b/plugins/shout.lua @@ -10,7 +10,7 @@ Shouts something. ```]] function shout:init() - shout.triggers = utilities.triggers(self.info.username):t('shout', true) + shout.triggers = utilities.triggers(self.info.username):t('shout', true).table end function shout:action(msg) diff --git a/plugins/youtube.lua b/plugins/youtube.lua index 63a7e49..ee7a41f 100755 --- a/plugins/youtube.lua +++ b/plugins/youtube.lua @@ -14,6 +14,8 @@ function youtube:init() print('youtube.lua will not be enabled.') return end + + youtube.triggers = utilities.triggers(self.info.username):t('youtube', true):t('yt', true).table end youtube.command = 'youtube ' @@ -23,10 +25,6 @@ Returns the top result from YouTube. Alias: /yt ```]] -function youtube:init() - youtube.triggers = utilities.triggers(self.info.username):t('youtube', true):t('yt', true).table -end - function youtube:action(msg) local input = utilities.input(msg.text) From 1dc61d2c44e6b574c1e6933e572dc7ea420fabc8 Mon Sep 17 00:00:00 2001 From: Brayden Banks Date: Wed, 13 Apr 2016 20:48:20 -0700 Subject: [PATCH 5/9] Final fixes. --- bindings.lua | 12 ++++---- bot.lua | 54 ++++++++++++++++++----------------- config.lua | 58 ++++++++++++++++++-------------------- launch.sh | 2 +- main.lua | 5 ++++ plugins/administration.lua | 8 +++--- plugins/echo.lua | 2 +- plugins/help.lua | 13 +++++---- plugins/luarun.lua | 2 +- plugins/moderation.lua | 10 +++---- plugins/nick.lua | 2 +- plugins/reactions.lua | 4 +-- plugins/shell.lua | 2 +- plugins/time.lua | 4 ++- plugins/whoami.lua | 2 +- utilities.lua | 17 ++++++----- 16 files changed, 105 insertions(+), 92 deletions(-) create mode 100644 main.lua diff --git a/bindings.lua b/bindings.lua index 9cf8974..2baf84b 100755 --- a/bindings.lua +++ b/bindings.lua @@ -75,7 +75,7 @@ function bindings:sendChatAction(chat_id, action) -- Support actions are typing, upload_photo, record_video, upload_video, record_audio, upload_audio, upload_document, find_location local url = self.BASE_URL .. '/sendChatAction?chat_id=' .. chat_id .. '&action=' .. action - return bindings.sendRequest(self, url) + return bindings.sendRequest(url) end @@ -94,7 +94,7 @@ function bindings:sendLocation(chat_id, latitude, longitude, reply_to_message_id url = url .. '&disable_notification=true' end - return bindings.sendRequest(self, url) + return bindings.sendRequest(url) end @@ -106,18 +106,18 @@ function bindings:forwardMessage(chat_id, from_chat_id, message_id, disable_noti url = url .. '&disable_notification=true' end - return bindings.sendRequest(self, url) + return bindings.sendRequest(url) end function bindings:kickChatMember(chat_id, user_id) local url = self.BASE_URL .. '/kickChatMember?chat_id=' .. chat_id .. '&user_id=' .. user_id - return bindings.sendRequest(self, url) + return bindings.sendRequest(url) end function bindings:unbanChatMember(chat_id, user_id) local url = self.BASE_URL .. '/unbanChatMember?chat_id=' .. chat_id .. '&user_id=' .. user_id - return bindings.sendRequest(self, url) + return bindings.sendRequest(url) end -- TODO: More of this. @@ -138,7 +138,7 @@ function bindings:sendPhotoID(chat_id, file_id, caption, reply_to_message_id, di url = url .. '&disable_notification=true' end - return bindings.sendRequest(self, url) + return bindings.sendRequest(url) end diff --git a/bot.lua b/bot.lua index 3e91658..25f10f6 100755 --- a/bot.lua +++ b/bot.lua @@ -1,7 +1,5 @@ local bot = {} -local instance = {} - local bindings = require('bindings') -- Load Telegram bindings. local utilities = require('utilities') -- Load miscellaneous and cross-plugin functions. @@ -27,7 +25,7 @@ function bot:init() -- The function run when the bot is started or reloaded. self.plugins = {} -- Load plugins. for _,v in ipairs(self.config.plugins) do - local p = require('plugins/'..v) + local p = require('plugins.'..v) table.insert(self.plugins, p) if p.init then p.init(self) end end @@ -77,7 +75,7 @@ function bot:on_msg_receive(msg) -- The fn run whenever a message is received. end) if not success then bindings.sendReply(self, msg, 'Sorry, an unexpected error occurred.') - bindings.handle_exception(self, result, msg.from.id .. ': ' .. msg.text) + utilities.handle_exception(self, result, msg.from.id .. ': ' .. msg.text) return end -- If the action returns a table, make that table msg. @@ -93,37 +91,41 @@ function bot:on_msg_receive(msg) -- The fn run whenever a message is received. end -bot.init(instance) -- Actually start the script. Run the bot_init function. +function bot:run() + bot.init(self) -- Actually start the script. Run the bot_init function. -while instance.is_started do -- Start a loop while the bot should be running. + while self.is_started do -- Start a loop while the bot should be running. - do - local res = bindings.getUpdates(instance, instance.last_update+1) -- Get the latest updates! - if res then - for _,v in ipairs(res.result) do -- Go through every new message. - instance.last_update = v.update_id - bot.on_msg_receive(instance, v.message) + do + local res = bindings.getUpdates(self, self.last_update+1) -- Get the latest updates! + if res then + for _,v in ipairs(res.result) do -- Go through every new message. + self.last_update = v.update_id + bot.on_msg_receive(self, v.message) + end + else + print(self.config.errors.connection) end - else - print(instance.config.errors.connection) end - end - if instance.last_cron ~= os.date('%M') then -- Run cron jobs every minute. - instance.last_cron = os.date('%M') - utilities.save_data(instance.info.username..'.db', instance.database) -- Save the database. - for i,v in ipairs(instance.plugins) do - if v.cron then -- Call each plugin's cron function, if it has one. - local res, err = pcall(function() v.cron(instance) end) - if not res then - utilities.handle_exception(instance, err, 'CRON: ' .. i) + if self.last_cron ~= os.date('%M') then -- Run cron jobs every minute. + self.last_cron = os.date('%M') + utilities.save_data(self.info.username..'.db', self.database) -- Save the database. + for i,v in ipairs(self.plugins) do + if v.cron then -- Call each plugin's cron function, if it has one. + local res, err = pcall(function() v.cron(self) end) + if not res then + utilities.handle_exception(self, err, 'CRON: ' .. i) + end end end end + end + -- Save the database before exiting. + utilities.save_data(self.info.username..'.db', self.database) + print('Halted.') end - -- Save the database before exiting. -utilities.save_data(instance.info.username..'.db', instance.database) -print('Halted.') +return bot diff --git a/config.lua b/config.lua index bac5ead..541a9f0 100755 --- a/config.lua +++ b/config.lua @@ -4,8 +4,6 @@ return { bot_api_key = '', -- Your Telegram ID. admin = 00000000, - -- Differences, in seconds, between your time and UTC. - time_offset = 0, -- Two-letter language code. lang = 'en', -- The channel, group, or user to send error reports to. @@ -51,35 +49,35 @@ Send /help to get started. }, plugins = { -- To enable a plugin, add its name to the list. - 'control.lua', - 'blacklist.lua', - 'about.lua', - 'ping.lua', - 'whoami.lua', - 'nick.lua', - 'echo.lua', - 'gSearch.lua', - 'gMaps.lua', - 'wikipedia.lua', - 'hackernews.lua', - 'imdb.lua', - 'calc.lua', - 'urbandictionary.lua', - 'time.lua', - 'eightball.lua', - 'dice.lua', - 'reddit.lua', - 'xkcd.lua', - 'slap.lua', - 'commit.lua', - 'pun.lua', - 'currency.lua', - 'cats.lua', - 'shout.lua', - 'patterns.lua', + 'control', + 'blacklist', + 'about', + 'ping', + 'whoami', + 'nick', + 'echo', + 'gSearch', + 'gMaps', + 'wikipedia', + 'hackernews', + 'imdb', + 'calc', + 'urbandictionary', + 'time', + 'eightball', + 'dice', + 'reddit', + 'xkcd', + 'slap', + 'commit', + 'pun', + 'currency', + 'cats', + 'shout', + 'patterns', -- Put new plugins above this line. - 'help.lua', - 'greetings.lua' + 'help', + 'greetings' } } diff --git a/launch.sh b/launch.sh index 6c20e59..be8b691 100755 --- a/launch.sh +++ b/launch.sh @@ -1,7 +1,7 @@ #!/bin/sh while true; do - lua bot.lua + lua main.lua echo 'otouto has stopped. ^C to exit.' sleep 5s done diff --git a/main.lua b/main.lua new file mode 100644 index 0000000..9158bcc --- /dev/null +++ b/main.lua @@ -0,0 +1,5 @@ +local bot = require('bot') + +local instance = {} + +return bot.run(instance) diff --git a/plugins/administration.lua b/plugins/administration.lua index 43ae4b7..d328433 100644 --- a/plugins/administration.lua +++ b/plugins/administration.lua @@ -324,7 +324,7 @@ function administration.init_command(self_) if self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] > 99 then drua.kick_user(msg.chat.id, msg.from.id) local output = administration.flags[5].kicked:gsub('GROUPNAME', msg.chat.title) - bindings.sendMessage(msg.from.id, output) + bindings.sendMessage(self, msg.from.id, output) self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] = nil return end @@ -372,7 +372,7 @@ function administration.init_command(self_) else group.name = msg.new_chat_title if group.grouptype == 'supergroup' then - administration.update_desc(msg.chat.id) + administration.update_desc(self, msg.chat.id) end end return @@ -799,7 +799,7 @@ function administration.init_command(self_) local status = group.flags[i] or false output = output .. '`[' .. i .. ']` *' .. v.name .. '*` = ' .. tostring(status) .. '`\n• ' .. v.desc .. '\n' end - bindings.sendMessage(msg.chat.id, output, true, nil, true) + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) return end if group.flags[input] == true then @@ -987,7 +987,7 @@ function administration.init_command(self_) action = function(self, msg) if self.database.administration.groups[msg.chat.id_str] then - bindings.sendReply(msg, 'I am already administrating this group.') + bindings.sendReply(self, msg, 'I am already administrating this group.') return end self.database.administration.groups[msg.chat.id_str] = { diff --git a/plugins/echo.lua b/plugins/echo.lua index 26be359..9ec8bee 100755 --- a/plugins/echo.lua +++ b/plugins/echo.lua @@ -10,7 +10,7 @@ Repeats a string of text. ```]] function echo:init() - echo.triggers = utilities.triggers(self.info.username):t('echo').table + echo.triggers = utilities.triggers(self.info.username):t('echo', true).table end function echo:action(msg) diff --git a/plugins/help.lua b/plugins/help.lua index a84bf78..0e99280 100755 --- a/plugins/help.lua +++ b/plugins/help.lua @@ -6,24 +6,27 @@ local help = {} local bindings = require('bindings') local utilities = require('utilities') -local help_text = '*Available commands:*' +local help_text function help:init() + help_text = '*Available commands:*' + for _,plugin in ipairs(self.plugins) do if plugin.command then help_text = help_text .. '\n• /' .. plugin.command:gsub('%[', '\\[') end end - help.triggers = utilities.triggers(self.info.username):t('help', true):t('h', true).table -end - -help_text = help_text .. [[ + help_text = help_text .. [[ • /help Arguments: \[optional] ]] + help.triggers = utilities.triggers(self.info.username):t('help', true):t('h', true).table + +end + function help:action(msg) local input = utilities.input(msg.text_lower) diff --git a/plugins/luarun.lua b/plugins/luarun.lua index 9200246..34eda5c 100644 --- a/plugins/luarun.lua +++ b/plugins/luarun.lua @@ -19,7 +19,7 @@ function luarun:action(msg) return end - local output = loadstring(input)() + local output = loadstring('local utilities = require(\'utilities\'); return function (instance) '..input..' end')()(self) if output == nil then output = 'Done!' elseif type(output) == 'table' then diff --git a/plugins/moderation.lua b/plugins/moderation.lua index c8417f1..0e3eb18 100755 --- a/plugins/moderation.lua +++ b/plugins/moderation.lua @@ -268,12 +268,12 @@ function moderation:init() moderation.triggers = {} for trigger,_ in pairs(commands) do if trigger[-1] == '$' then - moderation.triggers:insert(trigger:sub(1, -2)..'@'..self.info.username..'$') + tables.insert(moderation.triggers, trigger:sub(1, -2)..'@'..self.info.username..'$') else - moderation.triggers:insert(trigger..'%s+[^%s]*') - moderation.triggers:insert(trigger..'@'..self.info.username..'%s+[^%s]*') - moderation.triggers:insert(trigger..'$') - moderation.triggers:insert(trigger..'@'..self.info.username..'$') + tables.insert(moderation.triggers, trigger..'%s+[^%s]*') + tables.insert(moderation.triggers, trigger..'@'..self.info.username..'%s+[^%s]*') + tables.insert(moderation.triggers, trigger..'$') + tables.insert(moderation.triggers, trigger..'@'..self.info.username..'$') end end end diff --git a/plugins/nick.lua b/plugins/nick.lua index 603a04e..d2a680b 100755 --- a/plugins/nick.lua +++ b/plugins/nick.lua @@ -10,7 +10,7 @@ Set your nickname. Use "/nick --" to delete it. ```]] function nick:init() - nick.triggers = utilities.triggers(self.info.nick):t('nick', true).table + nick.triggers = utilities.triggers(self.info.username):t('nick', true).table end function nick:action(msg) diff --git a/plugins/reactions.lua b/plugins/reactions.lua index 4ea2c55..0087378 100755 --- a/plugins/reactions.lua +++ b/plugins/reactions.lua @@ -28,8 +28,8 @@ function reactions:init() reactions.triggers = utilities.triggers(self.info.username):t('reactions').table for trigger,reaction in pairs(mapping) do help = help .. '• ' .. trigger:gsub('.%?', '') .. ': ' .. reaction .. '\n' - reactions.triggers:insert(utilities.INVOCATION_PATTERN..trigger) - reactions.triggers:insert(utilities.INVOCATION_PATTERN..trigger..'@'..self.username) + table.insert(reactions.triggers, utilities.INVOCATION_PATTERN..trigger) + table.insert(reactions.triggers, utilities.INVOCATION_PATTERN..trigger..'@'..self.username) end end diff --git a/plugins/shell.lua b/plugins/shell.lua index b1b90b0..1a1bd6f 100644 --- a/plugins/shell.lua +++ b/plugins/shell.lua @@ -4,7 +4,7 @@ local bindings = require('bindings') local utilities = require('utilities') function shell:init() - shell.triggers = utilities.bindings(self.info.username):t('run', true).table + shell.triggers = utilities.triggers(self.info.username):t('run', true).table end function shell:action(msg) diff --git a/plugins/time.lua b/plugins/time.lua index fe17cdb..418d679 100755 --- a/plugins/time.lua +++ b/plugins/time.lua @@ -43,7 +43,9 @@ function time:action(msg) local jdat = JSON.decode(jstr) - local timestamp = os.time() + jdat.rawOffset + jdat.dstOffset + self.config.time_offset + local now = os.time() + local time_offset = os.difftime(now, os.time(os.date("!*t", now))) + local timestamp = now + jdat.rawOffset + jdat.dstOffset + time_offset local utcoff = (jdat.rawOffset + jdat.dstOffset) / 3600 if utcoff == math.abs(utcoff) then utcoff = '+' .. utcoff diff --git a/plugins/whoami.lua b/plugins/whoami.lua index ed26d92..ddb1891 100755 --- a/plugins/whoami.lua +++ b/plugins/whoami.lua @@ -17,7 +17,7 @@ function whoami:action(msg) if msg.reply_to_message then msg = msg.reply_to_message - msg.from.name = utilities.build_name(self, msg.from.first_name, msg.from.last_name) + msg.from.name = utilities.build_name(msg.from.first_name, msg.from.last_name) end local chat_id = math.abs(msg.chat.id) diff --git a/utilities.lua b/utilities.lua index 99254e5..7ef571a 100755 --- a/utilities.lua +++ b/utilities.lua @@ -276,19 +276,20 @@ end utilities.INVOCATION_PATTERN = '/' -utilities.triggers_metatable = {} -function utilities.triggers_metatable:t(pattern, has_args) - self.table:insert('^'..utilities.INVOCATION_PATTERN..pattern..'$') - self.table:insert('^'..utilities.INVOCATION_PATTERN..pattern..'@'..self.username..'$') +utilities.triggers_meta = {} +utilities.triggers_meta.__index = utilities.triggers_meta +function utilities.triggers_meta:t(pattern, has_args) + table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'$') + table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'@'..self.username..'$') if has_args then - self.table:insert('^'..utilities.INVOCATION_PATTERN..pattern..'%s+[^%s]*') - self.table:insert('^'..utilities.INVOCATION_PATTERN..pattern..'@'..self.username..'%s+[^%s]*') + table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'%s+[^%s]*') + table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'@'..self.username..'%s+[^%s]*') end return self end function utilities.triggers(username, trigger_table) - local self = setmetatable({}, utilities.triggers_metatable) + local self = setmetatable({}, utilities.triggers_meta) self.username = username self.table = trigger_table or {} return self @@ -331,3 +332,5 @@ function utilities.enrich_message(msg) end return msg end + +return utilities From 56abfab0b40dc8f8f105fba96093912db5e2dbb3 Mon Sep 17 00:00:00 2001 From: Brayden Banks Date: Fri, 15 Apr 2016 19:07:23 +0000 Subject: [PATCH 6/9] Through the Testing-Glass, & What Drew Found There --- README.md | 3 +-- bindings.lua | 2 +- plugins/administration.lua | 16 ++++++++-------- plugins/apod.lua | 2 +- plugins/chatter.lua | 2 +- plugins/dilbert.lua | 10 ++++++---- plugins/floodcontrol.lua | 2 +- plugins/gImages.lua | 2 +- plugins/gSearch.lua | 2 +- plugins/hackernews.lua | 2 +- plugins/hearthstone.lua | 4 ++-- plugins/imdb.lua | 2 +- plugins/lastfm.lua | 2 +- plugins/librefm.lua | 2 +- plugins/luarun.lua | 2 +- plugins/pokedex.lua | 2 +- plugins/reactions.lua | 2 +- plugins/reddit.lua | 2 +- plugins/shout.lua | 4 ++-- plugins/time.lua | 19 +++++++++++-------- plugins/translate.lua | 2 +- plugins/urbandictionary.lua | 6 +++--- plugins/weather.lua | 2 +- plugins/wikipedia.lua | 2 +- plugins/xkcd.lua | 2 +- plugins/youtube.lua | 2 +- utilities.lua | 16 +++++++++++++--- 27 files changed, 65 insertions(+), 51 deletions(-) diff --git a/README.md b/README.md index b61e7af..3509d9d 100755 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ otouto is an independently-developed Telegram API bot written in Lua. Originally | [Contributors](#contributors) | ## Setup -You _must_ have Lua (5.2+), lua-socket, lua-sec, and lua-cjson installed. To upload files, you must have curl installed. To use fortune.lua, you must have fortune installed. +You _must_ have Lua (5.2+), lua-socket, lua-sec, and dkjson installed. It is recommended you install these with LuaRocks. To upload files, you must have curl installed. To use fortune.lua, you must have fortune installed. Clone the repository and set the following values in `config.lua`: @@ -26,7 +26,6 @@ Clone the repository and set the following values in `config.lua`: Optionally: - - `time_offset` as the difference, in seconds, of your system clock to UTC. - `lang` as the two-letter code representing your language. Some plugins are not enabled by default. If you wish to enable them, add them to the `plugins` array. diff --git a/bindings.lua b/bindings.lua index af2bac5..533cbc1 100755 --- a/bindings.lua +++ b/bindings.lua @@ -5,7 +5,7 @@ local bindings = {} local HTTPS = require('ssl.https') -local JSON = require('cjson') +local JSON = require('dkjson') local URL = require('socket.url') function bindings.sendRequest(url) diff --git a/plugins/administration.lua b/plugins/administration.lua index d328433..fbe829d 100644 --- a/plugins/administration.lua +++ b/plugins/administration.lua @@ -25,7 +25,7 @@ ]]-- -local JSON = require('cjson') +local JSON = require('dkjson') local drua = dofile('drua-tg/drua-tg.lua') local bindings = require('bindings') local utilities = require('utilities') @@ -196,7 +196,7 @@ function administration:get_desc(chat_id) for i,v in ipairs(group.rules) do rulelist = rulelist .. '*' .. i .. '.* ' .. v .. '\n' end - table.insert(t, rulelist:trim()) + table.insert(t, utilities.trim(rulelist)) end local flaglist = '' for i = 1, #administration.flags do @@ -205,7 +205,7 @@ function administration:get_desc(chat_id) end end if flaglist ~= '' then - table.insert(t, '*Flags:*\n' .. flaglist:trim()) + table.insert(t, '*Flags:*\n' .. utilities.trim(flaglist)) end if group.governor then local gov = self.database.users[tostring(group.governor)] @@ -217,7 +217,7 @@ function administration:get_desc(chat_id) modstring = modstring .. administration.mod_format(self, k) end if modstring ~= '' then - table.insert(t, '*Moderators:*\n' .. modstring:trim()) + table.insert(t, '*Moderators:*\n' .. utilities.trim(modstring)) end return table.concat(t, '\n\n') @@ -491,7 +491,7 @@ function administration.init_command(self_) local gov = self.database.users[tostring(group.governor)] govstring = '*Governor:* ' .. utilities.md_escape(utilities.build_name(gov.first_name, gov.last_name)) .. ' `[' .. gov.id .. ']`' end - local output = modstring:trim() ..'\n\n' .. govstring:trim() + local output = utilities.trim(modstring) ..'\n\n' .. utilities.trim(govstring) if output == '\n\n' then output = 'There are currently no moderators for this group.' end @@ -695,13 +695,13 @@ function administration.init_command(self_) return end group.rules = {} - input = input:trim() .. '\n' + input = utilities.trim(input) .. '\n' local output = '*Rules for* _' .. msg.chat.title .. '_ *:*\n' local i = 1 for l in input:gmatch('(.-)\n') do output = output .. '*' .. i .. '.* ' .. l .. '\n' i = i + 1 - table.insert(group.rules, l:trim()) + table.insert(group.rules, utilities.trim(l)) end bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end @@ -728,7 +728,7 @@ function administration.init_command(self_) group.motd = nil bindings.sendReply(self, msg, 'The MOTD has been cleared.') else - input = input:trim() + input = utilities.trim(input) group.motd = input local output = '*MOTD for* _' .. msg.chat.title .. '_ *:*\n' .. input bindings.sendMessage(self, msg.chat.id, output, true, nil, true) diff --git a/plugins/apod.lua b/plugins/apod.lua index f8c56db..7370c06 100755 --- a/plugins/apod.lua +++ b/plugins/apod.lua @@ -1,7 +1,7 @@ local apod = {} local HTTPS = require('ssl.https') -local JSON = require('cjson') +local JSON = require('dkjson') local URL = require('socket.url') local bindings = require('bindings') local utilities = require('utilities') diff --git a/plugins/chatter.lua b/plugins/chatter.lua index c050a5c..ea83956 100755 --- a/plugins/chatter.lua +++ b/plugins/chatter.lua @@ -4,7 +4,7 @@ local chatter = {} local HTTP = require('socket.http') local URL = require('socket.url') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') function chatter:init() diff --git a/plugins/dilbert.lua b/plugins/dilbert.lua index e3b9fac..8012f6a 100644 --- a/plugins/dilbert.lua +++ b/plugins/dilbert.lua @@ -32,8 +32,12 @@ function dilbert:action(msg) return end - local strip_file = io.open('/tmp/' .. input .. '.gif') - if not strip_file then + local strip_filename = '/tmp/' .. input .. '.gif' + local strip_file = io.open(strip_filename) + if strip_file then + strip_file:close() + strip_file = strip_filename + else local strip_url = str:match('') strip_file = utilities.download_file(strip_url, '/tmp/' .. input .. '.gif') end @@ -42,8 +46,6 @@ function dilbert:action(msg) bindings.sendPhoto(self, msg.chat.id, strip_file, strip_title) - strip_file:close() - end return dilbert diff --git a/plugins/floodcontrol.lua b/plugins/floodcontrol.lua index 1af204d..92ec5e5 100755 --- a/plugins/floodcontrol.lua +++ b/plugins/floodcontrol.lua @@ -3,7 +3,7 @@ local floodcontrol = {} -local JSON = require('cjson') +local JSON = require('dkjson') local utilities = require('utilities') function floodcontrol:init() diff --git a/plugins/gImages.lua b/plugins/gImages.lua index ab36742..0eef7df 100755 --- a/plugins/gImages.lua +++ b/plugins/gImages.lua @@ -5,7 +5,7 @@ local gImages = {} local HTTPS = require('ssl.https') local URL = require('socket.url') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') diff --git a/plugins/gSearch.lua b/plugins/gSearch.lua index 4f40e70..36482c9 100755 --- a/plugins/gSearch.lua +++ b/plugins/gSearch.lua @@ -2,7 +2,7 @@ local gSearch = {} local HTTPS = require('ssl.https') local URL = require('socket.url') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') diff --git a/plugins/hackernews.lua b/plugins/hackernews.lua index 1029094..2e68fd1 100755 --- a/plugins/hackernews.lua +++ b/plugins/hackernews.lua @@ -1,7 +1,7 @@ local hackernews = {} local HTTPS = require('ssl.https') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') diff --git a/plugins/hearthstone.lua b/plugins/hearthstone.lua index 38507b8..6f5b6da 100755 --- a/plugins/hearthstone.lua +++ b/plugins/hearthstone.lua @@ -3,7 +3,7 @@ local hearthstone = {} local HTTPS = require('ssl.https') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') @@ -118,7 +118,7 @@ function hearthstone:action(msg) end end - output = output:trim() + output = utilities.trim(output) if output:len() == 0 then bindings.sendReply(self, msg, self.config.errors.results) return diff --git a/plugins/imdb.lua b/plugins/imdb.lua index 9eeaf23..a4f0c35 100755 --- a/plugins/imdb.lua +++ b/plugins/imdb.lua @@ -2,7 +2,7 @@ local imdb = {} local HTTP = require('socket.http') local URL = require('socket.url') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') diff --git a/plugins/lastfm.lua b/plugins/lastfm.lua index 1afd121..0a58544 100755 --- a/plugins/lastfm.lua +++ b/plugins/lastfm.lua @@ -2,7 +2,7 @@ local lastfm = {} local HTTP = require('socket.http') local URL = require('socket.url') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') diff --git a/plugins/librefm.lua b/plugins/librefm.lua index 458335d..3eb44fe 100644 --- a/plugins/librefm.lua +++ b/plugins/librefm.lua @@ -2,7 +2,7 @@ local librefm = {} local HTTPS = require('ssl.https') local URL = require('socket.url') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') diff --git a/plugins/luarun.lua b/plugins/luarun.lua index 34eda5c..f88f44d 100644 --- a/plugins/luarun.lua +++ b/plugins/luarun.lua @@ -19,7 +19,7 @@ function luarun:action(msg) return end - local output = loadstring('local utilities = require(\'utilities\'); return function (instance) '..input..' end')()(self) + local output = loadstring('local bindings = require(\'bindings\'); local utilities = require(\'utilities\'); return function (instance, msg) '..input..' end')()(self, msg) if output == nil then output = 'Done!' elseif type(output) == 'table' then diff --git a/plugins/pokedex.lua b/plugins/pokedex.lua index 9e9f128..7315ce7 100755 --- a/plugins/pokedex.lua +++ b/plugins/pokedex.lua @@ -1,7 +1,7 @@ local pokedex = {} local HTTP = require('socket.http') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') diff --git a/plugins/reactions.lua b/plugins/reactions.lua index 0087378..8b73c82 100755 --- a/plugins/reactions.lua +++ b/plugins/reactions.lua @@ -29,7 +29,7 @@ function reactions:init() for trigger,reaction in pairs(mapping) do help = help .. '• ' .. trigger:gsub('.%?', '') .. ': ' .. reaction .. '\n' table.insert(reactions.triggers, utilities.INVOCATION_PATTERN..trigger) - table.insert(reactions.triggers, utilities.INVOCATION_PATTERN..trigger..'@'..self.username) + table.insert(reactions.triggers, utilities.INVOCATION_PATTERN..trigger..'@'..self.username:lower()) end end diff --git a/plugins/reddit.lua b/plugins/reddit.lua index 113a3a0..6a59044 100755 --- a/plugins/reddit.lua +++ b/plugins/reddit.lua @@ -2,7 +2,7 @@ local reddit = {} local HTTP = require('socket.http') local URL = require('socket.url') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') diff --git a/plugins/shout.lua b/plugins/shout.lua index eb08293..dd66ac3 100644 --- a/plugins/shout.lua +++ b/plugins/shout.lua @@ -21,7 +21,7 @@ function shout:action(msg) bindings.sendMessage(self, msg.chat.id, shout.doc, true, msg.message_id, true) return end - input = input:trim() + input = utilities.trim(input) if input:len() > 20 then input = input:sub(1,20) @@ -42,7 +42,7 @@ function shout:action(msg) inc = inc + 1 output = output .. match .. ' ' .. spacing .. match .. '\n' end - output = '```\n' .. output:trim() .. '\n```' + output = '```\n' .. utilities.trim(output) .. '\n```' bindings.sendMessage(self, msg.chat.id, output, true, false, true) end diff --git a/plugins/time.lua b/plugins/time.lua index 418d679..e60de8e 100755 --- a/plugins/time.lua +++ b/plugins/time.lua @@ -1,7 +1,7 @@ local time = {} local HTTPS = require('ssl.https') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') @@ -33,7 +33,10 @@ function time:action(msg) return end - local url = 'https://maps.googleapis.com/maps/api/timezone/json?location=' .. coords.lat ..','.. coords.lon .. '×tamp='..os.time() + local now = os.time() + local utc = os.time(os.date("!*t", now)) + + local url = 'https://maps.googleapis.com/maps/api/timezone/json?location=' .. coords.lat ..','.. coords.lon .. '×tamp='..utc local jstr, res = HTTPS.request(url) if res ~= 200 then @@ -43,16 +46,16 @@ function time:action(msg) local jdat = JSON.decode(jstr) - local now = os.time() - local time_offset = os.difftime(now, os.time(os.date("!*t", now))) - local timestamp = now + jdat.rawOffset + jdat.dstOffset + time_offset + local timestamp = now + jdat.rawOffset + jdat.dstOffset local utcoff = (jdat.rawOffset + jdat.dstOffset) / 3600 if utcoff == math.abs(utcoff) then - utcoff = '+' .. utcoff + utcoff = '+'.. utilities.pretty_float(utcoff) + else + utcoff = utilities.pretty_float(utcoff) end - local message = os.date('%I:%M %p\n', timestamp) .. os.date('%A, %B %d, %Y\n', timestamp) .. jdat.timeZoneName .. ' (UTC' .. utcoff .. ')' + local message = os.date('!%I:%M %p\n', timestamp) .. os.date('!%A, %B %d, %Y\n', timestamp) .. jdat.timeZoneName .. ' (UTC' .. utcoff .. ')' - bindings.sendReply(self.msg, message) + bindings.sendReply(self, msg, message) end diff --git a/plugins/translate.lua b/plugins/translate.lua index f881c2d..ea1a104 100755 --- a/plugins/translate.lua +++ b/plugins/translate.lua @@ -2,7 +2,7 @@ local translate = {} local HTTPS = require('ssl.https') local URL = require('socket.url') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') diff --git a/plugins/urbandictionary.lua b/plugins/urbandictionary.lua index 4b34a37..b32dc6d 100755 --- a/plugins/urbandictionary.lua +++ b/plugins/urbandictionary.lua @@ -2,7 +2,7 @@ local urbandictionary = {} local HTTP = require('socket.http') local URL = require('socket.url') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') @@ -43,9 +43,9 @@ function urbandictionary:action(msg) return end - local output = '*' .. jdat.list[1].word .. '*\n\n' .. jdat.list[1].definition:trim() + local output = '*' .. jdat.list[1].word .. '*\n\n' .. utilities.trim(jdat.list[1].definition) if string.len(jdat.list[1].example) > 0 then - output = output .. '_\n\n' .. jdat.list[1].example:trim() .. '_' + output = output .. '_\n\n' .. utilities.trim(jdat.list[1].example) .. '_' end output = output:gsub('%[', ''):gsub('%]', '') diff --git a/plugins/weather.lua b/plugins/weather.lua index 0e4414c..34e543a 100755 --- a/plugins/weather.lua +++ b/plugins/weather.lua @@ -1,7 +1,7 @@ local weather = {} local HTTP = require('socket.http') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') diff --git a/plugins/wikipedia.lua b/plugins/wikipedia.lua index 1066f75..6b506c1 100755 --- a/plugins/wikipedia.lua +++ b/plugins/wikipedia.lua @@ -2,7 +2,7 @@ local wikipedia = {} local HTTPS = require('ssl.https') local URL = require('socket.url') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') diff --git a/plugins/xkcd.lua b/plugins/xkcd.lua index d6b3c20..4838744 100755 --- a/plugins/xkcd.lua +++ b/plugins/xkcd.lua @@ -3,7 +3,7 @@ local xkcd = {} local HTTP = require('socket.http') local HTTPS = require('ssl.https') local URL = require('socket.url') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') diff --git a/plugins/youtube.lua b/plugins/youtube.lua index ee7a41f..1979919 100755 --- a/plugins/youtube.lua +++ b/plugins/youtube.lua @@ -4,7 +4,7 @@ local youtube = {} local HTTPS = require('ssl.https') local URL = require('socket.url') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') local utilities = require('utilities') diff --git a/utilities.lua b/utilities.lua index 7ef571a..1aa7bd6 100755 --- a/utilities.lua +++ b/utilities.lua @@ -7,7 +7,7 @@ local HTTP = require('socket.http') local ltn12 = require('ltn12') local HTTPS = require('ssl.https') local URL = require('socket.url') -local JSON = require('cjson') +local JSON = require('dkjson') local bindings = require('bindings') -- get the indexed word in a string @@ -169,6 +169,7 @@ function utilities:user_from_message(msg) local input = utilities.input(msg.text_lower) local target = {} if msg.reply_to_message then + print('reply') target = msg.reply_to_message.from elseif input and tonumber(input) then target.id = tonumber(input) @@ -279,11 +280,12 @@ utilities.INVOCATION_PATTERN = '/' utilities.triggers_meta = {} utilities.triggers_meta.__index = utilities.triggers_meta function utilities.triggers_meta:t(pattern, has_args) + local username = self.username:lower() table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'$') - table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'@'..self.username..'$') + table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'@'..username..'$') if has_args then table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'%s+[^%s]*') - table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'@'..self.username..'%s+[^%s]*') + table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'@'..username..'%s+[^%s]*') end return self end @@ -333,4 +335,12 @@ function utilities.enrich_message(msg) return msg end +function utilities.pretty_float(x) + if x % 1 == 0 then + return tostring(math.floor(x)) + else + return tostring(x) + end +end + return utilities From f138ee913c30528603a92d3eb4beb7204a8be431 Mon Sep 17 00:00:00 2001 From: Brayden Banks Date: Mon, 25 Apr 2016 21:45:05 -0700 Subject: [PATCH 7/9] I think the refactor is finished now. --- plugins/administration.lua | 2 +- plugins/bandersnatch.lua | 2 +- plugins/greetings.lua | 4 +- plugins/moderation.lua | 309 ------------------------------------- plugins/preview.lua | 2 +- 5 files changed, 5 insertions(+), 314 deletions(-) delete mode 100755 plugins/moderation.lua diff --git a/plugins/administration.lua b/plugins/administration.lua index fbe829d..3c2b232 100644 --- a/plugins/administration.lua +++ b/plugins/administration.lua @@ -1002,7 +1002,7 @@ function administration.init_command(self_) photo = drua.get_photo(msg.chat.id), founded = os.time() } - administration:update_desc(self, msg.chat.id) + administration.update_desc(self, msg.chat.id) for i,_ in ipairs(administration.flags) do self.database.administration.groups[msg.chat.id_str].flags[i] = false end diff --git a/plugins/bandersnatch.lua b/plugins/bandersnatch.lua index 0411494..49a68c2 100755 --- a/plugins/bandersnatch.lua +++ b/plugins/bandersnatch.lua @@ -10,7 +10,7 @@ Alias: /bc ```]] function bandersnatch:init() - bandersnatch.triggers = utilities.triggers(self.info.username):trigger('bandersnatch'):trigger('bc').table + bandersnatch.triggers = utilities.triggers(self.info.username):t('bandersnatch'):t('bc').table end local fullnames = { "Wimbledon Tennismatch", "Rinkydink Curdlesnoot", "Butawhiteboy Cantbekhan", "Benadryl Claritin", "Bombadil Rivendell", "Wanda's Crotchfruit", "Biblical Concubine", "Syphilis Cankersore", "Buckminster Fullerene", "Bourgeoisie Capitalist" } diff --git a/plugins/greetings.lua b/plugins/greetings.lua index 5e0dcb7..48148e2 100755 --- a/plugins/greetings.lua +++ b/plugins/greetings.lua @@ -38,7 +38,7 @@ function greetings:init() end greetings.triggers = { - self.info.first_name .. '%p*$' + self.info.first_name:lower() .. '%p*$' } end @@ -48,7 +48,7 @@ function greetings:action(msg) for trigger,responses in pairs(self.config.greetings) do for _,response in pairs(responses) do - if msg.text_lower:match(response..',? '..self.info.first_name) then + if msg.text_lower:match(response..',? '..self.info.first_name:lower()) then bindings.sendMessage(self, msg.chat.id, utilities.latcyr(trigger:gsub('#NAME', nick))) return end diff --git a/plugins/moderation.lua b/plugins/moderation.lua deleted file mode 100755 index 0e3eb18..0000000 --- a/plugins/moderation.lua +++ /dev/null @@ -1,309 +0,0 @@ - -- Moderation for Liberbot groups. - -- The bot must be made an admin. - -- Put this near the top, after blacklist. - -- If you want to enable antisquig, put that at the top, before blacklist. - -local moderation = {} - -local bindings = require('bindings') -local utilities = require('utilities') - -local antisquig = {} - -local commands = { - - ['^/modhelp$'] = function(self, msg) - - if not self.database.moderation[msg.chat.id_str] then return end - - local output = [[ - *Users:* - • /modlist - List the moderators and administrators of this group. - *Moderators:* - • /modkick - Kick a user from this group. - • /modban - Ban a user from this group. - *Administrators:* - • /modadd - Add this group to the moderation system. - • /modrem - Remove this group from the moderation system. - • /modprom - Promote a user to a moderator. - • /moddem - Demote a moderator to a user. - • /modcast - Send a broadcast to every moderated group. - ]] - output = output:gsub('\t', '') - - bindings.sendMessage(self, msg.chat.id, output, true, nil, true) - - end, - - ['^/modlist$'] = function(self, msg) - - if not self.database.moderation[msg.chat.id_str] then return end - - local output = '' - - for k,v in pairs(self.database.moderation[msg.chat.id_str]) do - output = output .. '• ' .. v .. ' (' .. k .. ')\n' - end - - if output ~= '' then - output = '*Moderators for* _' .. msg.chat.title .. '_ *:*\n' .. output - end - - output = output .. '*Administrators for* _' .. self.config.moderation.realm_name .. '_ *:*\n' - for k,v in pairs(self.config.moderation.admins) do - output = output .. '• ' .. v .. ' (' .. k .. ')\n' - end - - bindings.sendMessage(self, msg.chat.id, output, true, nil, true) - - end, - - ['^/modcast'] = function(self, msg) - - local output = utilities.input(msg.text) - if not output then - return 'You must include a message.' - end - - if msg.chat.id ~= self.config.moderation.admin_group then - return 'This command must be run in the administration group.' - end - - if not self.config.moderation.admins[msg.from.id_str] then - return self.config.moderation.errors.not_admin - end - - output = '*Admin Broadcast:*\n' .. output - - for k,_ in pairs(self.database.moderation) do - bindings.sendMessage(self, k, output, true, nil, true) - end - - return 'Your broadcast has been sent.' - - end, - - ['^/modadd$'] = function(self, msg) - - if not self.config.moderation.admins[msg.from.id_str] then - return self.config.moderation.errors.not_admin - end - - if self.database.moderation[msg.chat.id_str] then - return 'I am already moderating this group.' - end - - self.database.moderation[msg.chat.id_str] = {} - return 'I am now moderating this group.' - - end, - - ['^/modrem$'] = function(self, msg) - - if not self.config.moderation.admins[msg.from.id_str] then - return self.config.moderation.errors.not_admin - end - - if not self.database.moderation[msg.chat.id_str] then - return self.config.moderation.errors.moderation - end - - self.database.moderation[msg.chat.id_str] = nil - return 'I am no longer moderating this group.' - - end, - - ['^/modprom$'] = function(self, msg) - - if not self.database.moderation[msg.chat.id_str] then return end - - if not self.config.moderation.admins[msg.from.id_str] then - return self.config.moderation.errors.not_admin - end - - if not msg.reply_to_message then - return 'Promotions must be done via reply.' - end - - local modid = tostring(msg.reply_to_message.from.id) - local modname = msg.reply_to_message.from.first_name - - if self.config.moderation.admins[modid] then - return modname .. ' is already an administrator.' - end - - if self.database.moderation[msg.chat.id_str][modid] then - return modname .. ' is already a moderator.' - end - - self.database.moderation[msg.chat.id_str][modid] = modname - - return modname .. ' is now a moderator.' - - end, - - ['^/moddem'] = function(self, msg) - - if not self.database.moderation[msg.chat.id_str] then return end - - if not self.config.moderation.admins[msg.from.id_str] then - return self.config.moderation.errors.not_admin - end - - local modid = utilities.input(msg.text) - - if not modid then - if msg.reply_to_message then - modid = tostring(msg.reply_to_message.from.id) - else - return 'Demotions must be done via reply or specification of a moderator\'s ID.' - end - end - - if self.config.moderation.admins[modid] then - return self.config.moderation.admins[modid] .. ' is an administrator.' - end - - if not self.database.moderation[msg.chat.id_str][modid] then - return 'User is not a moderator.' - end - - local modname = self.database.moderation[msg.chat.id_str][modid] - self.database.moderation[msg.chat.id_str][modid] = nil - - return modname .. ' is no longer a moderator.' - - end, - - ['/modkick'] = function(self, msg) - - if not self.database.moderation[msg.chat.id_str] then return end - - if not self.database.moderation[msg.chat.id_str][msg.from.id_str] then - if not self.config.moderation.admins[msg.from.id_str] then - return self.config.moderation.errors.not_mod - end - end - - local userid = utilities.input(msg.text) - local usernm = userid - - if msg.reply_to_message then - userid = tostring(msg.reply_to_message.from.id) - usernm = msg.reply_to_message.from.first_name - end - - if not userid then - return 'Kicks must be done via reply or specification of a user/bot\'s ID or username.' - end - - if self.database.moderation[msg.chat.id_str][userid] or self.config.moderation.admins[userid] then - return 'You cannot kick a moderator.' - end - - bindings.sendMessage(self, self.config.moderation.admin_group, '/kick ' .. userid .. ' from ' .. math.abs(msg.chat.id)) - - bindings.sendMessage(self, self.config.moderation.admin_group, usernm .. ' kicked from ' .. msg.chat.title .. ' by ' .. msg.from.first_name .. '.') - - end, - - ['^/modban'] = function(self, msg) - - if not self.database.moderation[msg.chat.id_str] then return end - - if not self.database.moderation[msg.chat.id_str][msg.from.id_str] then - if not self.config.moderation.admins[msg.from.id_str] then - return self.config.moderation.errors.not_mod - end - end - - local userid = utilities.input(msg.text) - local usernm = userid - - if msg.reply_to_message then - userid = tostring(msg.reply_to_message.from.id) - usernm = msg.reply_to_message.from.first_name - end - - if not userid then - return 'Kicks must be done via reply or specification of a user/bot\'s ID or username.' - end - - if self.database.moderation[msg.chat.id_str][userid] or self.config.moderation.admins[userid] then - return 'You cannot ban a moderator.' - end - - bindings.sendMessage(self.config.moderation.admin_group, '/ban ' .. userid .. ' from ' .. math.abs(msg.chat.id)) - - bindings.sendMessage(self.config.moderation.admin_group, usernm .. ' banned from ' .. msg.chat.title .. ' by ' .. msg.from.first_name .. '.') - - end - -} - -function moderation:init() - if not self.database.moderation then - self.database.moderation = {} - end - - if self.config.moderation.antisquig then - commands['[\216-\219][\128-\191]'] = function(msg) - - if not self.database.moderation[msg.chat.id_str] then return true end - if self.config.moderation.admins[msg.from.id_str] then return true end - if self.database.moderation[msg.chat.id_str][msg.from.id_str] then return true end - - if antisquig[msg.from.id] == true then - return - end - antisquig[msg.from.id] = true - - bindings.sendReply(self, msg, self.config.moderation.errors.antisquig) - bindings.sendMessage(self, self.config.moderation.admin_group, '/kick ' .. msg.from.id .. ' from ' .. math.abs(msg.chat.id)) - bindings.sendMessage(self, self.config.moderation.admin_group, 'ANTISQUIG: ' .. msg.from.first_name .. ' kicked from ' .. msg.chat.title .. '.') - - end - end - - moderation.triggers = {} - for trigger,_ in pairs(commands) do - if trigger[-1] == '$' then - tables.insert(moderation.triggers, trigger:sub(1, -2)..'@'..self.info.username..'$') - else - tables.insert(moderation.triggers, trigger..'%s+[^%s]*') - tables.insert(moderation.triggers, trigger..'@'..self.info.username..'%s+[^%s]*') - tables.insert(moderation.triggers, trigger..'$') - tables.insert(moderation.triggers, trigger..'@'..self.info.username..'$') - end - end -end - -function moderation:action(msg) - - for trigger,command in pairs(commands) do - if string.match(msg.text_lower, trigger) then - local output = command(self, msg) - if output == true then - return true - elseif output then - bindings.sendReply(self, msg, output) - end - return - end - end - - return true - -end - - -- When a user is kicked for squiggles, his ID is added to this table. - -- That user will not be kicked again as long as his ID is in the table. - -- The table is emptied every five seconds. - -- Thus the bot will not spam the group or admin group when a user posts more than one infringing messages. -function moderation:cron() - - antisquig = {} - -end - -return moderation diff --git a/plugins/preview.lua b/plugins/preview.lua index 3a6fb0e..34af40b 100644 --- a/plugins/preview.lua +++ b/plugins/preview.lua @@ -11,7 +11,7 @@ Returns a full-message, "unlinked" preview. ```]] function preview:init() - preview.triggers = utilities.triggers(self.info.username):t('preview').table + preview.triggers = utilities.triggers(self.info.username):t('preview', true).table end function preview:action(msg) From 91404aa69f4589c12876d3fe96aecb7ced2b5595 Mon Sep 17 00:00:00 2001 From: Brayden Date: Tue, 26 Apr 2016 12:04:42 -0700 Subject: [PATCH 8/9] Fix reddit /r/foo trigger --- plugins/reddit.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/reddit.lua b/plugins/reddit.lua index 6a59044..a09e80f 100755 --- a/plugins/reddit.lua +++ b/plugins/reddit.lua @@ -14,7 +14,7 @@ Aliases: /r, /r/[subreddit] ```]] function reddit:init() - reddit.triggers = utilities.triggers(self.info.username):t('reddit', true):t('r', true):t('r/', true).table + reddit.triggers = utilities.triggers(self.info.username, {'^/r/'}):t('reddit', true):t('r', true):t('r/', true).table end function reddit:action(msg) From 46343a5503f7442d0f7faa2821813998a65b1854 Mon Sep 17 00:00:00 2001 From: Brayden Banks Date: Thu, 28 Apr 2016 21:36:35 -0700 Subject: [PATCH 9/9] Let's get this rock rolling! --- bindings.lua | 4 ++-- bot.lua | 10 +++++++--- otouto-dev-1.rockspec | 22 ++++++++++++++++++++++ plugins/administration.lua | 2 +- plugins/bandersnatch.lua | 2 +- plugins/calc.lua | 2 +- plugins/control.lua | 8 ++++++++ plugins/currency.lua | 3 ++- plugins/imdb.lua | 2 +- plugins/luarun.lua | 2 +- plugins/reactions.lua | 8 ++++---- plugins/remind.lua | 4 ++-- plugins/time.lua | 5 +++-- plugins/translate.lua | 2 +- plugins/weather.lua | 2 +- 15 files changed, 57 insertions(+), 21 deletions(-) create mode 100644 otouto-dev-1.rockspec diff --git a/bindings.lua b/bindings.lua index 704af41..d303f67 100755 --- a/bindings.lua +++ b/bindings.lua @@ -67,9 +67,9 @@ function bindings:sendMessage(chat_id, text, disable_web_page_preview, reply_to_ end -function bindings:sendReply(msg, text) +function bindings:sendReply(msg, text, use_markdown, disable_notification) - return bindings.sendMessage(self, msg.chat.id, text, true, msg.message_id) + return bindings.sendMessage(self, msg.chat.id, text, true, msg.message_id, use_markdown, disable_notification) end diff --git a/bot.lua b/bot.lua index 25f10f6..a6bea28 100755 --- a/bot.lua +++ b/bot.lua @@ -1,12 +1,16 @@ local bot = {} -local bindings = require('bindings') -- Load Telegram bindings. -local utilities = require('utilities') -- Load miscellaneous and cross-plugin functions. +-- Requires are moved to init to allow for reloads. +local bindings -- Load Telegram bindings. +local utilities -- Load miscellaneous and cross-plugin functions. -bot.version = '3.6' +bot.version = '3.7' function bot:init() -- The function run when the bot is started or reloaded. + bindings = require('bindings') + utilities = require('utilities') + self.config = require('config') -- Load configuration file. self.BASE_URL = 'https://api.telegram.org/bot' .. self.config.bot_api_key diff --git a/otouto-dev-1.rockspec b/otouto-dev-1.rockspec new file mode 100644 index 0000000..86acac1 --- /dev/null +++ b/otouto-dev-1.rockspec @@ -0,0 +1,22 @@ +package = 'otouto' +version = 'dev-1' + +source = { + url = 'git://github.com/topkecleon/otouto.git' +} + +description = { + summary = 'The plugin-wielding, multipurpose Telegram bot!', + detailed = 'A plugin-wielding, multipurpose bot for the Telegram API.', + homepage = 'http://otou.to', + maintainer = 'Drew ', + license = 'GPL-2' +} + +dependencies = { + 'lua >= 5.2', + 'LuaSocket ~> 3.0', + 'LuaSec ~> 0.6', + 'dkjson ~> 2.5', + 'LPeg ~> 1.0' +} diff --git a/plugins/administration.lua b/plugins/administration.lua index 277c816..3f9a39a 100644 --- a/plugins/administration.lua +++ b/plugins/administration.lua @@ -1063,7 +1063,7 @@ function administration.init_command(self_) local input = utilities.input(msg.text) or msg.chat.id_str local output if self.database.administration.groups[input] then - local chat_name = self.administration.groups[input].name + local chat_name = self.database.administration.groups[input].name self.database.administration.groups[input] = nil for i,v in ipairs(self.database.administration.activity) do if v == input then diff --git a/plugins/bandersnatch.lua b/plugins/bandersnatch.lua index 6d9779f..5d44e81 100755 --- a/plugins/bandersnatch.lua +++ b/plugins/bandersnatch.lua @@ -29,7 +29,7 @@ function bandersnatch:action(msg) output = firstnames[math.random(#firstnames)] .. ' ' .. lastnames[math.random(#lastnames)] end - bindings.sendReply(self, msg, output) + bindings.sendMessage(self, msg.chat.id, '_'..output..'_', true, nil, true) end diff --git a/plugins/calc.lua b/plugins/calc.lua index 53a5bfd..0ee1070 100755 --- a/plugins/calc.lua +++ b/plugins/calc.lua @@ -22,7 +22,7 @@ function calc:action(msg) if msg.reply_to_message and msg.reply_to_message.text then input = msg.reply_to_message.text else - bindings.sendMessage(msg.chat.id, calc.doc, true, msg.message_id, true) + bindings.sendMessage(self, msg.chat.id, calc.doc, true, msg.message_id, true) return end end diff --git a/plugins/control.lua b/plugins/control.lua index a8f372b..b1c6c75 100644 --- a/plugins/control.lua +++ b/plugins/control.lua @@ -17,6 +17,14 @@ function control:action(msg) if msg.date < os.time() - 1 then return end if msg.text:match('^'..utilities.INVOCATION_PATTERN..'reload') then + for pac, _ in pairs(package.loaded) do + if pac:match('^plugins%.') then + package.loaded[pac] = nil + end + package.loaded['bindings'] = nil + package.loaded['utilities'] = nil + package.loaded['config'] = nil + end bot.init(self) bindings.sendReply(self, msg, 'Bot reloaded!') elseif msg.text:match('^'..utilities.INVOCATION_PATTERN..'halt') then diff --git a/plugins/currency.lua b/plugins/currency.lua index dc2a935..d4b1936 100755 --- a/plugins/currency.lua +++ b/plugins/currency.lua @@ -52,7 +52,8 @@ function currency:action(msg) end local output = amount .. ' ' .. from .. ' = ' .. result .. ' ' .. to .. '\n\n' - output = output .. '`' .. os.date('!%F %T UTC') .. '\nSource: Google Finance`' + output = output .. os.date('!%F %T UTC') .. '\nSource: Google Finance`' + output = '```\n' .. output .. '\n```' bindings.sendMessage(self, msg.chat.id, output, true, nil, true) diff --git a/plugins/imdb.lua b/plugins/imdb.lua index 5c142f5..0ee3dd7 100755 --- a/plugins/imdb.lua +++ b/plugins/imdb.lua @@ -46,7 +46,7 @@ function imdb:action(msg) local output = '*' .. jdat.Title .. ' ('.. jdat.Year ..')*\n' output = output .. jdat.imdbRating ..'/10 | '.. jdat.Runtime ..' | '.. jdat.Genre ..'\n' output = output .. '_' .. jdat.Plot .. '_\n' - output = output .. '[*Read more*](http://imdb.com/title/' .. jdat.imdbID .. ')' + output = output .. '[Read more.](http://imdb.com/title/' .. jdat.imdbID .. ')' bindings.sendMessage(self, msg.chat.id, output, true, nil, true) diff --git a/plugins/luarun.lua b/plugins/luarun.lua index f88f44d..c416adb 100644 --- a/plugins/luarun.lua +++ b/plugins/luarun.lua @@ -19,7 +19,7 @@ function luarun:action(msg) return end - local output = loadstring('local bindings = require(\'bindings\'); local utilities = require(\'utilities\'); return function (instance, msg) '..input..' end')()(self, msg) + local output = loadstring('local bindings = require(\'bindings\'); local utilities = require(\'utilities\'); return function (self, msg) '..input..' end')()(self, msg) if output == nil then output = 'Done!' elseif type(output) == 'table' then diff --git a/plugins/reactions.lua b/plugins/reactions.lua index 8b73c82..5a08052 100755 --- a/plugins/reactions.lua +++ b/plugins/reactions.lua @@ -24,17 +24,17 @@ local help function reactions:init() -- Generate a "help" message triggered by "/reactions". - local help = 'Reactions:\n' + help = 'Reactions:\n' reactions.triggers = utilities.triggers(self.info.username):t('reactions').table for trigger,reaction in pairs(mapping) do - help = help .. '• ' .. trigger:gsub('.%?', '') .. ': ' .. reaction .. '\n' + help = help .. '• ' .. utilities.INVOCATION_PATTERN..trigger .. trigger:gsub('.%?', '') .. ': ' .. reaction .. '\n' table.insert(reactions.triggers, utilities.INVOCATION_PATTERN..trigger) - table.insert(reactions.triggers, utilities.INVOCATION_PATTERN..trigger..'@'..self.username:lower()) + table.insert(reactions.triggers, utilities.INVOCATION_PATTERN..trigger..'@'..self.info.username:lower()) end end function reactions:action(msg) - if string.match(msg.text_lower, utilities.INVOCATION_PATTERN..'help') then + if string.match(msg.text_lower, utilities.INVOCATION_PATTERN..'reactions') then bindings.sendMessage(self, msg.chat.id, help) return end diff --git a/plugins/remind.lua b/plugins/remind.lua index ea6ad94..b4fca96 100644 --- a/plugins/remind.lua +++ b/plugins/remind.lua @@ -17,7 +17,7 @@ end function remind:action(msg) -- Ensure there are arguments. If not, send doc. - local input = msg.text:input() + local input = utilities.input(msg.text) if not input then bindings.sendMessage(self, msg.chat.id, remind.doc, true, msg.message_id, true) return @@ -36,7 +36,7 @@ function remind:action(msg) duration = 526000 end -- Ensure there is a second arg. - local message = input:input() + local message = utilities.input(input) if not message then bindings.sendMessage(self, msg.chat.id, remind.doc, true, msg.message_id, true) return diff --git a/plugins/time.lua b/plugins/time.lua index b3867d6..be47ddd 100755 --- a/plugins/time.lua +++ b/plugins/time.lua @@ -53,9 +53,10 @@ function time:action(msg) else utcoff = utilities.pretty_float(utcoff) end - local output = '`' .. os.date('!%I:%M %p\n', timestamp) .. os.date('!%A, %B %d, %Y\n', timestamp) .. jdat.timeZoneName .. ' (UTC' .. utcoff .. ')``' + local output = os.date('!%I:%M %p\n', timestamp) .. os.date('!%A, %B %d, %Y\n', timestamp) .. jdat.timeZoneName .. ' (UTC' .. utcoff .. ')' + output = '```\n' .. output .. '\n```' - bindings.sendReply(self, msg, output) + bindings.sendReply(self, msg, output, true) end diff --git a/plugins/translate.lua b/plugins/translate.lua index 01732ef..204f297 100755 --- a/plugins/translate.lua +++ b/plugins/translate.lua @@ -45,7 +45,7 @@ function translate:action(msg) local output = jdat.text[1] output = '*Translation:*\n"' .. utilities.md_escape(output) .. '"' - bindings.sendReply(self, msg.reply_to_message or msg, output) + bindings.sendReply(self, msg.reply_to_message or msg, output, true) end diff --git a/plugins/weather.lua b/plugins/weather.lua index d06286a..89ea62d 100755 --- a/plugins/weather.lua +++ b/plugins/weather.lua @@ -57,7 +57,7 @@ function weather:action(msg) local fahrenheit = string.format('%.2f', celsius * (9/5) + 32) local output = '`' .. celsius .. '°C | ' .. fahrenheit .. '°F, ' .. jdat.weather[1].description .. '.`' - bindings.sendReply(self, msg, output) + bindings.sendReply(self, msg, output, true) end