From 24deaec7596fa6ff4df3a681178d2407c7aab177 Mon Sep 17 00:00:00 2001 From: Brayden Banks Date: Sun, 10 Apr 2016 21:04:47 -0700 Subject: [PATCH] *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