*Should* have a working local refactor now.

This commit is contained in:
Brayden Banks 2016-04-10 21:04:47 -07:00
parent acb679f8fa
commit 24deaec759
49 changed files with 1026 additions and 952 deletions

View File

@ -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: A plugin can have five components, and two of them are required:
| Component | Description | Required? | | Component | Description | Required? |
|:----------|:-----------------------------------------------------|:----------| |:----------|:---------------------------------------------|:----------|
| action | Main function. Expects `msg` table as an argument. | Y | | action | Main function. Expects `msg` table as an argument. | Y |
| triggers | Table of triggers for the plugin. Uses Lua patterns. | Y | | triggers | Table of triggers for the plugin. Uses Lua patterns. | Y |
| cron | Optional function to be called every minute. | N | | cron | Optional function to be called every minute. | N |
| command | Basic command and syntax. Listed in the help text. | N | | command | Basic command and syntax. Listed in the help text. | N |
| doc | Usage for the plugin. Returned by "/help $command". | 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`. 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`.

26
bot.lua
View File

@ -1,5 +1,7 @@
local bot = {} local bot = {}
local instance = {}
local bindings = require('bindings') -- Load Telegram bindings. local bindings = require('bindings') -- Load Telegram bindings.
local utilities = require('utilities') -- Load miscellaneous and cross-plugin functions. 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 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 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 if res then
for _,v in ipairs(res.result) do -- Go through every new message. for _,v in ipairs(res.result) do -- Go through every new message.
bot.last_update = v.update_id instance.last_update = v.update_id
bot.on_msg_receive(bot, v.message) bot.on_msg_receive(instance, v.message)
end end
else else
print(bot.config.errors.connection) print(instance.config.errors.connection)
end end
end end
if bot.last_cron ~= os.date('%M') then -- Run cron jobs every minute. if instance.last_cron ~= os.date('%M') then -- Run cron jobs every minute.
bot.last_cron = os.date('%M') instance.last_cron = os.date('%M')
utilities.save_data(bot.info.username..'.db', bot.database) -- Save the database. utilities.save_data(instance.info.username..'.db', instance.database) -- Save the database.
for i,v in ipairs(bot.plugins) do for i,v in ipairs(instance.plugins) do
if v.cron then -- Call each plugin's cron function, if it has one. if v.cron then -- Call each plugin's cron function, if it has one.
local res, err = pcall(function() v.cron() end) local res, err = pcall(function() v.cron() end)
if not res then if not res then
utilities.handle_exception(bot, err, 'CRON: ' .. i) utilities.handle_exception(instance, err, 'CRON: ' .. i)
end end
end end
end end
@ -147,5 +149,5 @@ while bot.is_started do -- Start a loop while the bot should be running.
end end
-- Save the database before exiting. -- 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.') print('Halted.')

View File

@ -1,5 +1,6 @@
local about = {} local about = {}
local bot = require('bot')
local bindings = require('bindings') local bindings = require('bindings')
about.command = 'about' about.command = 'about'
@ -15,7 +16,7 @@ function about:action(msg)
-- other plugins. -- other plugins.
if msg.forward_from then return end 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 if msg.new_chat_participant and msg.new_chat_participant.id == self.info.id then
bindings.sendMessage(self, msg.chat.id, message, true) bindings.sendMessage(self, msg.chat.id, message, true)

View File

@ -26,7 +26,7 @@ function bible:action(msg)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then 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 return
end end

View File

@ -14,7 +14,7 @@ end
cats.command = 'cat' cats.command = 'cat'
cats.doc = '`Returns a cat!`' cats.doc = '`Returns a cat!`'
cats.triggers = utilities.triggers():t('cat') cats.triggers = utilities.triggers():t('cat').table
function cats:action(msg) function cats:action(msg)

View File

@ -1,24 +1,33 @@
-- Put this absolutely at the end, even after greetings.lua. -- Put this absolutely at the end, even after greetings.lua.
if not config.simsimi_key then local chatter = {}
print('Missing config value: simsimi_key.')
print('chatter.lua will not be enabled.') local HTTP = require('socket.http')
return 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 end
local triggers = { function chatter:action(msg)
'',
'^' .. bot.first_name .. ',',
'^@' .. bot.username .. ','
}
local action = function(msg)
if msg.text == '' then return end if msg.text == '' then return end
-- This is awkward, but if you have a better way, please share. -- This is awkward, but if you have a better way, please share.
if msg.text_lower:match('^' .. bot.first_name .. ',') then if msg.text_lower:match('^' .. self.info.first_name .. ',')
elseif msg.text_lower:match('^@' .. bot.username .. ',') then or msg.text_lower:match('^@' .. self.info.username .. ',') then
elseif msg.text:match('^/') then elseif msg.text:match('^/') then
return true return true
-- Uncomment the following line for Al Gore-like reply chatter. -- Uncomment the following line for Al Gore-like reply chatter.
@ -28,40 +37,41 @@ local action = function(msg)
return true return true
end end
sendChatAction(msg.chat.id, 'typing') bindings.sendChatAction(self, msg.chat.id, 'typing')
local input = msg.text_lower local input = msg.text_lower
input = input:gsub(bot.first_name, 'simsimi') input = input:gsub(self.info.first_name, 'simsimi')
input = input:gsub('@'..bot.username, 'simsimi') input = input:gsub('@'..self.info.username, 'simsimi')
if config.simsimi_trial then local sandbox
if self.config.simsimi_trial then
sandbox = 'sandbox.' sandbox = 'sandbox.'
else else
sandbox = '' -- NO Sandbox sandbox = '' -- NO Sandbox
end 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) local jstr, res = HTTP.request(url)
if res ~= 200 then if res ~= 200 then
sendMessage(msg.chat.id, config.errors.chatter_connection) bindings.sendMessage(self, msg.chat.id, self.config.errors.chatter_connection)
return return
end end
local jdat = JSON.decode(jstr) local jdat = JSON.decode(jstr)
if not jdat.response then 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 return
end end
local message = jdat.response local message = jdat.response
if message:match('^I HAVE NO RESPONSE.') then if message:match('^I HAVE NO RESPONSE.') then
message = config.errors.chatter_response message = self.config.errors.chatter_response
end end
-- Let's clean up the response a little. Capitalization & punctuation. -- Let's clean up the response a little. Capitalization & punctuation.
local filter = { local filter = {
['%aimi?%aimi?'] = bot.first_name, ['%aimi?%aimi?'] = self.info.first_name,
['^%s*(.-)%s*$'] = '%1', ['^%s*(.-)%s*$'] = '%1',
['^%l'] = string.upper, ['^%l'] = string.upper,
['USER'] = msg.from.first_name ['USER'] = msg.from.first_name
@ -75,11 +85,8 @@ local action = function(msg)
message = message .. '.' message = message .. '.'
end end
sendMessage(msg.chat.id, message) bindings.sendMessage(self, msg.chat.id, message)
end end
return { return chatter
action = action,
triggers = triggers
}

View File

@ -1,11 +1,16 @@
-- Commits from https://github.com/ngerakines/commitment. -- Commits from https://github.com/ngerakines/commitment.
local command = 'commit' local commit = {}
local doc = '`Returns a commit message from whatthecommit.com.`'
local triggers = { local bindings = require('bindings')
'^/commit[@'..bot.username..']*' 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 = { local commits = {
"One does not simply merge into master", "One does not simply merge into master",
@ -416,15 +421,10 @@ local commits = {
"fml" "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 end
return { return commit
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,28 +1,30 @@
local triggers = { local control = {}
'^/reload[@'..bot.username..']*',
'^/halt[@'..bot.username..']*'
}
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 return
end end
if msg.date < os.time() then return end if msg.date < os.time() then return end
if msg.text:match('^/reload') then if msg.text:match('^'..utilities.INVOCATION_PATTERN..'reload') then
bot_init() bot.init(self)
sendReply(msg, 'Bot reloaded!') bindings.sendReply(self, msg, 'Bot reloaded!')
elseif msg.text:match('^/halt') then elseif msg.text:match('^'..utilities.INVOCATION_PATTERN..'halt') then
is_started = false self.is_started = false
sendReply(msg, 'Stopping bot!') bindings.sendReply(self, msg, 'Stopping bot!')
end end
end end
return { return control
action = action,
triggers = triggers
}

View File

@ -1,26 +1,32 @@
local command = 'cash [amount] <from> to <to>' local currency = {}
local doc = [[```
local HTTPS = require('ssl.https')
local bindings = require('bindings')
local utilities = require('utilities')
currency.command = 'cash [amount] <from> to <to>'
currency.doc = [[```
/cash [amount] <from> to <to> /cash [amount] <from> to <to>
Example: /cash 5 USD to EUR Example: /cash 5 USD to EUR
Returns exchange rates for various currencies. Returns exchange rates for various currencies.
Source: Google Finance. Source: Google Finance.
```]] ```]]
local triggers = { function currency:init()
'^/cash[@'..bot.username..']*' 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() local input = msg.text:upper()
if not input:match('%a%a%a TO %a%a%a') then 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 return
end end
local from = input:match('(%a%a%a) TO') local from = input:match('(%a%a%a) TO')
local to = input:match('TO (%a%a%a)') 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 amount = tonumber(amount) or 1
local result = 1 local result = 1
@ -28,16 +34,16 @@ local action = function(msg)
if from ~= to then 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) local str, res = HTTPS.request(url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
str = str:match('<span class=bld>(.*) %u+</span>') str = str:match('<span class=bld>(.*) %u+</span>')
if not str then if not str then
sendReply(msg, config.errors.results) bindings.sendReply(self, msg, self.config.errors.results)
return return
end end
@ -49,13 +55,8 @@ local action = function(msg)
output = output .. os.date('!%F %T UTC') .. '\nSource: Google Finance' output = output .. os.date('!%F %T UTC') .. '\nSource: Google Finance'
output = '`' .. output .. '`' output = '`' .. output .. '`'
sendMessage(msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end end
return { return currency
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,18 +1,23 @@
local command = 'roll <nDr>' local dice = {}
local doc = [[```
local bindings = require('bindings')
local utilities = require('utilities')
dice.command = 'roll <nDr>'
dice.doc = [[```
/roll <nDr> /roll <nDr>
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. 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 = { function dice:init()
'^/roll[@'..bot.username..']*' 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) local input = utilities.input(msg.text_lower)
if not input then 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 return
end end
@ -23,7 +28,7 @@ local action = function(msg)
count = 1 count = 1
range = input:match('^d?([%d]+)$') range = input:match('^d?([%d]+)$')
else 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 return
end end
@ -31,27 +36,22 @@ local action = function(msg)
range = tonumber(range) range = tonumber(range)
if range < 2 then if range < 2 then
sendReply(msg, 'The minimum range is 2.') bindings.sendReply(self, msg, 'The minimum range is 2.')
return return
end end
if range > 1000 or count > 1000 then 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 return
end end
local output = '*' .. count .. 'd' .. range .. '*\n`' local output = '*' .. count .. 'd' .. range .. '*\n`'
for i = 1, count do for _ = 1, count do
output = output .. math.random(range) .. '\t' output = output .. math.random(range) .. '\t'
end end
output = output .. '`' 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 end
return { return dice
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,20 +1,25 @@
dilbert = dilbert or {} local dilbert = {}
local command = 'dilbert [date]' local HTTP = require('socket.http')
local doc = [[``` local URL = require('socket.url')
local bindings = require('bindings')
local utilities = require('utilities')
dilbert.command = 'dilbert [date]'
dilbert.doc = [[```
/dilbert [YYYY-MM-DD] /dilbert [YYYY-MM-DD]
Returns the latest Dilbert strip or that of the provided date. 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. Dates before the first strip will return the first strip. Dates after the last trip will return the last strip.
Source: dilbert.com Source: dilbert.com
```]] ```]]
local triggers = { function dilbert:init()
'^/dilbert[@'..bot.username..']*' 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) local input = utilities.input(msg.text)
if not input then input = os.date('%F') end 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 url = 'http://dilbert.com/strip/' .. URL.escape(input)
local str, res = HTTP.request(url) local str, res = HTTP.request(url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
if not dilbert[input] then local strip_file = io.open('/tmp/' .. input .. '.gif')
if not strip_file then
local strip_url = str:match('<meta property="og:image" content="(.-)"/>') local strip_url = str:match('<meta property="og:image" content="(.-)"/>')
dilbert[input] = download_file(strip_url, '/tmp/' .. input .. '.gif') strip_file = utilities.download_file(strip_url, '/tmp/' .. input .. '.gif')
end end
local strip_title = str:match('<meta property="article:publish_date" content="(.-)"/>') local strip_title = str:match('<meta property="article:publish_date" content="(.-)"/>')
sendPhoto(msg.chat.id, dilbert[input], strip_title) bindings.sendPhoto(self, msg.chat.id, strip_file, strip_title)
strip_file:close()
end end
return { return dilbert
command = command,
doc = doc,
triggers = triggers,
action = action
}

View File

@ -1,35 +1,35 @@
local command = 'echo <text>' local echo = {}
local doc = [[```
local bindings = require('bindings')
local utilities = require('utilities')
echo.command = 'echo <text>'
echo.doc = [[```
/echo <text> /echo <text>
Repeats a string of text. Repeats a string of text.
```]] ```]]
local triggers = { function echo:init()
'^/echo[@'..bot.username..']*' 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) local input = utilities.input(msg.text)
if not input then 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 else
local output local output
if msg.chat.type == 'supergroup' then if msg.chat.type == 'supergroup' then
output = 'Echo:\n"' .. input .. '"' output = 'Echo:\n"' .. input .. '"'
else else
output = latcyr(input) output = utilities.latcyr(input)
end end
sendMessage(msg.chat.id, output, true) bindings.sendMessage(self, msg.chat.id, output, true)
end end
end end
return { return echo
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,10 +1,14 @@
local command = '8ball' local eightball = {}
local doc = '`Returns an answer from a magic 8-ball!`'
local triggers = { local bindings = require('bindings')
'^/8ball', local utilities = require('utilities')
'y/n%p?$'
} 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 = { local ball_answers = {
"It is certain.", "It is certain.",
@ -37,7 +41,7 @@ local yesno_answers = {
'No.' 'No.'
} }
local action = function(msg) function eightball:action(msg)
if msg.reply_to_message then if msg.reply_to_message then
msg = msg.reply_to_message msg = msg.reply_to_message
@ -51,13 +55,8 @@ local action = function(msg)
message = ball_answers[math.random(#ball_answers)] message = ball_answers[math.random(#ball_answers)]
end end
sendReply(msg, message) bindings.sendReply(self, msg, message)
end end
return { return eightball
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,22 +1,29 @@
-- Liberbot-compliant floodcontrol. -- Liberbot-compliant floodcontrol.
-- Put this after moderation.lua or blacklist.lua. -- 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 return
end 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 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. return -- Only run for Liberbot or the admin.
end end
@ -29,25 +36,21 @@ local action = function(msg)
input.duration = 600 input.duration = 600
end 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.' local output = input.groupid .. ' silenced for ' .. input.duration .. ' seconds.'
handle_exception('floodcontrol.lua', output) utilities.handle_exception(self, 'floodcontrol.lua', output)
end 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 if os.time() > v then
floodcontrol[k] = nil self.floodcontrol[k] = nil
end end
end end
end end
return { return floodcontrol
action = action,
triggers = triggers,
cron = cron
}

View File

@ -1,29 +1,29 @@
-- Requires that the "fortune" program is installed on your computer. -- Requires that the "fortune" program is installed on your computer.
local s = io.popen('fortune'):read('*all') local fortune = {}
if s:match('not found$') then
print('fortune is not installed on this computer.') local bindings = require('bindings')
print('fortune.lua will not be enabled.') local utilities = require('utilities')
return
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 end
local command = 'fortune' fortune.command = 'fortune'
local doc = '`Returns a UNIX fortune.`' fortune.doc = '`Returns a UNIX fortune.`'
local triggers = { function fortune:action(msg)
'^/fortune[@'..bot.username..']*'
}
local action = function(msg)
local message = io.popen('fortune'):read('*all') local message = io.popen('fortune'):read('*all')
sendMessage(msg.chat.id, message) bindings.sendMessage(self, msg.chat.id, message)
end end
return { return fortune
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -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 need a Google API key and a Google Custom Search Engine set up to use this, in config.google_api_key and config.google_cse_key, respectively.
-- You must also sign up for the CSE in the Google Developer Concsole, and enable image results. -- You must also sign up for the CSE in the Google Developer Concsole, and enable image results.
if not config.google_api_key then local gImages = {}
print('Missing config value: google_api_key.')
print('gImages.lua will not be enabled.') local HTTPS = require('ssl.https')
return local URL = require('socket.url')
elseif not config.google_cse_key then local JSON = require('cjson')
print('Missing config value: google_cse_key.') local bindings = require('bindings')
print('gImages.lua will not be enabled.') local utilities = require('utilities')
return
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 end
local command = 'image <query>' gImages.command = 'image <query>'
local doc = [[``` gImages.doc = [[```
/image <query> /image <query>
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. 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 Alias: /i
```]] ```]]
local triggers = { function gImages:action(msg)
'^/image[@'..bot.username..']*',
'^/i[@'..bot.username..']* ',
'^/i[@'..bot.username..']*$',
'^/insfw[@'..bot.username..']*'
}
local action = function(msg)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if not input then
if msg.reply_to_message and msg.reply_to_message.text then if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text input = msg.reply_to_message.text
else 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 return
end end
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 if not string.match(msg.text, '^/i[mage]*nsfw') then
url = url .. '&safe=high' url = url .. '&safe=high'
@ -47,13 +52,13 @@ local action = function(msg)
local jstr, res = HTTPS.request(url) local jstr, res = HTTPS.request(url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(jstr) local jdat = JSON.decode(jstr)
if jdat.searchInformation.totalResults == '0' then if jdat.searchInformation.totalResults == '0' then
sendReply(msg, config.errors.results) bindings.sendReply(self, msg, self.config.errors.results)
return return
end end
@ -64,16 +69,11 @@ local action = function(msg)
if msg.text:match('nsfw') then if msg.text:match('nsfw') then
sendReply(msg, result) bindings.sendReply(self, msg, output)
else else
sendMessage(msg.chat.id, output, false, nil, true) bindings.sendMessage(self, msg.chat.id, output, false, nil, true)
end end
end end
return { return gImages
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,41 +1,39 @@
local command = 'location <query>' local gMaps = {}
local doc = [[```
local bindings = require('bindings')
local utilities = require('utilities')
gMaps.command = 'location <query>'
gMaps.doc = [[```
/location <query> /location <query>
Returns a location from Google Maps. Returns a location from Google Maps.
Alias: /loc Alias: /loc
```]] ```]]
local triggers = { function gMaps:init()
'^/location[@'..bot.username..']*', gMaps.triggers = utilities.triggers(self.info.username):t('location', true):t('loc', true).table
'^/loc[@'..bot.username..']* ', end
'^/loc[@'..bot.username..']*$'
}
local action = function(msg) function gMaps:action(msg)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if not input then
if msg.reply_to_message and msg.reply_to_message.text then if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text input = msg.reply_to_message.text
else 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 return
end end
end end
local coords = get_coords(input) local coords = utilities.get_coords(self, input)
if type(coords) == 'string' then if type(coords) == 'string' then
sendReply(msg, coords) bindings.sendReply(self, msg, coords)
return return
end 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 end
return { return gMaps
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,25 +1,30 @@
local command = 'google <query>' local gSearch = {}
local doc = [[```
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 <query>'
gSearch.doc = [[```
/google <query> /google <query>
Returns four (if group) or eight (if private message) results from Google. Safe search is enabled by default, use "/gnsfw" to disable it. 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 Alias: /g
```]] ```]]
local triggers = { function gSearch:init()
'^/g[@'..bot.username..']*$', gSearch.triggers = utilities.triggers(self.info.username):t('g', true):t('google', true):t('gnsfw', true).table
'^/g[@'..bot.username..']* ', end
'^/google[@'..bot.username..']*',
'^/gnsfw[@'..bot.username..']*'
}
local action = function(msg) function gSearch:action(msg)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if not input then
if msg.reply_to_message and msg.reply_to_message.text then if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text input = msg.reply_to_message.text
else 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 return
end end
end end
@ -40,22 +45,22 @@ local action = function(msg)
local jstr, res = HTTPS.request(url) local jstr, res = HTTPS.request(url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(jstr) local jdat = JSON.decode(jstr)
if not jdat.responseData then if not jdat.responseData then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
if not jdat.responseData.results[1] then if not jdat.responseData.results[1] then
sendReply(msg, config.errors.results) bindings.sendReply(self, msg, self.config.errors.results)
return return
end end
local output = '*Google results for* _' .. input .. '_ *:*\n' 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('&amp;', '&') local title = jdat.responseData.results[i].titleNoFormatting:gsub('%[.+%]', ''):gsub('&amp;', '&')
--[[ --[[
if title:len() > 48 then if title:len() > 48 then
@ -70,13 +75,8 @@ local action = function(msg)
end end
end end
sendMessage(msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end end
return { return gSearch
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -2,47 +2,54 @@
-- If you want to configure your own greetings, copy the following table -- If you want to configure your own greetings, copy the following table
-- (without the "config.") to your config.lua file. -- (without the "config.") to your config.lua file.
if not config.greetings then local greetings = {}
config.greetings = {
['Hello, #NAME.'] = { local bindings = require('bindings')
'hello', local utilities = require('utilities')
'hey',
'sup', function greetings:init()
'hi', if not self.config.greetings then
'good morning', self.config.greetings = {
'good day', ['Hello, #NAME.'] = {
'good afternoon', 'hello',
'good evening' 'hey',
}, 'sup',
['Goodbye, #NAME.'] = { 'hi',
'bye', 'good morning',
'later', 'good day',
'see ya', 'good afternoon',
'good night' 'good evening'
}, },
['Welcome back, #NAME.'] = { ['Goodbye, #NAME.'] = {
'i\'m home', 'bye',
'i\'m back' 'later',
}, 'see ya',
['You\'re welcome, #NAME.'] = { 'good night'
'thanks', },
'thank you' ['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 end
local triggers = { function greetings:action(msg)
bot.first_name .. '%p*$'
}
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 trigger,responses in pairs(self.config.greetings) do
for _,response in pairs(responses) do
for k,v in pairs(config.greetings) do if msg.text_lower:match(response..',? '..self.info.first_name) then
for key,val in pairs(v) do bindings.sendMessage(self, msg.chat.id, utilities.latcyr(trigger:gsub('#NAME', nick)))
if msg.text_lower:match(val..',? '..bot.first_name) then
sendMessage(msg.chat.id, latcyr(k:gsub('#NAME', nick)))
return return
end end
end end
@ -52,7 +59,4 @@ local action = function(msg)
end end
return { return greetings
action = action,
triggers = triggers
}

View File

@ -1,21 +1,25 @@
local command = 'hackernews' local hackernews = {}
local doc = [[```
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. Returns four (if group) or eight (if private message) top stories from Hacker News.
Alias: /hn Alias: /hn
```]] ```]]
local triggers = { hackernews.triggers = utilities.triggers():t('hackernews', true):t('hn', true).table
'^/hackernews[@'..bot.username..']*',
'^/hn[@'..bot.username..']*'
}
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') local jstr, res = HTTPS.request('https://hacker-news.firebaseio.com/v0/topstories.json')
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
@ -31,7 +35,7 @@ local action = function(msg)
local res_url = 'https://hacker-news.firebaseio.com/v0/item/' .. jdat[i] .. '.json' local res_url = 'https://hacker-news.firebaseio.com/v0/item/' .. jdat[i] .. '.json'
jstr, res = HTTPS.request(res_url) jstr, res = HTTPS.request(res_url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local res_jdat = JSON.decode(jstr) local res_jdat = JSON.decode(jstr)
@ -41,7 +45,7 @@ local action = function(msg)
end end
local url = res_jdat.url local url = res_jdat.url
if not url then if not url then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
if url:find('%(') then if url:find('%(') then
@ -52,13 +56,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 end
return { return hackernews
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,45 +1,50 @@
-- Plugin for the Hearthstone database provided by hearthstonejson.com. -- 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 = { function hearthstone:init()
expiration = os.time() + 600000 if not self.database.hearthstone or os.time() > self.database.hearthstone.expiration then
}
local jstr, res = HTTPS.request('http://hearthstonejson.com/json/AllSets.json') print('Downloading Hearthstone database...')
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 k,v in pairs(jdat) do self.database.hearthstone = {
for key,val in pairs(v) do expiration = os.time() + 600000
table.insert(database.hearthstone, val) }
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 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 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 end
local command = 'hearthstone <query>' hearthstone.command = 'hearthstone <query>'
local doc = [[``` hearthstone.doc = [[```
/hearthstone <query> /hearthstone <query>
Returns Hearthstone card info. Returns Hearthstone card info.
Alias: /hs Alias: /hs
```]] ```]]
local triggers = { local function format_card(card)
'^/hearthstone[@'..bot.username..']*',
'^/hs[@'..bot.username..']*$',
'^/hs[@'..bot.username..']* '
}
local format_card = function(card)
local ctype = card.type local ctype = card.type
if card.race then if card.race then
@ -70,6 +75,7 @@ local format_card = function(card)
stats = card.health .. 'h' stats = card.health .. 'h'
end end
-- unused?
local info = '' local info = ''
if card.text then if card.text then
info = card.text:gsub('</?.->',''):gsub('%$','') info = card.text:gsub('</?.->',''):gsub('%$','')
@ -94,16 +100,16 @@ local format_card = function(card)
end end
local action = function(msg) function hearthstone:action(msg)
local input = utilities.input(msg.text_lower) local input = utilities.input(msg.text_lower)
if not input then 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 return
end end
local output = '' 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 if type(v) == 'table' and string.lower(v.name):match(input) then
output = output .. format_card(v) .. '\n\n' output = output .. format_card(v) .. '\n\n'
end end
@ -111,17 +117,12 @@ local action = function(msg)
output = output:trim() output = output:trim()
if output:len() == 0 then if output:len() == 0 then
sendReply(msg, config.errors.results) bindings.sendReply(self, msg, self.config.errors.results)
return return
end end
sendMessage(msg.chat.id, output, true, msg.message_id, true) bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true)
end end
return { return hearthstone
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,12 +1,21 @@
-- This plugin should go at the end of your plugin list in -- This plugin should go at the end of your plugin list in
-- config.lua, but not after greetings.lua. -- config.lua, but not after greetings.lua.
local help = {}
local bindings = require('bindings')
local utilities = require('utilities')
local help_text = '*Available commands:*' local help_text = '*Available commands:*'
for i,v in ipairs(plugins) do function help:init()
if v.command then for _,plugin in ipairs(self.plugins) do
help_text = help_text .. '\n• /' .. v.command:gsub('%[', '\\[') if plugin.command then
help_text = help_text .. '\n• /' .. plugin.command:gsub('%[', '\\[')
end
end end
help.triggers = utilities.triggers():t('help', true):t('h', true).table
end end
help_text = help_text .. [[ help_text = help_text .. [[
@ -15,40 +24,32 @@ help_text = help_text .. [[
Arguments: <required> \[optional] Arguments: <required> \[optional]
]] ]]
local triggers = { function help:action(msg)
'^/help[@'..bot.username..']*',
'^/h[@'..bot.username..']*$'
}
local action = function(msg)
local input = utilities.input(msg.text_lower) local input = utilities.input(msg.text_lower)
-- Attempts to send the help message via PM. -- Attempts to send the help message via PM.
-- If msg is from a group, it tells the group whether the PM was successful. -- If msg is from a group, it tells the group whether the PM was successful.
if not input then 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 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 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 end
return return
end end
for i,v in ipairs(plugins) do for _,plugin in ipairs(self.plugins) do
if v.command and get_word(v.command, 1) == input and v.doc then if plugin.command and utilities.get_word(plugin.command, 1) == input and plugin.doc then
local output = '*Help for* _' .. get_word(v.command, 1) .. '_ *:*\n' .. v.doc local output = '*Help for* _' .. utilities.get_word(plugin.command, 1) .. '_ *:*\n' .. plugin.doc
sendMessage(msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
return return
end end
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 end
return { return help
action = action,
triggers = triggers
}

View File

@ -1,21 +1,29 @@
local command = 'imdb <query>' local imdb = {}
local doc = [[```
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 <query>'
imdb.doc = [[```
/imdb <query> /imdb <query>
Returns an IMDb entry. Returns an IMDb entry.
```]] ```]]
local triggers = { function imdb:init()
'^/imdb[@'..bot.username..']*' 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) local input = utilities.input(msg.text)
if not input then if not input then
if msg.reply_to_message and msg.reply_to_message.text then if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text input = msg.reply_to_message.text
else 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 return
end end
end end
@ -24,14 +32,14 @@ local action = function(msg)
local jstr, res = HTTP.request(url) local jstr, res = HTTP.request(url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(jstr) local jdat = JSON.decode(jstr)
if jdat.Response ~= 'True' then if jdat.Response ~= 'True' then
sendReply(msg, config.errors.results) bindings.sendReply(self, msg, self.config.errors.results)
return return
end end
@ -40,13 +48,8 @@ local action = function(msg)
output = output .. jdat.imdbRating ..'/10 | '.. jdat.Runtime ..' | '.. jdat.Genre ..'\n' output = output .. jdat.imdbRating ..'/10 | '.. jdat.Runtime ..' | '.. jdat.Genre ..'\n'
output = output .. jdat.Plot output = output .. jdat.Plot
sendMessage(msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end end
return { return imdb
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,14 +1,23 @@
if not config.lastfm_api_key then local lastfm = {}
print('Missing config value: lastfm_api_key.')
print('lastfm.lua will not be enabled.')
return
end
local HTTP = require('socket.http') 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' function lastfm:init()
local doc = [[``` 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] /np [username]
Returns what you are or were last listening to. If you specify a username, info will be returned for that 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. Sets your last.fm username. Otherwise, /np will use your Telegram username. Use "/fmset --" to delete it.
```]] ```]]
local triggers = { function lastfm:action(msg)
'^/lastfm[@'..bot.username..']*',
'^/np[@'..bot.username..']*',
'^/fmset[@'..bot.username..']*'
}
local action = function(msg)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if string.match(msg.text, '^/lastfm') then 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 return
elseif string.match(msg.text, '^/fmset') then elseif string.match(msg.text, '^/fmset') then
if not input 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 elseif input == '--' or input == '' then
database.users[msg.from.id_str].lastfm = nil self.database.users[msg.from.id_str].lastfm = nil
sendReply(msg, 'Your last.fm username has been forgotten.') bindings.sendReply(self, msg, 'Your last.fm username has been forgotten.')
else else
database.users[msg.from.id_str].lastfm = input self.database.users[msg.from.id_str].lastfm = input
sendReply(msg, 'Your last.fm username has been set to "' .. input .. '".') bindings.sendReply(self, msg, 'Your last.fm username has been set to "' .. input .. '".')
end end
return return
end 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 username
local output = '' local output = ''
if input then if input then
username = input username = input
elseif database.users[msg.from.id_str].lastfm then elseif self.database.users[msg.from.id_str].lastfm then
username = database.users[msg.from.id_str].lastfm username = self.database.users[msg.from.id_str].lastfm
elseif msg.from.username then elseif msg.from.username then
username = msg.from.username username = msg.from.username
output = '\n\nYour username has been set to ' .. username .. '.\nTo change it, use /fmset <username>.' output = '\n\nYour username has been set to ' .. username .. '.\nTo change it, use /fmset <username>.'
database.users[msg.from.id_str].lastfm = username self.database.users[msg.from.id_str].lastfm = username
else 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 return
end end
url = url .. URL.escape(username) 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 if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(jstr) local jdat = JSON.decode(jstr)
if jdat.error then 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 return
end end
local jdat = jdat.recenttracks.track[1] or jdat.recenttracks.track jdat = jdat.recenttracks.track[1] or jdat.recenttracks.track
if not jdat then if not jdat then
sendReply(msg, 'No history for this user.' .. output) bindings.sendReply(self, msg, 'No history for this user.' .. output)
return return
end end
@ -95,13 +102,8 @@ local action = function(msg)
end end
message = message .. title .. ' - ' .. artist .. output message = message .. title .. ' - ' .. artist .. output
sendMessage(msg.chat.id, message) bindings.sendMessage(self, msg.chat.id, message)
end end
return { return lastfm
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,9 +1,21 @@
if not database.librefm then local librefm = {}
database.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 end
local command = 'librefm' librefm.command = 'librefm'
local doc = [[``` librefm.doc = [[```
/lnp [username] /lnp [username]
Returns what you are or were last listening to. If you specify a username, info will be returned for that 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. Sets your libre.fm username. Otherwise, /np will use your Telegram username. Use "/fmset -" to delete it.
```]] ```]]
local triggers = { function librefm:action(msg)
'^/librefm[@'..bot.username..']*',
'^/lnp[@'..bot.username..']*',
'^/lfmset[@'..bot.username..']*'
}
local action = function(msg)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if string.match(msg.text, '^/librefm') then 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 return
elseif string.match(msg.text, '^/lfmset') then elseif string.match(msg.text, '^/lfmset') then
if not input 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 elseif input == '-' then
database.lastfm[msg.from.id_str] = nil self.database.lastfm[msg.from.id_str] = nil
sendReply(msg, 'Your libre.fm username has been forgotten.') bindings.sendReply(self, msg, 'Your libre.fm username has been forgotten.')
else else
database.lastfm[msg.from.id_str] = input self.database.lastfm[msg.from.id_str] = input
sendReply(msg, 'Your libre.fm username has been set to "' .. input .. '".') bindings.sendReply(self, msg, 'Your libre.fm username has been set to "' .. input .. '".')
end end
return return
end end
@ -43,34 +49,34 @@ local action = function(msg)
local output = '' local output = ''
if input then if input then
username = input username = input
elseif database.lastfm[msg.from.id_str] then elseif self.database.lastfm[msg.from.id_str] then
username = database.lastfm[msg.from.id_str] username = self.database.lastfm[msg.from.id_str]
elseif msg.from.username then elseif msg.from.username then
username = msg.from.username username = msg.from.username
output = '\n\nYour username has been set to ' .. username .. '.\nTo change it, use /lfmset <username>.' output = '\n\nYour username has been set to ' .. username .. '.\nTo change it, use /lfmset <username>.'
database.lastfm[msg.from.id_str] = username self.database.lastfm[msg.from.id_str] = username
else 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 return
end end
url = url .. URL.escape(username) url = url .. URL.escape(username)
jstr, res = HTTPS.request(url) local jstr, res = HTTPS.request(url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(jstr) local jdat = JSON.decode(jstr)
if jdat.error then 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 return
end end
local jdat = jdat.recenttracks.track[1] or jdat.recenttracks.track jdat = jdat.recenttracks.track[1] or jdat.recenttracks.track
if not jdat then if not jdat then
sendReply(msg, 'No history for this user.' .. output) bindings.sendReply(self, msg, 'No history for this user.' .. output)
return return
end end
@ -90,13 +96,8 @@ local action = function(msg)
end end
message = message .. title .. ' - ' .. artist .. output message = message .. title .. ' - ' .. artist .. output
sendMessage(msg.chat.id, message) bindings.sendMessage(self, msg.chat.id, message)
end end
return { return librefm
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,16 +1,21 @@
local triggers = { local luarun = {}
'^/lua[@'..bot.username..']*'
}
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 return
end end
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if not input then
sendReply(msg, 'Please enter a string to load.') bindings.sendReply(self, msg, 'Please enter a string to load.')
return return
end end
@ -22,12 +27,9 @@ local action = function(msg)
else else
output = '```\n' .. tostring(output) .. '\n```' output = '```\n' .. tostring(output) .. '\n```'
end end
sendMessage(msg.chat.id, output, true, msg.message_id, true) bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true)
end end
return { return luarun
action = action,
triggers = triggers
}

View File

@ -1,16 +1,20 @@
local triggers = { local me = {}
'^/me',
'^/me@'..bot.username
}
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 function me:action(msg)
target = user_from_message(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 if target.err then
sendReply(msg, target.err) bindings.sendReply(self, msg, target.err)
return return
end end
end end
@ -19,11 +23,8 @@ local action = function(msg)
for k,v in pairs(target) do for k,v in pairs(target) do
output = output .. '*' .. k .. ':* `' .. tostring(v) .. '`\n' output = output .. '*' .. k .. ':* `' .. tostring(v) .. '`\n'
end end
sendMessage(msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end end
return { return me
triggers = triggers,
action = action
}

View File

@ -3,17 +3,18 @@
-- Put this near the top, after blacklist. -- Put this near the top, after blacklist.
-- If you want to enable antisquig, put that at the top, before blacklist. -- If you want to enable antisquig, put that at the top, before blacklist.
if not database.moderation then local moderation = {}
database.moderation = {}
end local bindings = require('bindings')
local utilities = require('utilities')
local antisquig = {} local antisquig = {}
local commands = { 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 = [[ local output = [[
*Users:* *Users:*
@ -30,17 +31,17 @@ local commands = {
]] ]]
output = output:gsub('\t', '') output = output:gsub('\t', '')
sendMessage(msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end, 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 = '' 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' output = output .. '' .. v .. ' (' .. k .. ')\n'
end end
@ -48,76 +49,76 @@ local commands = {
output = '*Moderators for* _' .. msg.chat.title .. '_ *:*\n' .. output output = '*Moderators for* _' .. msg.chat.title .. '_ *:*\n' .. output
end end
output = output .. '*Administrators for* _' .. config.moderation.realm_name .. '_ *:*\n' output = output .. '*Administrators for* _' .. self.config.moderation.realm_name .. '_ *:*\n'
for k,v in pairs(config.moderation.admins) do for k,v in pairs(self.config.moderation.admins) do
output = output .. '' .. v .. ' (' .. k .. ')\n' output = output .. '' .. v .. ' (' .. k .. ')\n'
end end
sendMessage(msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end, end,
['^/modcast[@'..bot.username..']*'] = function(msg) ['^/modcast'] = function(self, msg)
local output = utilities.input(msg.text) local output = utilities.input(msg.text)
if not output then if not output then
return 'You must include a message.' return 'You must include a message.'
end 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.' return 'This command must be run in the administration group.'
end end
if not config.moderation.admins[msg.from.id_str] then if not self.config.moderation.admins[msg.from.id_str] then
return config.moderation.errors.not_admin return self.config.moderation.errors.not_admin
end end
output = '*Admin Broadcast:*\n' .. output output = '*Admin Broadcast:*\n' .. output
for k,v in pairs(database.moderation) do for k,_ in pairs(self.database.moderation) do
sendMessage(k, output, true, nil, true) bindings.sendMessage(self, k, output, true, nil, true)
end end
return 'Your broadcast has been sent.' return 'Your broadcast has been sent.'
end, end,
['^/modadd[@'..bot.username..']*$'] = function(msg) ['^/modadd$'] = function(self, msg)
if not config.moderation.admins[msg.from.id_str] then if not self.config.moderation.admins[msg.from.id_str] then
return config.moderation.errors.not_admin return self.config.moderation.errors.not_admin
end 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.' return 'I am already moderating this group.'
end end
database.moderation[msg.chat.id_str] = {} self.database.moderation[msg.chat.id_str] = {}
return 'I am now moderating this group.' return 'I am now moderating this group.'
end, end,
['^/modrem[@'..bot.username..']*$'] = function(msg) ['^/modrem$'] = function(self, msg)
if not config.moderation.admins[msg.from.id_str] then if not self.config.moderation.admins[msg.from.id_str] then
return config.moderation.errors.not_admin return self.config.moderation.errors.not_admin
end end
if not database.moderation[msg.chat.id_str] then if not self.database.moderation[msg.chat.id_str] then
return config.moderation.errors.moderation return self.config.moderation.errors.moderation
end end
database.moderation[msg.chat.id_str] = nil self.database.moderation[msg.chat.id_str] = nil
return 'I am no longer moderating this group.' return 'I am no longer moderating this group.'
end, 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 if not self.config.moderation.admins[msg.from.id_str] then
return config.moderation.errors.not_admin return self.config.moderation.errors.not_admin
end end
if not msg.reply_to_message then if not msg.reply_to_message then
@ -127,26 +128,26 @@ local commands = {
local modid = tostring(msg.reply_to_message.from.id) local modid = tostring(msg.reply_to_message.from.id)
local modname = msg.reply_to_message.from.first_name 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.' return modname .. ' is already an administrator.'
end 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.' return modname .. ' is already a moderator.'
end end
database.moderation[msg.chat.id_str][modid] = modname self.database.moderation[msg.chat.id_str][modid] = modname
return modname .. ' is now a moderator.' return modname .. ' is now a moderator.'
end, 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 if not self.config.moderation.admins[msg.from.id_str] then
return config.moderation.errors.not_admin return self.config.moderation.errors.not_admin
end end
local modid = utilities.input(msg.text) local modid = utilities.input(msg.text)
@ -159,28 +160,28 @@ local commands = {
end end
end end
if config.moderation.admins[modid] then if self.config.moderation.admins[modid] then
return config.moderation.admins[modid] .. ' is an administrator.' return self.config.moderation.admins[modid] .. ' is an administrator.'
end 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.' return 'User is not a moderator.'
end end
local modname = database.moderation[msg.chat.id_str][modid] local modname = self.database.moderation[msg.chat.id_str][modid]
database.moderation[msg.chat.id_str][modid] = nil self.database.moderation[msg.chat.id_str][modid] = nil
return modname .. ' is no longer a moderator.' return modname .. ' is no longer a moderator.'
end, 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 self.database.moderation[msg.chat.id_str][msg.from.id_str] then
if not config.moderation.admins[msg.from.id_str] then if not self.config.moderation.admins[msg.from.id_str] then
return config.moderation.errors.not_mod return self.config.moderation.errors.not_mod
end end
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.' return 'Kicks must be done via reply or specification of a user/bot\'s ID or username.'
end 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.' return 'You cannot kick a moderator.'
end 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, 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 self.database.moderation[msg.chat.id_str][msg.from.id_str] then
if not config.moderation.admins[msg.from.id_str] then if not self.config.moderation.admins[msg.from.id_str] then
return config.moderation.errors.not_mod return self.config.moderation.errors.not_mod
end end
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.' return 'Kicks must be done via reply or specification of a user/bot\'s ID or username.'
end 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.' return 'You cannot ban a moderator.'
end 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 end
} }
if config.moderation.antisquig then function moderation:init()
commands['[\216-\219][\128-\191]'] = function(msg) if not self.database.moderation then
self.database.moderation = {}
end
if not database.moderation[msg.chat.id_str] then return true end if self.config.moderation.antisquig then
if config.moderation.admins[msg.from.id_str] then return true end commands['[\216-\219][\128-\191]'] = function(msg)
if database.moderation[msg.chat.id_str][msg.from.id_str] then return true end
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 end
antisquig[msg.from.id] = true end
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 .. '.')
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
end end
local triggers = {} function moderation:action(msg)
for k,v in pairs(commands) do
table.insert(triggers, k)
end
local action = function(msg) for trigger,command in pairs(commands) do
if string.match(msg.text_lower, trigger) then
for k,v in pairs(commands) do local output = command(self, msg)
if string.match(msg.text_lower, k) then
local output = v(msg)
if output == true then if output == true then
return true return true
elseif output then elseif output then
sendReply(msg, output) bindings.sendReply(self, msg, output)
end end
return return
end end
@ -286,14 +300,10 @@ end
-- That user will not be kicked again as long as his ID is in the table. -- That user will not be kicked again as long as his ID is in the table.
-- The table is emptied every five seconds. -- 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. -- 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 = {} antisquig = {}
end end
return { return moderation
action = action,
triggers = triggers,
cron = cron
}

View File

@ -1,18 +1,23 @@
local command = 'nick <nickname>' local nick = {}
local doc = [[```
local bindings = require('bindings')
local utilities = require('utilities')
nick.command = 'nick <nickname>'
nick.doc = [[```
/nick <nickname> /nick <nickname>
Set your nickname. Use "/nick --" to delete it. Set your nickname. Use "/nick --" to delete it.
```]] ```]]
local triggers = { function nick:init()
'^/nick[@'..bot.username..']*' nick.triggers = utilities.triggers(self.info.nick):t('nick', true).table
} end
local action = function(msg) function nick:action(msg)
local target = msg.from 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 = msg.reply_to_message.from
target.id_str = tostring(target.id) target.id_str = tostring(target.id)
target.name = target.first_name target.name = target.first_name
@ -24,28 +29,23 @@ local action = function(msg)
local output local output
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if not input then
if database.users[target.id_str].nickname then if self.database.users[target.id_str].nickname then
output = target.name .. '\'s nickname is "' .. database.users[target.id_str].nickname .. '".' output = target.name .. '\'s nickname is "' .. self.database.users[target.id_str].nickname .. '".'
else else
output = target.name .. ' currently has no nickname.' output = target.name .. ' currently has no nickname.'
end end
elseif string.len(input) > 32 then elseif string.len(input) > 32 then
output = 'The character limit for nicknames is 32.' output = 'The character limit for nicknames is 32.'
elseif input == '--' or input == '' then 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.' output = target.name .. '\'s nickname has been deleted.'
else 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 .. '".' output = target.name .. '\'s nickname has been set to "' .. input .. '".'
end end
sendReply(msg, output) bindings.sendReply(self, msg, output)
end end
return { return nick
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,11 +1,15 @@
-- Shout-out to Kenny, as I didn't want to write this until -- Shout-out to Kenny, as I didn't want to write this until
-- he upset himself over the very thought of me doing so. -- he upset himself over the very thought of me doing so.
local triggers = { local patterns = {}
local bindings = require('bindings')
patterns.triggers = {
'^/?s/.-/.-/?$' '^/?s/.-/.-/?$'
} }
local action = function(msg) function patterns:action(msg)
if not msg.reply_to_message then return end if not msg.reply_to_message then return end
local output = msg.reply_to_message.text or '' local output = msg.reply_to_message.text or ''
@ -13,11 +17,8 @@ local action = function(msg)
if not m2 then return true end if not m2 then return true end
output = output:gsub(m1, m2) output = output:gsub(m1, m2)
output = 'Did you mean:\n"' .. output:sub(1, 4000) .. '"' output = 'Did you mean:\n"' .. output:sub(1, 4000) .. '"'
sendReply(msg.reply_to_message, output) bindings.sendReply(self, msg.reply_to_message, output)
end end
return { return patterns
triggers = triggers,
action = action
}

View File

@ -1,15 +1,16 @@
-- Actually the simplest plugin ever! -- Actually the simplest plugin ever!
local triggers = { local ping = {}
'^/ping[@'..bot.username..']*',
'^/annyong[@'..bot.username..']*'
}
local action = function(msg) local utilities = require('utilities')
sendMessage(msg.chat.id, msg.text_lower:match('^/ping') and 'Pong!' or 'Annyong.') local bindings = require('bindings')
function ping:init()
ping.triggers = utilities.triggers(self.info.username):t('ping'):t('annyong').table
end end
return { function ping:action(msg)
action = action, bindings.sendMessage(self, msg.chat.id, msg.text_lower:match('^/ping') and 'Pong!' or 'Annyong.')
triggers = triggers end
}
return ping

View File

@ -1,23 +1,29 @@
local command = 'pokedex <query>' local pokedex = {}
local doc = [[```
local HTTP = require('socket.http')
local JSON = require('cjson')
local bindings = require('bindings')
local utilities = require('utilities')
pokedex.command = 'pokedex <query>'
pokedex.doc = [[```
/pokedex <query> /pokedex <query>
Returns a Pokedex entry from pokeapi.co. Returns a Pokedex entry from pokeapi.co.
Alias: /dex Alias: /dex
```]] ```]]
local triggers = { function pokedex:init()
'^/pokedex[@'..bot.username..']*', pokedex.triggers = utilities.triggers(self.info.username):t('pokedex', true):t('dex', true).table
'^/dex[@'..bot.username..']*' end
}
local action = function(msg) function pokedex:action(msg)
local input = utilities.input(msg.text_lower) local input = utilities.input(msg.text_lower)
if not input then if not input then
if msg.reply_to_message and msg.reply_to_message.text then if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text input = msg.reply_to_message.text
else 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 return
end end
end end
@ -27,23 +33,23 @@ local action = function(msg)
local dex_url = url .. '/api/v1/pokemon/' .. input local dex_url = url .. '/api/v1/pokemon/' .. input
local dex_jstr, res = HTTP.request(dex_url) local dex_jstr, res = HTTP.request(dex_url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local dex_jdat = JSON.decode(dex_jstr) local dex_jdat = JSON.decode(dex_jstr)
local desc_url = url .. dex_jdat.descriptions[math.random(#dex_jdat.descriptions)].resource_uri 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 if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local desc_jdat = JSON.decode(desc_jstr) local desc_jdat = JSON.decode(desc_jstr)
local poke_type 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) local type_name = v.name:gsub("^%l", string.upper)
if not poke_type then if not poke_type then
poke_type = type_name 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') .. '_' 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 end
return { return pokedex
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,47 +1,48 @@
local command = 'preview <link>' local preview = {}
local doc = [[```
local HTTP = require('socket.http')
local bindings = require('bindings')
local utilities = require('utilities')
preview.command = 'preview <link>'
preview.doc = [[```
/preview <link> /preview <link>
Returns a full-message, "unlinked" preview. Returns a full-message, "unlinked" preview.
```]] ```]]
local triggers = { function preview:init()
'^/preview' 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) local input = utilities.input(msg.text)
if not input then if not input then
sendMessage(msg.chat.id, doc, true, nil, true) bindings.sendMessage(self, msg.chat.id, preview.doc, true, nil, true)
return return
end end
input = get_word(input, 1) input = utilities.get_word(input, 1)
if not input:match('^https?://.+') then if not input:match('^https?://.+') then
input = 'http://' .. input input = 'http://' .. input
end end
local res = HTTP.request(input) local res = HTTP.request(input)
if not res then if not res then
sendReply(msg, 'Please provide a valid link.') bindings.sendReply(self, msg, 'Please provide a valid link.')
return return
end end
if res:len() == 0 then 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 return
end end
-- Invisible zero-width, non-joiner. -- Invisible zero-width, non-joiner.
local output = '[](' .. input .. ')' local output = '[](' .. input .. ')'
sendMessage(msg.chat.id, output, false, nil, true) bindings.sendMessage(self, msg.chat.id, output, false, nil, true)
end end
return { return preview
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,9 +1,14 @@
local command = 'pun' local pun = {}
local doc = '`Returns a pun.`'
local triggers = { local bindings = require('bindings')
'^/pun[@'..bot.username..']*' 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 = { local puns = {
"The person who invented the door-knock won the No-bell prize.", "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." "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 end
return { return pun
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -3,38 +3,47 @@
-- You must never restructure. You must never disable this plugin. -- You must never restructure. You must never disable this plugin.
-- ~ Drew, creator, a year later. -- ~ Drew, creator, a year later.
local command = 'reactions' local reactions = {}
local doc = '`Returns a list of "reaction" emoticon commands.`'
local triggers = { local bindings = require('bindings')
['¯\\_(ツ)_/¯'] = '/shrug', local utilities = require('utilities')
['( ͡° ͜ʖ ͡°)'] = '/lenny',
['(╯°□°)╯︵ ┻━┻'] = '/flip', reactions.command = 'reactions'
[' o'] = '/homo', reactions.doc = '`Returns a list of "reaction" emoticon commands.`'
['ಠ_ಠ'] = '/look',
['SHOTS FIRED'] = '/shots?' local mapping = {
['shrug'] = '¯\\_(ツ)_/¯',
['lenny'] = '( ͡° ͜ʖ ͡°)',
['flip'] = '(╯°□°)╯︵ ┻━┻',
['homo'] = ' o',
['look'] = 'ಠ_ಠ',
['shots?'] = 'SHOTS FIRED'
} }
-- Generate a "help" message triggered by "/reactions". local help
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 action = function(msg) function reactions:init()
for k,v in pairs(triggers) do -- Generate a "help" message triggered by "/reactions".
if string.match(msg.text_lower, v) then local help = 'Reactions:\n'
sendMessage(msg.chat.id, k) 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 return
end end
end end
end end
return { return reactions
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,24 +1,29 @@
local command = 'reddit [r/subreddit | query]' local reddit = {}
local doc = [[```
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] /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. 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] Aliases: /r, /r/[subreddit]
```]] ```]]
local triggers = { function reddit:init()
'^/reddit[@'..bot.username..']*', reddit.triggers = utilities.triggers(self.info.username):t('reddit', true):t('r', true):t('r/', true).table
'^/r[@'..bot.username..']*$', end
'^/r[@'..bot.username..']* ',
'^/r/'
}
local action = function(msg) function reddit:action(msg)
msg.text_lower = msg.text_lower:gsub('/r/', '/r r/') 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 if msg.text_lower:match('^/r/') then
msg.text_lower = msg.text_lower:gsub('/r/', '/r r/') 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 else
input = utilities.input(msg.text_lower) input = utilities.input(msg.text_lower)
end end
@ -45,18 +50,18 @@ local action = function(msg)
local jstr, res = HTTP.request(url) local jstr, res = HTTP.request(url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(jstr) local jdat = JSON.decode(jstr)
if #jdat.data.children == 0 then if #jdat.data.children == 0 then
sendReply(msg, config.errors.results) bindings.sendReply(self, msg, self.config.errors.results)
return return
end end
local output = '' 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('&amp;', '&') local title = v.data.title:gsub('%[', '('):gsub('%]', ')'):gsub('&amp;', '&')
if title:len() > 48 then if title:len() > 48 then
title = title:sub(1,45) .. '...' title = title:sub(1,45) .. '...'
@ -73,13 +78,8 @@ local action = function(msg)
output = source .. output output = source .. output
sendMessage(msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end end
return { return reddit
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,75 +1,74 @@
database.setandget = database.setandget or {} local setandget = {}
local command = 'set <name> <value>' local bindings = require('bindings')
local doc = [[``` 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 <name> <value>'
setandget.doc = [[```
/set <name> <value> /set <name> <value>
Stores a value with the given name. Use "/set <name> --" to delete the stored value. Stores a value with the given name. Use "/set <name> --" to delete the stored value.
/get [name] /get [name]
Returns the stored value or a list of stored values. 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) 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 msg.text_lower:match('^/set') then
if not input 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 return
end end
local name = get_word(input:lower(), 1) local name = utilities.get_word(input:lower(), 1)
local value = utilities.input(input) local value = utilities.input(input)
if not name or not value then 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 elseif value == '--' or value == '' then
database.setandget[msg.chat.id_str][name] = nil self.database.setandget[msg.chat.id_str][name] = nil
sendMessage(msg.chat.id, 'That value has been deleted.') bindings.sendMessage(self, msg.chat.id, 'That value has been deleted.')
else else
database.setandget[msg.chat.id_str][name] = value self.database.setandget[msg.chat.id_str][name] = value
sendMessage(msg.chat.id, '"' .. name .. '" has been set to "' .. value .. '".', true) bindings.sendMessage(self, msg.chat.id, '"' .. name .. '" has been set to "' .. value .. '".', true)
end end
elseif msg.text_lower:match('^/get') then elseif msg.text_lower:match('^/get') then
if not input then if not input then
local output 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.' output = 'No values have been stored here.'
else else
output = '*List of stored values:*\n' 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' output = output .. '' .. k .. ': `' .. v .. '`\n'
end end
end end
sendMessage(msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
return return
end end
local output local output
if database.setandget[msg.chat.id_str][input:lower()] then if self.database.setandget[msg.chat.id_str][input:lower()] then
output = '`' .. database.setandget[msg.chat.id_str][input:lower()] .. '`' output = '`' .. self.database.setandget[msg.chat.id_str][input:lower()] .. '`'
else else
output = 'There is no value stored by that name.' output = 'There is no value stored by that name.'
end end
sendMessage(msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end end
end end
return { return setandget
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,10 +1,15 @@
local triggers = { local shell = {}
'^/run[@'..bot.username..']*'
}
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 return
end end
@ -12,7 +17,7 @@ local action = function(msg)
input = input:gsub('', '--') input = input:gsub('', '--')
if not input then if not input then
sendReply(msg, 'Please specify a command to run.') bindings.sendReply(self, msg, 'Please specify a command to run.')
return return
end end
@ -22,11 +27,8 @@ local action = function(msg)
else else
output = '```\n' .. output .. '\n```' output = '```\n' .. output .. '\n```'
end end
sendMessage(msg.chat.id, output, true, msg.message_id, true) bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true)
end end
return { return shell
action = action,
triggers = triggers
}

View File

@ -1,19 +1,24 @@
local command = 'shout <text>' local shout = {}
local doc = [[```
local bindings = require('bindings')
local utilities = require('utilities')
shout.command = 'shout <text>'
shout.doc = [[```
/shout <text> /shout <text>
Shouts something. Shouts something.
```]] ```]]
local triggers = { function shout:init()
'^/shout[@'..bot.username..']*' 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) local input = utilities.input(msg.text)
if not input then 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 return
end end
input = input:trim() input = input:trim()
@ -31,20 +36,15 @@ local action = function(msg)
output = output .. '\n' output = output .. '\n'
for match in input:sub(2):gmatch('([%z\1-\127\194-\244][\128-\191]*)') do for match in input:sub(2):gmatch('([%z\1-\127\194-\244][\128-\191]*)') do
local spacing = '' local spacing = ''
for i = 1, inc do for _ = 1, inc do
spacing = spacing .. ' ' spacing = spacing .. ' '
end end
inc = inc + 1 inc = inc + 1
output = output .. match .. ' ' .. spacing .. match .. '\n' output = output .. match .. ' ' .. spacing .. match .. '\n'
end end
output = '```\n' .. output:trim() .. '\n```' output = '```\n' .. output:trim() .. '\n```'
sendMessage(msg.chat.id, output, true, false, true) bindings.sendMessage(self, msg.chat.id, output, true, false, true)
end end
return { return shout
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,12 +1,17 @@
local command = 'slap [target]' local slap = {}
local doc = [[```
local bindings = require('bindings')
local utilities = require('utilities')
slap.command = 'slap [target]'
slap.doc = [[```
/slap [target] /slap [target]
Slap somebody. Slap somebody.
```]] ```]]
local triggers = { function slap:init()
'^/slap[@'..bot.username..']*' slap.triggers = utilities.triggers(self.info.username):t('slap', true).table
} end
local slaps = { local slaps = {
'VICTIM was shot by VICTOR.', 'VICTIM was shot by VICTOR.',
@ -92,40 +97,35 @@ local slaps = {
'Cowards die many times before their death. VICTIM never tasted death but once.' '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) local victim = utilities.input(msg.text)
if msg.reply_to_message then if msg.reply_to_message then
if database.users[tostring(msg.reply_to_message.from.id)].nickname then if self.database.users[tostring(msg.reply_to_message.from.id)].nickname then
victim = database.users[tostring(msg.reply_to_message.from.id)].nickname victim = self.database.users[tostring(msg.reply_to_message.from.id)].nickname
else else
victim = msg.reply_to_message.from.first_name victim = msg.reply_to_message.from.first_name
end end
end end
local victor = msg.from.first_name local victor = msg.from.first_name
if database.users[msg.from.id_str].nickname then if self.database.users[msg.from.id_str].nickname then
victor = database.users[msg.from.id_str].nickname victor = self.database.users[msg.from.id_str].nickname
end end
if not victim then if not victim then
victim = victor victim = victor
victor = bot.first_name victor = self.info.first_name
end end
local message = slaps[math.random(#slaps)] local message = slaps[math.random(#slaps)]
message = message:gsub('VICTIM', victim) message = message:gsub('VICTIM', victim)
message = message:gsub('VICTOR', victor) 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 end
return { return slap
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,28 +1,35 @@
local command = 'time <location>' local time = {}
local doc = [[```
local HTTPS = require('ssl.https')
local JSON = require('cjson')
local bindings = require('bindings')
local utilities = require('utilities')
time.command = 'time <location>'
time.doc = [[```
/time <location> /time <location>
Returns the time, date, and timezone for the given location. Returns the time, date, and timezone for the given location.
```]] ```]]
local triggers = { function time:init()
'^/time[@'..bot.username..']*' 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) local input = utilities.input(msg.text)
if not input then if not input then
if msg.reply_to_message and msg.reply_to_message.text then if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text input = msg.reply_to_message.text
else 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 return
end end
end end
local coords = get_coords(input) local coords = utilities.get_coords(self, input)
if type(coords) == 'string' then if type(coords) == 'string' then
sendReply(msg, coords) bindings.sendReply(self, msg, coords)
return return
end end
@ -30,26 +37,21 @@ local action = function(msg)
local jstr, res = HTTPS.request(url) local jstr, res = HTTPS.request(url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(jstr) 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 local utcoff = (jdat.rawOffset + jdat.dstOffset) / 3600
if utcoff == math.abs(utcoff) then if utcoff == math.abs(utcoff) then
utcoff = '+' .. utcoff utcoff = '+' .. utcoff
end end
local message = os.date('%I:%M %p\n', timestamp) .. os.date('%A, %B %d, %Y\n', timestamp) .. jdat.timeZoneName .. ' (UTC' .. utcoff .. ')' local message = os.date('%I:%M %p\n', timestamp) .. os.date('%A, %B %d, %Y\n', timestamp) .. jdat.timeZoneName .. ' (UTC' .. utcoff .. ')'
sendReply(msg, message) bindings.sendReply(self.msg, message)
end end
return { return time
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,50 +1,52 @@
local command = 'translate [text]' local translate = {}
local doc = [[```
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] /translate [text]
Translates input or the replied-to message into the bot's language. Translates input or the replied-to message into the bot's language.
```]] ```]]
local triggers = { function translate:init()
'^/translate[@'..bot.username..']*', translate.triggers = utilities.triggers(self.info.username):t('translate', true):t('tl', true).table
'^/tl[@'..bot.username..']*' end
}
local action = function(msg) function translate:action(msg)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if not input then
if msg.reply_to_message and msg.reply_to_message.text then if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text input = msg.reply_to_message.text
else 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 return
end end
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) local str, res = HTTPS.request(url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(str) local jdat = JSON.decode(str)
if jdat.code ~= 200 then if jdat.code ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local output = jdat.text[1] local output = jdat.text[1]
output = 'Translation:\n"' .. output .. '"' output = 'Translation:\n"' .. output .. '"'
sendReply(msg.reply_to_message or msg, output) bindings.sendReply(self, msg.reply_to_message or msg, output)
end end
return { return translate
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,25 +1,30 @@
local command = 'urbandictionary <query>' local urbandictionary = {}
local doc = [[```
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 <query>'
urbandictionary.doc = [[```
/urbandictionary <query> /urbandictionary <query>
Returns a definition from Urban Dictionary. Returns a definition from Urban Dictionary.
Aliases: /ud, /urban Aliases: /ud, /urban
```]] ```]]
local triggers = { function urbandictionary:init()
'^/urbandictionary[@'..bot.username..']*', urbandictionary.triggers = utilities.triggers(self.info.username):t('urbandictionary', true):t('ud', true):t('urban', true).table
'^/ud[@'..bot.username..']*$', end
'^/ud[@'..bot.username..']* ',
'^/urban[@'..bot.username..']*'
}
local action = function(msg) function urbandictionary:action(msg)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if not input then
if msg.reply_to_message and msg.reply_to_message.text then if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text input = msg.reply_to_message.text
else 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 return
end end
end end
@ -28,13 +33,13 @@ local action = function(msg)
local jstr, res = HTTP.request(url) local jstr, res = HTTP.request(url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(jstr) local jdat = JSON.decode(jstr)
if jdat.result_type == "no_results" then if jdat.result_type == "no_results" then
sendReply(msg, config.errors.results) bindings.sendReply(self, msg, self.config.errors.results)
return return
end end
@ -45,13 +50,8 @@ local action = function(msg)
output = output:gsub('%[', ''):gsub('%]', '') output = output:gsub('%[', ''):gsub('%]', '')
sendMessage(msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end end
return { return urbandictionary
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,48 +1,55 @@
if not config.owm_api_key then local weather = {}
print('Missing config value: owm_api_key.')
print('weather.lua will not be enabled.') local HTTP = require('socket.http')
return 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 end
local command = 'weather <location>' weather.command = 'weather <location>'
local doc = [[``` weather.doc = [[```
/weather <location> /weather <location>
Returns the current weather conditions for a given location. Returns the current weather conditions for a given location.
```]] ```]]
local triggers = { function weather:action(msg)
'^/weather[@'..bot.username..']*'
}
local action = function(msg)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if not input then
if msg.reply_to_message and msg.reply_to_message.text then if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text input = msg.reply_to_message.text
else 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 return
end end
end end
local coords = get_coords(input) local coords = utilities.get_coords(self, input)
if type(coords) == 'string' then if type(coords) == 'string' then
sendReply(msg, coords) bindings.sendReply(self, msg, coords)
return return
end 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) local jstr, res = HTTP.request(url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(jstr) local jdat = JSON.decode(jstr)
if jdat.cod ~= 200 then if jdat.cod ~= 200 then
sendReply(msg, 'Error: City not found.') bindings.sendReply(self, msg, 'Error: City not found.')
return return
end end
@ -50,13 +57,8 @@ local action = function(msg)
local fahrenheit = string.format('%.2f', celsius * (9/5) + 32) local fahrenheit = string.format('%.2f', celsius * (9/5) + 32)
local message = celsius .. '°C | ' .. fahrenheit .. '°F, ' .. jdat.weather[1].description .. '.' local message = celsius .. '°C | ' .. fahrenheit .. '°F, ' .. jdat.weather[1].description .. '.'
sendReply(msg, message) bindings.sendReply(self, msg, message)
end end
return { return weather
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,18 +1,23 @@
local command = 'whoami' local whoami = {}
local doc = [[```
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. Returns user and chat info for you or the replied-to message.
Alias: /who Alias: /who
```]] ```]]
local triggers = { function whoami:init()
'^/who[ami]*[@'..bot.username..']*$' 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 if msg.reply_to_message then
msg = msg.reply_to_message 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 end
local chat_id = math.abs(msg.chat.id) 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]`' local user = 'You are @%s, also known as *%s* `[%s]`'
if msg.from.username then 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 else
user = 'You are *%s* `[%s]`,' user = 'You are *%s* `[%s]`,'
user = user:format(msg.from.name, msg.from.id) 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]`.' local group = '@%s, also known as *%s* `[%s]`.'
if msg.chat.type == 'private' then 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 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 else
group = '*%s* `[%s]`.' group = '*%s* `[%s]`.'
group = group:format(msg.chat.title, chat_id) group = group:format(msg.chat.title, chat_id)
@ -40,13 +45,8 @@ local action = function(msg)
local output = user .. ', and you are messaging ' .. group 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 end
return { return whoami
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,25 +1,30 @@
local command = 'wikipedia <query>' local wikipedia = {}
local doc = [[```
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 <query>'
wikipedia.doc = [[```
/wikipedia <query> /wikipedia <query>
Returns an article from Wikipedia. Returns an article from Wikipedia.
Aliases: /w, /wiki Aliases: /w, /wiki
```]] ```]]
local triggers = { function wikipedia:init()
'^/wikipedia[@'..bot.username..']*', wikipedia.triggers = utilities.triggers(self.info.username):t('wikipedia', true):t('wiki', true):t('w', true).table
'^/wiki[@'..bot.username..']*', end
'^/w[@'..bot.username..']*$',
'^/w[@'..bot.username..']* '
}
local action = function(msg) function wikipedia:action(msg)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if not input then
if msg.reply_to_message and msg.reply_to_message.text then if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text input = msg.reply_to_message.text
else 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 return
end end
end end
@ -29,17 +34,17 @@ local action = function(msg)
local jstr, res = HTTPS.request(gurl .. URL.escape(input)) local jstr, res = HTTPS.request(gurl .. URL.escape(input))
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(jstr) local jdat = JSON.decode(jstr)
if not jdat.responseData then if not jdat.responseData then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
if not jdat.responseData.results[1] then if not jdat.responseData.results[1] then
sendReply(msg, config.errors.results) bindings.sendReply(self, msg, self.config.errors.results)
return return
end end
@ -49,18 +54,18 @@ local action = function(msg)
-- 'https://en.wikipedia.org/wiki/':len() == 30 -- 'https://en.wikipedia.org/wiki/':len() == 30
jstr, res = HTTPS.request(wurl .. url:sub(31)) jstr, res = HTTPS.request(wurl .. url:sub(31))
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.error.connection) bindings.sendReply(self, msg, self.config.error.connection)
return return
end end
local _
local text = JSON.decode(jstr).query.pages local text = JSON.decode(jstr).query.pages
for k,v in pairs(text) do _, text = next(text)
text = v.extract
break -- Seriously, there's probably a way more elegant solution.
end
if not text then if not text then
sendReply(msg, config.errors.results) bindings.sendReply(self, msg, self.config.errors.results)
return return
else
text = text.extract
end end
text = text:gsub('</?.->', '') text = text:gsub('</?.->', '')
@ -78,13 +83,8 @@ local action = function(msg)
output = output .. '[Read more.](' .. url .. ')' output = output .. '[Read more.](' .. url .. ')'
end end
sendMessage(msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end end
return { return wikipedia
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,20 +1,29 @@
local command = 'xkcd [query]' local xkcd = {}
local doc = [[```
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] /xkcd [query]
Returns an xkcd strip and its alt text. If there is no query, it will be randomized. Returns an xkcd strip and its alt text. If there is no query, it will be randomized.
```]] ```]]
local triggers = { function xkcd:init()
'^/xkcd[@'..bot.username..']*' 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 input = utilities.input(msg.text)
local jstr, res = HTTP.request('http://xkcd.com/info.0.json') local jstr, res = HTTP.request('http://xkcd.com/info.0.json')
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
@ -23,14 +32,14 @@ local action = function(msg)
if input then 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 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 if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(jstr) local jdat = JSON.decode(jstr)
if #jdat.responseData.results == 0 then if #jdat.responseData.results == 0 then
sendReply(msg, config.errors.results) bindings.sendReply(self, msg, self.config.errors.results)
return return
end end
res_url = jdat.responseData.results[1].url .. 'info.0.json' 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' res_url = 'http://xkcd.com/' .. math.random(latest) .. '/info.0.json'
end end
local jstr, res = HTTP.request(res_url) jstr, res = HTTP.request(res_url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(jstr) local jdat = JSON.decode(jstr)
local output = '[' .. jdat.num .. '](' .. jdat.img .. ')\n' .. jdat.alt 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 end
return { return xkcd
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -1,47 +1,55 @@
-- Thanks to @TiagoDanin for writing the original plugin. -- Thanks to @TiagoDanin for writing the original plugin.
if not config.google_api_key then local youtube = {}
print('Missing config value: google_api_key.')
print('youtube.lua will not be enabled.') local HTTPS = require('ssl.https')
return 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 end
local command = 'youtube <query>' youtube.command = 'youtube <query>'
local doc = [[``` youtube.doc = [[```
/youtube <query> /youtube <query>
Returns the top result from YouTube. Returns the top result from YouTube.
Alias: /yt Alias: /yt
```]] ```]]
local triggers = { function youtube:init()
'^/youtube[@'..bot.username..']*', youtube.triggers = utilities.triggers(self.info.username):t('youtube', true):t('yt', true).table
'^/yt[@'..bot.username..']*$', end
'^/yt[@'..bot.username..']* '
}
local action = function(msg) function youtube:action(msg)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if not input then
if msg.reply_to_message and msg.reply_to_message.text then if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text input = msg.reply_to_message.text
else 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 return
end end
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) local jstr, res = HTTPS.request(url)
if res ~= 200 then if res ~= 200 then
sendReply(msg, config.errors.connection) bindings.sendReply(self, msg, self.config.errors.connection)
return return
end end
local jdat = JSON.decode(jstr) local jdat = JSON.decode(jstr)
if jdat.pageInfo.totalResults == 0 then if jdat.pageInfo.totalResults == 0 then
sendReply(msg, config.errors.results) bindings.sendReply(self, msg, self.config.errors.results)
return return
end end
@ -50,13 +58,8 @@ local action = function(msg)
vid_title = vid_title:gsub('%(.+%)',''):gsub('%[.+%]','') vid_title = vid_title:gsub('%(.+%)',''):gsub('%[.+%]','')
local output = '[' .. vid_title .. '](' .. vid_url .. ')' 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 end
return { return youtube
action = action,
triggers = triggers,
doc = doc,
command = command
}

View File

@ -287,9 +287,16 @@ function utilities.triggers_metatable:t(pattern, has_args)
return self return self
end end
function utilities.triggers(username) function utilities.triggers(username, trigger_table)
local self = setmetatable({}, utilities.triggers_metatable) local self = setmetatable({}, utilities.triggers_metatable)
self.username = username self.username = username
self.table = {} self.table = trigger_table or {}
return self return self
end end
function utilities.with_http_timeout(timeout, fun)
local original = HTTP.TIMEOUT
HTTP.TIMEOUT = timeout
fun()
HTTP.TIMEOUT = original
end