otouto v3 is out!

Everything reworked and rewritten.
Antisquig is now a plugin to work with moderation.lua.
The bot can now upload photos, stickers, and other files.
Return values in plugin functions to affect the bot's behavior.
All this and more!
This commit is contained in:
topkecleon
2015-11-24 21:22:04 -05:00
parent 3bd9d5302e
commit cacfea1fa5
64 changed files with 2262 additions and 2890 deletions

View File

@ -1,31 +1,30 @@
local PLUGIN = {}
PLUGIN.doc = [[
local doc = [[
/about
Information about the bot.
Get info about the bot.
]]
PLUGIN.triggers = {
'^/about',
'^/info'
local triggers = {
''
}
function PLUGIN.action(msg)
local action = function(msg)
local message = [[
I am ]] .. bot.first_name .. [[: a plugin-wielding, multi-purpose Telegram bot.
Send /help for a list of commands.
local message = config.about_text .. '\nBased on otouto v'..version..' by topkecleon.\notouto v3 is licensed under the GPLv2.\ntopkecleon.github.io/otouto'
Based on otouto v]] .. VERSION .. [[ by @topkecleon.
otouto v2 is licensed under the GPLv2.
topkecleon.github.io/otouto
if msg.new_chat_participant and msg.new_chat_participant.id == bot.id then
sendMessage(msg.chat.id, message)
return
elseif string.match(msg.text_lower, '^/about[@'..bot.username..']*') then
sendReply(msg, message)
return
end
Join the update/news channel!
telegram.me/otouto
]] -- Please do not remove this message. ^.^
send_message(msg.chat.id, message, true)
return true
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,45 +1,75 @@
local PLUGIN = {}
PLUGIN.triggers = {
'^/admin '
local triggers = {
'^/admin[@'..bot.username..']*'
}
function PLUGIN.action(msg)
local commands = {
if msg.date < os.time() - 1 then return end
local input = get_input(msg.text)
local message = config.locale.errors.argument
if not config.admins[msg.from.id] then
return send_msg(msg, 'Permission denied.')
end
if string.lower(first_word(input)) == 'run' then
local output = get_input(input)
if not output then
return send_msg(msg, config.locale.errors.argument)
['run'] = function(cmd)
local cmd = cmd:input()
if not cmd then
return 'Please enter a command to run.'
end
local output = io.popen(output)
message = output:read('*all')
output:close()
return io.popen(cmd):read('*all')
end,
elseif string.lower(first_word(input)) == 'reload' then
['lua'] = function(cmd)
local cmd = cmd:input()
if not cmd then
return 'Please enter a command to run.'
end
local a = loadstring(cmd)()
if a then
return a
else
return 'Done!'
end
end,
['reload'] = function(cmd)
bot_init()
message = 'Bot reloaded!'
elseif string.lower(first_word(input)) == 'halt' then
return 'Bot reloaded!'
end,
['halt'] = function(cmd)
is_started = false
message = 'Shutting down...'
return 'Stopping bot!'
end,
['error'] = function(cmd)
error('Intentional test error.')
end
send_msg(msg, message)
}
local action = function(msg)
if msg.from.id ~= config.admin then
return
end
local input = msg.text:input()
if not input then
local list = 'Specify a command: '
for k,v in pairs(commands) do
list = list .. k .. ', '
end
list = list:gsub(', $', '.')
sendReply(msg, list)
return
end
for k,v in pairs(commands) do
if string.match(get_word(input, 1), k) then
sendReply(msg, v(input))
return
end
end
sendReply(msg, 'Specify a command: run, reload, halt.')
end
return PLUGIN
return {
action = action,
triggers = triggers
}

46
plugins/antisquig.lua Executable file
View File

@ -0,0 +1,46 @@
-- Put this at the very top of your plugin list, even before blacklist.lua.
antisquig = {}
local triggers = {
'[\216-\219][\128-\191]'
}
local action = function(msg)
local moddat = load_data('moderation.json')
if not moddat[msg.chat.id_str] then
return true
end
if moddat[msg.chat.id_str][msg.from.id_str] or config.moderation.admins[msg.from.id_str] then
return true
end
if antisquig[msg.from.id] == true then
return
end
antisquig[msg.from.id] = true
sendReply(msg, config.errors.antisquig)
sendMessage(config.moderation.admin_group, '/kick ' .. msg.from.id .. ' from ' .. math.abs(msg.chat.id))
sendMessage(config.moderation.admin_group, 'ANTISQUIG: ' .. msg.from.first_name .. ' kicked from ' .. msg.chat.title .. '.')
end
-- When a user is kicked for squigglies, his ID is added to this table.
-- That user will not be kicked again as long as his ID is in the table.
-- The table is emptied every five seconds.
-- Thus the bot will not spam the group or admin group when a user posts more than one infringing messages.
local cron = function()
antisquig = {}
end
return {
action = action,
triggers = triggers,
cron = cron
}

View File

@ -1,33 +1,35 @@
local PLUGIN = {}
PLUGIN.doc = [[
local doc = [[
/bandersnatch
This is a Benedict Cumberbatch name generator.
Shun the frumious Bandersnatch.
]]
PLUGIN.triggers = {
'^/bandersnatch',
'^/bc$'
local triggers = {
'^/bandersnatch[@'..bot.username..']*',
'^/bc[@'..bot.username..']*'
}
PLUGIN.fullnames = { "Wimbledon Tennismatch", "Rinkydink Curdlesnoot", "Butawhiteboy Cantbekhan", "Benadryl Claritin", "Bombadil Rivendell", "Wanda's Crotchfruit", "Biblical Concubine", "Syphilis Cankersore", "Buckminster Fullerene", "Bourgeoisie Capitalist" }
local fullnames = { "Wimbledon Tennismatch", "Rinkydink Curdlesnoot", "Butawhiteboy Cantbekhan", "Benadryl Claritin", "Bombadil Rivendell", "Wanda's Crotchfruit", "Biblical Concubine", "Syphilis Cankersore", "Buckminster Fullerene", "Bourgeoisie Capitalist" }
PLUGIN.firstnames = { "Bumblebee", "Bandersnatch", "Broccoli", "Rinkydink", "Bombadil", "Boilerdang", "Bandicoot", "Fragglerock", "Muffintop", "Congleton", "Blubberdick", "Buffalo", "Benadryl", "Butterfree", "Burberry", "Whippersnatch", "Buttermilk", "Beezlebub", "Budapest", "Boilerdang", "Blubberwhale", "Bumberstump", "Bulbasaur", "Cogglesnatch", "Liverswort", "Bodybuild", "Johnnycash", "Bendydick", "Burgerking", "Bonaparte", "Bunsenburner", "Billiardball", "Bukkake", "Baseballmitt", "Blubberbutt", "Baseballbat", "Rumblesack", "Barister", "Danglerack", "Rinkydink", "Bombadil", "Honkytonk", "Billyray", "Bumbleshack", "Snorkeldink", "Anglerfish", "Beetlejuice", "Bedlington", "Bandicoot", "Boobytrap", "Blenderdick", "Bentobox", "Anallube", "Pallettown", "Wimbledon", "Buttercup", "Blasphemy", "Snorkeldink", "Brandenburg", "Barbituate", "Snozzlebert", "Tiddleywomp", "Bouillabaisse", "Wellington", "Benetton", "Bendandsnap", "Timothy", "Brewery", "Bentobox", "Brandybuck", "Benjamin", "Buckminster", "Bourgeoisie", "Bakery", "Oscarbait", "Buckyball", "Bourgeoisie", "Burlington", "Buckingham", "Barnoldswick" }
local firstnames = { "Bumblebee", "Bandersnatch", "Broccoli", "Rinkydink", "Bombadil", "Boilerdang", "Bandicoot", "Fragglerock", "Muffintop", "Congleton", "Blubberdick", "Buffalo", "Benadryl", "Butterfree", "Burberry", "Whippersnatch", "Buttermilk", "Beezlebub", "Budapest", "Boilerdang", "Blubberwhale", "Bumberstump", "Bulbasaur", "Cogglesnatch", "Liverswort", "Bodybuild", "Johnnycash", "Bendydick", "Burgerking", "Bonaparte", "Bunsenburner", "Billiardball", "Bukkake", "Baseballmitt", "Blubberbutt", "Baseballbat", "Rumblesack", "Barister", "Danglerack", "Rinkydink", "Bombadil", "Honkytonk", "Billyray", "Bumbleshack", "Snorkeldink", "Anglerfish", "Beetlejuice", "Bedlington", "Bandicoot", "Boobytrap", "Blenderdick", "Bentobox", "Anallube", "Pallettown", "Wimbledon", "Buttercup", "Blasphemy", "Snorkeldink", "Brandenburg", "Barbituate", "Snozzlebert", "Tiddleywomp", "Bouillabaisse", "Wellington", "Benetton", "Bendandsnap", "Timothy", "Brewery", "Bentobox", "Brandybuck", "Benjamin", "Buckminster", "Bourgeoisie", "Bakery", "Oscarbait", "Buckyball", "Bourgeoisie", "Burlington", "Buckingham", "Barnoldswick" }
PLUGIN.lastnames = { "Coddleswort", "Crumplesack", "Curdlesnoot", "Calldispatch", "Humperdinck", "Rivendell", "Cuttlefish", "Lingerie", "Vegemite", "Ampersand", "Cumberbund", "Candycrush", "Clombyclomp", "Cragglethatch", "Nottinghill", "Cabbagepatch", "Camouflage","Creamsicle", "Curdlemilk", "Upperclass", "Frumblesnatch", "Crumplehorn", "Talisman", "Candlestick", "Chesterfield", "Bumbersplat", "Scratchnsniff", "Snugglesnatch", "Charizard", "Carrotstick", "Cumbercooch", "Crackerjack", "Crucifix", "Cuckatoo", "Cockletit", "Collywog", "Capncrunch", "Covergirl", "Cumbersnatch", "Countryside","Coggleswort", "Splishnsplash", "Copperwire", "Animorph", "Curdledmilk", "Cheddarcheese", "Cottagecheese", "Crumplehorn", "Snickersbar", "Banglesnatch", "Stinkyrash", "Cameltoe", "Chickenbroth", "Concubine", "Candygram", "Moldyspore", "Chuckecheese", "Cankersore", "Crimpysnitch", "Wafflesmack", "Chowderpants", "Toodlesnoot", "Clavichord", "Cuckooclock", "Oxfordshire", "Cumbersome", "Chickenstrips", "Battleship", "Commonwealth", "Cunningsnatch", "Custardbath", "Kryptonite", "Curdlesnoot", "Cummerbund", "Coochyrash", "Crackerdong", "Crackerdong", "Curdledong", "Crackersprout", "Crumplebutt", "Colonist", "Coochierash", "Thundersnatch" }
local lastnames = { "Coddleswort", "Crumplesack", "Curdlesnoot", "Calldispatch", "Humperdinck", "Rivendell", "Cuttlefish", "Lingerie", "Vegemite", "Ampersand", "Cumberbund", "Candycrush", "Clombyclomp", "Cragglethatch", "Nottinghill", "Cabbagepatch", "Camouflage","Creamsicle", "Curdlemilk", "Upperclass", "Frumblesnatch", "Crumplehorn", "Talisman", "Candlestick", "Chesterfield", "Bumbersplat", "Scratchnsniff", "Snugglesnatch", "Charizard", "Carrotstick", "Cumbercooch", "Crackerjack", "Crucifix", "Cuckatoo", "Cockletit", "Collywog", "Capncrunch", "Covergirl", "Cumbersnatch", "Countryside","Coggleswort", "Splishnsplash", "Copperwire", "Animorph", "Curdledmilk", "Cheddarcheese", "Cottagecheese", "Crumplehorn", "Snickersbar", "Banglesnatch", "Stinkyrash", "Cameltoe", "Chickenbroth", "Concubine", "Candygram", "Moldyspore", "Chuckecheese", "Cankersore", "Crimpysnitch", "Wafflesmack", "Chowderpants", "Toodlesnoot", "Clavichord", "Cuckooclock", "Oxfordshire", "Cumbersome", "Chickenstrips", "Battleship", "Commonwealth", "Cunningsnatch", "Custardbath", "Kryptonite", "Curdlesnoot", "Cummerbund", "Coochyrash", "Crackerdong", "Crackerdong", "Curdledong", "Crackersprout", "Crumplebutt", "Colonist", "Coochierash", "Thundersnatch" }
function PLUGIN.action(msg)
local action = function(msg)
math.randomseed(os.time())
local message
local message = ''
if math.random(10) == 10 then
message = PLUGIN.fullnames[math.random(#PLUGIN.fullnames)]
message = fullnames[math.random(#fullnames)]
else
message = PLUGIN.firstnames[math.random(#PLUGIN.firstnames)] .. ' ' .. PLUGIN.lastnames[math.random(#PLUGIN.lastnames)]
message = firstnames[math.random(#firstnames)] .. ' ' .. lastnames[math.random(#lastnames)]
end
send_msg(msg, message)
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,32 +1,50 @@
local PLUGIN = {}
if not config.biblia_api_key then
print('Missing config value: biblia_api_key.')
print('bible.lua will not be enabled.')
return
end
PLUGIN.doc = [[
/bible <verse>
Returns a verse from the bible, King James Version. Use a standard or abbreviated reference (John 3:16, Jn3:16).
http://biblia.com
local doc = [[
/bible <reference>
Returns a verse from the American Standard Version of the Bible, or an apocryphal verse from the King James Version. Results from biblia.com.
]]
PLUGIN.triggers = {
'^/bible',
'^/b '
local triggers = {
'^/b[ible]*[@'..bot.username..']*$',
'^/b[ible]*[@'..bot.username..']* '
}
function PLUGIN.action(msg)
local action = function(msg)
local input = get_input(msg.text)
local input = msg.text:input()
if not input then
return send_msg(msg, PLUGIN.doc)
sendReply(msg, doc)
return
end
local url = 'http://api.biblia.com/v1/bible/content/KJV.txt?key=' .. config.biblia_api_key .. '&passage=' .. URL.escape(input)
local url = 'http://api.biblia.com/v1/bible/content/ASV.txt?key=' .. config.biblia_api_key .. '&passage=' .. URL.escape(input)
local message, res = HTTP.request(url)
if res ~= 200 then
message = config.locale.errors.connection
if message:len() == 0 then
url = 'http://api.biblia.com/v1/bible/content/KJVAPOC.txt?key=' .. config.biblia_api_key .. '&passage=' .. URL.escape(input)
message, res = HTTP.request(url)
end
send_msg(msg, message)
if res ~= 200 then
message = config.errors.results
end
if message:len() > 4000 then
message = 'The text is too long to post here. Try being more specific.'
end
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,44 +1,49 @@
-- Admins can blacklist a user from utilizing this bot. Use via reply or with an ID as an argument. Un-blacklist a user with the same command.
-- This plugin will allow the admin to blacklist users who will be unable to
-- use the bot. This plugin should be at the top of your plugin list in config.
local triggers = {
'^/blacklist',
'^/listofcolor'
''
}
local action = function(msg)
local action = function(msg)
if not config.admins[msg.from.id] then
return send_msg(msg, 'Permission denied.')
local blacklist = load_data('blacklist.json')
if blacklist[msg.from.id_str] then
return -- End if the sender is blacklisted.
end
local name
local input = get_input(msg.text)
if not string.match(msg.text_lower, '^/blacklist') then
return true
end
if msg.from.id ~= config.admin then
return -- End if the user isn't admin.
end
local input = msg.text:input()
if not input then
if msg.reply_to_message then
input = msg.reply_to_message.from.id
name = msg.reply_to_message.from.first_name
input = tostring(msg.reply_to_message.from.id)
else
return send_msg(msg, 'Must be used via reply or by specifying a user\'s ID.')
sendReply(msg, 'You must use this command via reply or by specifying a user\'s ID.')
return
end
end
local id = tostring(input)
if not name then name = id end
if blacklist[id] then
blacklist[id] = nil
send_message(msg.chat.id, name .. ' has been removed from the blacklist.')
if blacklist[input] then
blacklist[input] = nil
sendReply(msg, input .. ' has been removed from the blacklist.')
else
blacklist[id] = true
send_message(msg.chat.id, name .. ' has been blacklisted.')
blacklist[input] = true
sendReply(msg, input .. ' has been added to the blacklist.')
end
save_data('blacklist.json', blacklist)
end
end
return {
doc = doc,
triggers = triggers,
action = action
return {
action = action,
triggers = triggers
}

View File

@ -1,66 +0,0 @@
local PLUGIN = {}
PLUGIN.doc = [[
/btc <currency> [amount]
Gives bitcoin prices for the given currency, and optionally conversion of an amount to and from that currency.
BitcoinAverage Price Index https://bitcoinaverage.com/
]]
PLUGIN.triggers = {
'^/btc'
}
function PLUGIN.action(msg)
local url = nil
local arg1 = 'USD'
local arg2 = 1
local jstr, res = HTTPS.request('https://api.bitcoinaverage.com/ticker/global/')
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
end
local jdat = JSON.decode(jstr)
local input = get_input(msg.text)
if input then
arg1 = string.upper(string.sub(input, 1, 3))
arg2 = string.sub(input, 5)
if not tonumber(arg2) then
return send_msg(msg, config.locale.errors.argument)
end
end
for k,v in pairs(jdat) do
if k == arg1 then
url = v .. '/'
break
end
end
if url then
jstr, res = HTTPS.request(url)
else
return send_msg(msg, config.locale.errors.results)
end
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
end
jdat = JSON.decode(jstr)
if not jdat['24h_avg'] then
return send_msg(msg, config.locale.errors.results)
end
local m = arg2 .. ' BTC = ' .. jdat['24h_avg']*arg2 ..' '.. arg1 .. '\n'
m = m .. arg2 ..' '.. arg1 .. ' = ' .. string.format("%.8f", arg2/jdat['24h_avg']) .. ' BTC'
send_msg(msg, m)
end
return PLUGIN

View File

@ -1,30 +1,38 @@
local PLUGIN = {}
PLUGIN.doc = [[
local doc = [[
/calc <expression>
This command solves math expressions and does conversion between common units. See mathjs.org/docs/expressions/syntax for a list of accepted syntax.
Returns solutions to mathematical expressions and conversions between common units. Results provided by mathjs.org.
]]
PLUGIN.triggers = {
'^/calc'
local triggers = {
'^/calc[@'..bot.username..']*'
}
function PLUGIN.action(msg)
local action = function(msg)
local input = get_input(msg.text)
local input = msg.text:input()
if not input then
return send_msg(msg, PLUGIN.doc)
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
sendReply(msg, doc)
return
end
end
local url = 'http://api.mathjs.org/v1/?expr=' .. URL.escape(input)
local message, res = HTTP.request(url)
local url = 'https://api.mathjs.org/v1/?expr=' .. URL.escape(input)
if res ~= 200 then
return send_msg(msg, config.locale.errors.syntax)
local ans, res = HTTPS.request(url)
if not ans then
sendReply(msg, config.errors.connection)
return
end
send_msg(msg, message)
sendReply(msg, ans)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,10 +1,15 @@
if not config.thecatapi_key then
print('Missing config value: thecatapi_key.')
print('cats.lua will be enabled, but there are more features with a key.')
end
local doc = [[
/cat
Get a cat pic!
Returns a cat!
]]
local triggers = {
'^/cats?'
'^/cat[@'..bot.username..']*$'
}
local action = function(msg)
@ -14,20 +19,20 @@ local action = function(msg)
url = url .. '&api_key=' .. config.thecatapi_key
end
local jstr, res = HTTP.request(url)
local str, res = HTTP.request(url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.errors.connection)
return
end
jstr = jstr:match('<img src="(.*)">')
str = str:match('<img src="(.*)">')
send_message(msg.chat.id, jstr, false, msg.message_id)
sendMessage(msg.chat.id, str)
end
return {
doc = doc,
triggers = triggers,
action = action,
typing = true
triggers = triggers,
doc = doc
}

View File

@ -1,36 +1,36 @@
-- shout-out to @luksireiku for showing me this site
-- Put this absolutely at the end, even after greetings.lua.
local PLUGIN = {}
PLUGIN.typing = true
PLUGIN.triggers = {
'^@' .. bot.username .. ', ',
'^' .. bot.first_name .. ', '
local triggers = {
''
}
function PLUGIN.action(msg)
local action = function(msg)
local input = get_input(msg.text)
if not msg.reply_to_message then
return true
elseif msg.reply_to_message and msg.reply_to_message.from.id ~= bot.id then
return true
end
local url = 'http://www.simsimi.com/requestChat?lc=en&ft=1.0&req=' .. URL.escape(input)
sendChatAction(msg.chat.id, 'typing')
local url = 'http://www.simsimi.com/requestChat?lc=en&ft=1.0&req=' .. URL.escape(msg.text_lower)
local jstr, res = HTTP.request(url)
if res ~= 200 then
return send_message(msg.chat.id, "I don't feel like talking right now.")
sendMessage(msg.chat.id, config.errors.chatter_connection)
return
end
local jdat = JSON.decode(jstr)
if string.match(jdat.res.msg, '^I HAVE NO RESPONSE.') or not jdat then
jdat.res.msg = "I don't know what to say to that."
end
local message = jdat.res.msg
if message:match('^I HAVE NO RESPONSE.') then
message = config.errors.chatter_response
end
-- Let's clean up the response a little. Capitalization & punctuation.
filter = {
local filter = {
['%aimi?%aimi?'] = bot.first_name,
['^%s*(.-)%s*$'] = '%1',
['^%l'] = string.upper,
@ -45,8 +45,11 @@ function PLUGIN.action(msg)
message = message .. '.'
end
send_message(msg.chat.id, message)
sendMessage(msg.chat.id, message)
end
return PLUGIN
return {
action = action,
triggers = triggers
}

View File

@ -1,20 +1,15 @@
local PLUGIN = {}
-- Commits from https://github.com/ngerakines/commitment.
PLUGIN.doc = [[
local doc = [[
/commit
http://whatthecommit.com.
Returns a commit message from whatthecommit.com.
]]
PLUGIN.triggers = {
'^/commit'
local triggers = {
'^/commit[@'..bot.username..']*'
}
function PLUGIN.action(msg)
math.randomseed(os.time())
send_msg(msg, PLUGIN.commits[math.random(#PLUGIN.commits)])
end
PLUGIN.commits = {
local commits = {
"One does not simply merge into master",
"Merging the merge",
"Another bug bites the dust",
@ -417,4 +412,14 @@ PLUGIN.commits = {
"One little whitespace gets its very own commit! Oh, life is so erratic!"
}
return PLUGIN
local action = function(msg)
sendMessage(msg.chat.id, commits[math.random(#commits)])
end
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,54 +1,54 @@
local doc = [[
/cash <from> <to> [amount]
Convert an amount from one currency to another.
Example: /cash USD EUR 5
/cash [amount] <from> to <to>
Example: /cash 5 USD to EUR
Returns exchange rates for various currencies.
]]
local triggers = {
'^/cash'
'^/cash[@'..bot.username..']*'
}
local action = function(msg)
local input = get_input(msg.text)
if not input then
return send_msg(msg, doc)
local input = msg.text:upper()
if not input:match('%a%a%a TO %a%a%a') then
sendReply(msg, doc)
return
end
local url = 'http://www.google.com/finance/converter' -- thanks juan :^)
local from = input:match('(%a%a%a) TO')
local to = input:match('TO (%a%a%a)')
local amount = input:match('([%d]+) %a%a%a TO %a%a%a') or 1
local result = 1
local from = first_word(input):upper()
local to = first_word(input, 2):upper()
local amount = first_word(input, 3)
local result
if not tonumber(amount) then
amount = 1
result = 1
end
local url = 'https://www.google.com/finance/converter'
if from ~= to then
local url = url .. '?from=' .. from .. '&to=' .. to .. '&a=' .. amount
local str, res = HTTP.request(url)
local str, res = HTTPS.request(url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.errors.connection)
return
end
local str = str:match('<span class=bld>(.*) %u+</span>')
if not str then return send_msg(msg, config.locale.errors.results) end
result = string.format('%.2f', str)
str = str:match('<span class=bld>(.*) %u+</span>')
if not str then
sendReply(msg, config.errors.results)
return
end
result = str:format('%.2f')
end
local message = amount .. ' ' .. from .. ' = ' .. result .. ' ' .. to
send_msg(msg, message)
sendReply(msg, message)
end
return {
doc = doc,
action = action,
triggers = triggers,
action = action
doc = doc
}

View File

@ -1,94 +0,0 @@
-- This is an experimental plugin for indexing a list of compliant groups, their descriptions, how to join them, etc. It is not complete nor fully implemented. The current test bot is @dgmpbot.
local triggers = {
'^/index',
'^/listgroups'
}
local dgmp_index = function(msg)
local dgmp = load_data('dgmp.json')
local input = get_input(msg.text)
if not input then return end
input = JSON.decode(input)
if not input then return end
local id = tostring(input.chatid)
if not dgmp[id] then
dgmp[id] = {}
end
group = dgmp[id]
group.chatname = input.chatname
if input.usercount then
group.usercount = input.usercount
end
if input.description then
group.description = input.description
end
if input.joininstructions then
group.joininstructions = input.joininstructions
end
save_data('dgmp.json', dgmp)
end
local dgmp_list = function(msg)
local dgmp = load_data('dgmp.json')
local input = get_input(msg.text)
if not input then
input = ''
else
input = string.lower(input)
end
local output = ''
for k,v in pairs(dgmp) do
if string.find(string.lower(v.chatname), input) then
output = output .. v.chatname .. ' (' .. k .. ')\n'
if v.description then
output = output .. v.description .. '\n'
end
if v.usercount then
output = output .. 'Users: ' .. v.usercount .. '\n'
end
if v.joininstructions then
output = output .. 'How to join: ' .. v.joininstructions .. '\n'
end
output = output .. '\n'
end
end
if string.len(output) > 4000 then
output = 'List is too long! Please use a (better) search query.'
end
output = trim_string(output)
if string.len(output) == 0 then
output = 'No results found.'
end
send_msg(msg, output)
end
local action = function(msg)
if string.match(msg.text, '^/index') then
dgmp_index(msg)
elseif string.match(msg.text, '^/listgroups') then
dgmp_list(msg)
end
end
return {
triggers = triggers,
action = action
}

View File

@ -1,67 +1,54 @@
local PLUGIN = {}
PLUGIN.doc = [[
/roll [arg]
Roll a die. Use any positive number for range or use D&D notation.
Example: /roll 4D100 will roll a 100-sided die four times.
local doc = [[
/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.
]]
PLUGIN.triggers = {
'^/roll'
local triggers = {
'^/roll[@'..bot.username..']*'
}
function PLUGIN.action(msg)
local action = function(msg)
math.randomseed(os.time())
local input = get_input(msg.text)
local input = msg.text_lower:input()
if not input then
input = 6
sendReply(msg, doc)
return
end
local count, range
if input:match('^[%d]+d[%d]+$') then
count, range = input:match('([%d]+)d([%d]+)')
elseif input:match('^d?[%d]+$') then
count = 1
range = input:match('^d?([%d]+)$')
else
input = string.upper(input)
sendReply(msg, doc)
return
end
if tonumber(input) then
range = tonumber(input)
rolls = 1
elseif string.find(input, 'D') then
local dloc = string.find(input, 'D')
if dloc == 1 then
rolls = 1
else
rolls = string.sub(input, 1, dloc-1)
end
range = string.sub(input, dloc+1)
if not tonumber(rolls) or not tonumber(range) then
return send_msg(msg, config.locale.errors.argument)
end
else
return send_msg(msg, config.locale.errors.argument)
count = tonumber(count)
range = tonumber(range)
if range < 2 then
sendReply(msg, 'The minimum range is 2.')
return
end
if range > 1000 or count > 1000 then
sendReply(msg, 'The maximum range and count are 1000.')
return
end
if tonumber(rolls) == 1 then
results = 'Random (1-' .. range .. '):\t'
elseif tonumber(rolls) > 1 then
results = rolls .. 'D' .. range .. ':\n'
else
return send_msg(msg, config.locale.errors.syntax)
local message = ''
for i = 1, count do
message = message .. math.random(range) .. '\t'
end
if tonumber(range) < 2 then
return send_msg(msg, config.locale.errors.syntax)
end
if tonumber(rolls) > 100 or tonumber(range) > 100000 then
return send_msg(msg, 'Max 100D100000')
end
for i = 1, tonumber(rolls) do
results = results .. math.random(range) .. '\t'
end
send_msg(msg, results)
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,29 +0,0 @@
local PLUGIN = {}
PLUGIN.doc = [[
/dogify <lines/separatedby/slashes>
Produces a doge image from dogr.io. Newlines are indicated by a forward slash. Words do not need to be spaced, but spacing is supported. Will post a previewed link rather than an image.
]]
PLUGIN.triggers = {
'^/doge ',
'^/dogify '
}
function PLUGIN.action(msg)
local input = get_input(msg.text)
if not input then
return send_msg(msg, PLUGIN.doc)
end
local input = string.gsub(input, ' ', '')
local input = string.lower(input)
url = 'http://dogr.io/' .. input .. '.png'
send_message(msg.chat.id, url, false, msg.message_id)
end
return PLUGIN

View File

@ -1,23 +1,26 @@
local PLUGIN = {}
PLUGIN.doc = [[
local doc = [[
/echo <text>
Repeat a string.
Repeat a string of text!
]]
PLUGIN.triggers = {
'^/echo'
local triggers = {
'^/echo[@'..bot.username..']*'
}
function PLUGIN.action(msg)
local action = function(msg)
local input = get_input(msg.text)
if not input then
return send_msg(msg, PLUGIN.doc)
local input = msg.text:input()
if input then
sendReply(msg, latcyr(input))
else
sendReply(msg, doc)
end
send_message(msg.chat.id, latcyr(input))
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,17 +1,14 @@
local PLUGIN = {}
PLUGIN.doc = [[
local doc = [[
/8ball
Magic 8-ball. Returns a standard 8ball message, unless called with "y/n", where it will return a less verbose answer.
Returns an answer from a magic 8-ball!
]]
PLUGIN.triggers = {
'^/helix',
local triggers = {
'^/8ball',
'y/n%p?$'
}
PLUGIN.answers = {
local ball_answers = {
"It is certain.",
"It is decidedly so.",
"Without a doubt.",
@ -35,24 +32,33 @@ PLUGIN.answers = {
"There is a time and place for everything, but not now."
}
PLUGIN.yesno = {'Absolutely.', 'In your dreams.', 'Yes.', 'No.'}
local yesno_answers = {
'Absolutely.',
'In your dreams.',
'Yes.',
'No.'
}
function PLUGIN.action(msg)
math.randomseed(os.time())
local action = function(msg)
if msg.reply_to_message then
msg = msg.reply_to_message
end
if string.match(string.lower(msg.text), 'y/n') then
message = PLUGIN.yesno[math.random(#PLUGIN.yesno)]
local message
if msg.text:match('y/n%p?$') then
message = yesno_answers[math.random(#yesno_answers)]
else
message = PLUGIN.answers[math.random(#PLUGIN.answers)]
message = ball_answers[math.random(#ball_answers)]
end
send_msg(msg, message)
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,31 +1,37 @@
floodcontrol = {}
-- Liberbot-compliant floodcontrol.
-- Put this after moderation.lua or blacklist.lua.
floodcontrol = floodcontrol or {}
local triggers = {
'/floodcontrol'
''
}
local action = function(msg)
local input, output
if msg.from.id ~= 100547061 then -- Only acknowledge Liberbot.
if not config.admins[msg.from.id] then -- or an admin. :)
return
end
if floodcontrol[-msg.chat.id] then
return
end
input = get_input(msg.text) -- Remove the first word from the input.
input = JSON.decode(input) -- Parse the JSON into a table.
if not input.groupid then return end -- If no group is specified, end.
if not input.duration then -- If no duration is specified, set it to 5min.
local input = msg.text_lower:match('^/floodcontrol[@'..bot.username..']* (.+)')
if not input then return true end
if msg.from.id ~= 100547061 and msg.from.id ~= config.admin then
return -- Only run for Liberbot or the admin.
end
input = JSON.decode(input)
if not input.groupid then
return
end
if not input.duration then
input.duration = 600
end
floodcontrol[input.groupid] = os.time() + input.duration
local s = input.groupid .. ' silenced for ' .. input.duration .. ' seconds.'
send_message(-34496439, s) -- Set this to whatever, or comment it out. I use it to send this data to my private bot group.
print(input.groupid .. ' silenced for ' .. input.duration .. ' seconds.')
end
@ -40,7 +46,7 @@ local cron = function()
end
return {
triggers = triggers,
action = action,
triggers = triggers,
cron = cron
}

View File

@ -1,22 +1,30 @@
local PLUGIN = {}
-- Requires that the "fortune" program is installed on your computer.
PLUGIN.doc = [[
/fortune
Get a random fortune from the UNIX fortune program.
]]
PLUGIN.triggers = {
'^/fortune',
'^/f$'
}
function PLUGIN.action(msg)
local output = io.popen('fortune')
message = ''
for l in output:lines() do
message = message .. l .. '\n'
end
send_msg(msg, message)
local s = io.popen('fortune'):read('*all')
if s:match('fortune: command not found') then
print('fortune is not installed on this computer.')
print('fortune.lua will not be enabled.')
return
end
return PLUGIN
local doc = [[
/fortune
Returns a UNIX fortune.
]]
local triggers = {
'^/fortune[@'..bot.username..']*'
}
local action = function(msg)
local message = io.popen('fortune'):read('*all')
sendMessage(msg.chat.id, message)
end
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,78 +1,58 @@
local PLUGIN = {}
PLUGIN.doc = [[
/images <query>
This command performs a Google Images search for the given query. One random top result is returned. Safe search is enabled by default; use '/insfw' to get potentially NSFW results.
Want images sent directly to chat? Try @ImageBot.
local doc = [[
/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.
]]
PLUGIN.triggers = {
'^/images?',
'^/img',
'^/i ',
'^/insfw'
local triggers = {
'^/i[mage]*[nsfw]*[@'..bot.username..']*$',
'^/i[mage]*[nsfw]*[@'..bot.username..']* '
}
PLUGIN.exts = {
'.png$',
'.jpg$',
'.jpeg$',
'.jpe$',
'.gif$'
}
local action = function(msg)
function PLUGIN.action(msg)
local url = 'http://ajax.googleapis.com/ajax/services/search/images?v=1.0&rsz=8'
if not string.match(msg.text, '^/insfw ') then
url = url .. '&safe=active'
local input = msg.text:input()
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
sendReply(msg, doc)
return
end
end
local input = get_input(msg.text)
if not input then
if msg.reply_to_message then
msg = msg.reply_to_message
input = msg.text
else
return send_msg(msg, PLUGIN.doc)
end
local url = 'https://ajax.googleapis.com/ajax/services/search/images?v=1.0&rsz=8'
if not string.match(msg.text, '^/i[mage]*nsfw') then
url = url .. '&safe=active'
end
url = url .. '&q=' .. URL.escape(input)
local jstr, res = HTTP.request(url)
local jstr, res = HTTPS.request(url)
if res ~= 200 then
send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if #jdat.responseData.results < 1 then
send_msg(msg, config.locale.errors.results)
sendReply(msg, config.errors.results)
return
end
local is_real = false
local counter = 0
while is_real == false do
counter = counter + 1
if counter > 5 then
return send_msg(msg, config.locale.errors.results)
end
local i = math.random(#jdat.responseData.results)
result_url = jdat.responseData.results[i].url
for i,v in pairs(PLUGIN.exts) do
if string.match(string.lower(result_url), v) then
is_real = true
end
end
end
local i = math.random(#jdat.responseData.results)
local result = jdat.responseData.results[i].url
send_message(msg.chat.id, result_url, false, msg.message_id)
if string.match(msg.text, '^/i[mage]*nsfw') then
sendReply(msg, result)
else
sendMessage(msg.chat.id, result, false, msg.message_id)
end
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,45 +1,37 @@
local PLUGIN = {}
PLUGIN.doc = [[
/loc <location>
Sends location data for query, taken from Google Maps. Works for countries, cities, landmarks, etc.
local doc = [[
/location <query>
Returns a location from Google Maps.
]]
PLUGIN.triggers = {
'^/loc'
triggers = {
'^/loc[ation]*[@'..bot.username..']*$',
'^/loc[ation]*[@'..bot.username..']* '
}
function PLUGIN.action(msg)
local action = function(msg)
local input = get_input(msg.text)
local input = msg.text:input()
if not input then
if msg.reply_to_message then
msg = msg.reply_to_message
input = msg.text
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
return send_msg(msg, PLUGIN.doc)
sendReply(msg, doc)
return
end
end
local url = 'http://maps.googleapis.com/maps/api/geocode/json?address=' .. URL.escape(input)
local jstr, res = HTTP.request(url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
local coords = get_coords(input)
if type(coords) == 'string' then
sendReply(msg, coords)
return
end
local jdat = JSON.decode(jstr)
if jdat.status ~= 'OK' then
local message = config.locale.errors.results
return send_msg(msg, message)
end
local lat = jdat.results[1].geometry.location.lat
local lng = jdat.results[1].geometry.location.lng
send_location(msg.chat.id, lat, lng, msg.message_id)
sendLocation(msg.chat.id, coords.lat, coords.lon, msg.message_id)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,65 +1,62 @@
local PLUGIN = {}
PLUGIN.doc = [[
local doc = [[
/google <query>
This command performs a Google search for the given query. Four results are returned. Safe search is enabled by default; use '/gnsfw' to get potentially NSFW results. Four results are returned for a group chat, or eight in a private message.
Returns four (if group) or eight (if private message) results from Google. Safe search is enabled by default, use "/gnsfw" to disable it.
]]
PLUGIN.triggers = {
'^/g ',
'^/g$',
'^/google',
'^/gnsfw'
local triggers = {
'^/g[oogle]*[nsfw]*[@'..bot.username..']*$',
'^/g[oogle]*[nsfw]*[@'..bot.username..']* '
}
function PLUGIN.action(msg)
local action = function(msg)
local url = 'http://ajax.googleapis.com/ajax/services/search/web?v=1.0'
if not string.match(msg.text, '^/gnsfw ') then
url = url .. '&safe=active'
end
if not msg.chat.title then
url = url .. '&rsz=8'
end
local input = get_input(msg.text)
local input = msg.text:input()
if not input then
if msg.reply_to_message then
msg = msg.reply_to_message
input = msg.text
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
return send_msg(msg, PLUGIN.doc)
sendReply(msg, doc)
return
end
end
local url = 'https://ajax.googleapis.com/ajax/services/search/web?v=1.0'
if msg.from.id == msg.chat.id then
url = url .. '&rsz=8'
else
url = url .. '&rsz=4'
end
if not string.match(msg.text, '^/g[oogle]*nsfw') then
url = url .. '&safe=active'
end
url = url .. '&q=' .. URL.escape(input)
local jstr, res = HTTP.request(url)
local jstr, res = HTTPS.request(url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if #jdat.responseData.results < 1 then
return send_msg(msg, config.locale.errors.results)
sendReply(msg, config.errors.results)
return
end
local message = ''
for i = 1, #jdat.responseData.results do
local result_url = jdat.responseData.results[i].unescapedUrl
local result_title = jdat.responseData.results[i].titleNoFormatting
message = message .. ' - ' .. result_title ..'\n'.. result_url .. '\n'
for i,v in ipairs(jdat.responseData.results) do
message = message .. jdat.responseData.results[i].titleNoFormatting .. '\n ' .. jdat.responseData.results[i].unescapedUrl .. '\n'
end
local message = message:gsub('&amp;', '&') -- blah
send_msg(msg, message)
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,57 +0,0 @@
local PLUGIN = {}
PLUGIN.doc = [[
/giphy [query]
Returns a random or search-resulted GIF from giphy.com. Results are limited to PG-13 by default; use '/gifnsfw' to get potentially NSFW results.
Want GIFs sent directly to chat? Try @ImageBot.
]]
PLUGIN.triggers = {
'^/giphy',
'^/gifnsfw'
}
function PLUGIN.action(msg)
local search_url = 'http://api.giphy.com/v1/gifs/search?limit=10&api_key=' .. config.giphy_api_key
local random_url = 'http://tv.giphy.com/v1/gifs/random?api_key=' .. config.giphy_api_key
local result_url = ''
if string.match(msg.text, '^/giphynsfw') then
search_url = search_url .. '&rating=r&q='
random_url = random_url .. '&rating=r'
else
search_url = search_url .. '&rating=pg-13&q='
random_url = random_url .. '&rating=pg-13'
end
local input = get_input(msg.text)
if not input then
local jstr, res = HTTP.request(random_url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
end
local jdat = JSON.decode(jstr)
result_url = jdat.data.image_url
else
local jstr, res = HTTP.request(search_url .. input)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
end
local jdat = JSON.decode(jstr)
if #jdat.data == 0 then
return send_msg(msg, config.locale.errors.results)
end
result_url = jdat.data[math.random(#jdat.data)].images.original.url
end
send_message(msg.chat.id, result_url, false, msg.message_id)
end
return PLUGIN

29
plugins/greetings.lua Executable file
View File

@ -0,0 +1,29 @@
-- Put this on the bottom of your plugin list, after help.lua.
local triggers = {
bot.first_name .. '%p?$'
}
local action = function(msg)
local nicks = load_data('nicknames.json')
local nick = nicks[msg.from.id_str] or msg.from.first_name
for k,v in pairs(config.greetings) do
for key,val in pairs(v) do
if msg.text_lower:match(val..',? '..bot.first_name) then
sendMessage(msg.chat.id, latcyr(k:gsub('#NAME', nick)))
return
end
end
end
return true
end
return {
action = action,
triggers = triggers
}

View File

@ -1,37 +1,46 @@
local PLUGIN = {}
PLUGIN.typing = true -- usually takes a few seconds to load
PLUGIN.doc = [[
local doc = [[
/hackernews
Returns some top stories from Hacker News. Four in a group or eight in a private message.
Returns four (if group) or eight (if private message) top stories from Hacker News.
]]
PLUGIN.triggers = {
'^/hackernews',
'^/hn$'
local triggers = {
'^/hackernews[@'..bot.username..']*',
'^/hn[@'..bot.username..']*'
}
function PLUGIN.action(msg)
local action = function(msg)
local jstr, res = HTTPS.request('https://hacker-news.firebaseio.com/v0/topstories.json')
if res ~= 200 then
sendReply(msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
local res_count = 4
if msg.chat.id == msg.from.id then
res_count = 8
end
local message = ''
local jstr = HTTPS.request('https://hacker-news.firebaseio.com/v0/topstories.json')
local stories = JSON.decode(jstr)
local limit = 4
if msg.chat.id == msg.from.id then
limit = 8
for i = 1, res_count do
local res_url = 'https://hacker-news.firebaseio.com/v0/item/' .. jdat[i] .. '.json'
jstr, res = HTTPS.request(res_url)
if res ~= 200 then
sendReply(msg, config.errors.connection)
return
end
local res_jdat = JSON.decode(jstr)
message = message .. res_jdat.title .. '\n ' .. res_jdat.url .. '\n'
end
for i = 1, limit do
url = 'https://hacker-news.firebaseio.com/v0/item/'..stories[i]..'.json'
jstr = HTTPS.request(url)
jdat = JSON.decode(jstr)
message = message .. jdat.title .. '\n' .. jdat.url .. '\n'
end
send_msg(msg, message)
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,107 +0,0 @@
-- Get info for a hearthstone card.
local jstr, res = HTTP.request('http://hearthstonejson.com/json/AllSets.json')
if res ~= 200 then
return print('Error connecting to the Hearthstone database. hearthstone.lua will not be enabled.')
end
jdat = JSON.decode(jstr)
hs_dat = {}
for k,v in pairs(jdat) do
for key,val in pairs(v) do
table.insert(hs_dat, val)
end
end
local doc = [[
/hearthstone <card>
Get information about a Hearthstone card.
]]
local triggers = {
'^/hearthstone',
'^/hs'
}
local fmt_card = function(card)
local ctype = card.type
if card.race then
ctype = card.race
end
if card.rarity then
ctype = card.rarity .. ' ' .. ctype
end
if card.playerClass then
ctype = ctype .. ' (' .. card.playerClass .. ')'
elseif card.faction then
ctype = ctype .. ' (' .. card.faction .. ')'
end
local stats
if card.cost then
stats = card.cost .. 'c'
if card.attack then
stats = stats .. ' | ' .. card.attack .. 'a'
end
if card.health then
stats = stats .. ' | ' .. card.health .. 'h'
end
if card.durability then
stats = stats .. ' | ' .. card.durability .. 'd'
end
elseif card.health then
stats = card.health .. 'h'
end
local info = ''
if card.text then
info = card.text:gsub('</?.->',''):gsub('%$','')
if card.flavor then
info = info .. '\n' .. card.flavor
end
elseif card.flavor then
info = card.flavor
else
info = nil
end
local s = card.name .. '\n' .. ctype
if stats then
s = s .. '\n' .. stats
end
if info then
s = s .. '\n' .. info
end
return s
end
local action = function(msg)
local input = get_input(msg.text)
if not input then return send_msg(msg, doc) end
input = string.lower(input)
local output = ''
for k,v in pairs(hs_dat) do
if string.match(string.lower(v.name), input) then
output = output .. fmt_card(v) .. '\n\n'
end
end
output = trim_string(output)
if string.len(output) == 0 then
return send_msg(msg, config.locale.errors.results)
end
send_msg(msg, output)
end
return {
doc = doc,
triggers = triggers,
action = action
}

View File

@ -1,45 +1,37 @@
local PLUGIN = {}
-- This plugin should go at the end of your plugin list in
-- config.lua, but not after greetings.lua.
PLUGIN.doc = [[
/help [command]
Get list of basic information for all commands, or more detailed documentation on a specified command.
]]
local help_text = 'Available commands:\n'
PLUGIN.triggers = {
'^/help',
'^/h$',
'^/start$'
for i,v in ipairs(plugins) do
if v.doc then
local a = string.sub(v.doc, 1, string.find(v.doc, '\n')-1)
help_text = help_text .. a .. '\n'
end
end
local help_text = help_text .. 'Arguments: <required> [optional]'
local triggers = {
'^/h[elp]*[@'..bot.username..']*$',
'^/start[@'..bot.username..']*'
}
function PLUGIN.action(msg)
if string.find(msg.text, '@') and not string.match(msg.text, 'help@'..bot.username) then return end
local input = get_input(msg.text)
if input then
for i,v in ipairs(plugins) do
if v.doc then
if '/' .. input == trim_string(first_word(v.doc)) then
return send_msg(msg, v.doc)
end
end
end
end
local message = 'Available commands:\n' .. help_message .. [[
*Arguments: <required> [optional]
]]
local action = function(msg)
if msg.from.id ~= msg.chat.id then
if not send_message(msg.from.id, message, true, msg.message_id) then
return send_msg(msg, message) -- Unable to PM user who hasn't PM'd first.
if sendMessage(msg.from.id, help_text) then
sendReply(msg, 'I have sent you the requested information in a private message.')
else
sendReply(msg, help_text)
end
return send_msg(msg, 'I have sent you the requested information in a private message.')
else
return send_msg(msg, message)
sendReply(msg, help_text)
end
end
return PLUGIN
return {
action = action,
triggers = triggers
}

View File

@ -1,29 +0,0 @@
local PLUGIN = {}
PLUGIN.doc = [[
/hex <number>
This function converts a number to or from hexadecimal.
]]
PLUGIN.triggers = {
'^/hex '
}
function PLUGIN.action(msg)
local input = get_input(msg.text)
if string.sub(input, 1, 2) == '0x' then
send_msg(msg, tonumber(input))
elseif tonumber(input) then
send_msg(msg, string.format('%x', input))
else
send_msg(msg, config.locale.errors.argument)
end
end
return PLUGIN

View File

@ -1,36 +1,37 @@
local PLUGIN = {}
PLUGIN.doc = [[
/imdb <movie | TV series>
This function retrieves the IMDb info for a given film or television series, including the year, genre, imdb rating, runtime, and a summation of the plot.
local doc = [[
/imdb <query>
Returns an IMDb entry.
]]
PLUGIN.triggers = {
'^/imdb'
local triggers = {
'^/imdb[@'..bot.username..']*'
}
function PLUGIN.action(msg)
local action = function(msg)
local input = get_input(msg.text)
local input = msg.text:input()
if not input then
if msg.reply_to_message then
msg = msg.reply_to_message
input = msg.text
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
return send_msg(msg, PLUGIN.doc)
sendReply(msg, doc)
return
end
end
local url = 'http://www.omdbapi.com/?t=' .. URL.escape(input)
local jstr, res = HTTP.request(url)
local jdat = JSON.decode(jstr)
if res ~= 200 or not jdat then
return send_msg(msg, config.locale.errors.connection)
local jstr, res = HTTP.request(url)
if res ~= 200 then
sendReply(msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if jdat.Response ~= 'True' then
return send_msg(msg, jdat.Error)
sendReply(msg, config.errors.results)
return
end
local message = jdat.Title ..' ('.. jdat.Year ..')\n'
@ -38,8 +39,12 @@ function PLUGIN.action(msg)
message = message .. jdat.Plot .. '\n'
message = message .. 'http://imdb.com/title/' .. jdat.imdbID
send_msg(msg, message)
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,36 +0,0 @@
local PLUGIN = {}
PLUGIN.triggers = {
bot.first_name .. '%p?$',
'^tadaima%p?$',
'^i\'m home%p?$',
'^i\'m back%p?$'
}
function PLUGIN.action(msg)
local input = string.lower(msg.text)
local data = load_data('nicknames.json')
local id = tostring(msg.from.id)
local nick = msg.from.first_name
if data[id] then nick = data[id] end
for i = 2, #PLUGIN.triggers do
if string.match(input, PLUGIN.triggers[i]) then
return send_message(msg.chat.id, 'Welcome back, ' .. nick .. '!')
end
end
for k,v in pairs(config.locale.interactions) do
for key,val in pairs(v) do
if input:match(val..',? '..bot.first_name) then
return send_message(msg.chat.id, latcyr(k:gsub('#NAME', nick)))
end
end
end
end
return PLUGIN

View File

@ -1,69 +0,0 @@
-- Kickass Torrents
-- Based on @Imandaneshi's torrent.lua
-- https://github.com/Imandaneshi/Jack/blob/master/plugins/torrent.lua
local doc = [[
/torrent <query>
Search Kickass Torrents. Results may be NSFW.
]]
local triggers = {
'^/torrent',
'^/kickass'
}
local action = function(msg)
local url = 'http://kat.cr/json.php?q='
local input = get_input(msg.text)
if not input then
return send_msg(msg, doc)
end
local jstr, res = HTTPS.request(url..URL.escape(input))
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
end
local jdat = JSON.decode(jstr)
if #jdat.total_results == 0 then
return send_msg(msg, config.locale.errors.results)
end
local limit = 4 -- If the request is made in a PM, send 8 results instead of 4.
if msg.chat.id == msg.from.id then
limit = 8
end
if #jdat.total_results < limit then -- If there are not that many results, do as many as possible.
limit = #jdat.total_results
end
for i,v in ipairs(jdat.list) do -- Remove any entries that have zero seeds.
if v.seeds == 0 then
table.remove(jdat.list, i)
end
end
if #jdat.list == 0 then
return send_msg(msg, config.locale.errors.results)
end
local message = ''
for i = 1, limit do
local torrenturl = jdat.list[i].torrentLink:sub(1, jdat.list[i].torrentLink:find('?')-1) -- Clean up the torrent link.
message = message .. jdat.list[i].title .. '\n' .. jdat.list[i].category .. ' | ' .. string.format('%.3f', jdat.list[i].size/1000000) .. 'MB | ' .. jdat.list[i].seeds .. 'S/' .. jdat.list[i].peers .. 'L\n' .. torrenturl .. '\n\n'
end
message = message:gsub('&amp;', '&')
send_msg(msg, message)
end
return {
doc = doc,
triggers = triggers,
action = action,
typing = true
}

View File

@ -1,89 +1,101 @@
local PLUGIN = {}
if not config.lastfm_api_key then
print('Missing config value: lastfm_api_key.')
print('lastfm.lua will not be enabled.')
return
end
PLUGIN.doc = [[
/lastfm [username]
Get current- or last-played track data from last.fm. If a username is specified, it will return info for that username rather than your own.
"/fmset username" will configure your last.fm username.
local doc = [[
/lastfm
/np [username]
Returns what you are or were last listening to. If you specify a username, info will be returned for that username.
/fmset <username>
Sets your last.fm username. Otherwise, /np will use your Telegram username. Use "/fmset -" to delete it.
]]
PLUGIN.triggers = {
'^/lastfm',
'^/np$',
'^/fm$',
'^/fmset'
local triggers = {
'^/lastfm[@'..bot.username..']*',
'^/np[@'..bot.username..']*',
'^/fmset[@'..bot.username..']*'
}
function PLUGIN.action(msg)
local action = function(msg)
if msg.text:match('^/fmset') then
local input = get_input(msg.text)
if not input then
return send_msg(msg, PLUGIN.doc)
end
local data = load_data('lastfm.json')
local id = tostring(msg.from.id)
data[id] = input
save_data('lastfm.json', data)
send_msg(msg, 'Your last.fm username has been set to ' .. input .. '.')
lastfm = load_data('lastfm.json')
local input = msg.text:input()
if string.match(msg.text, '^/lastfm') then
sendReply(msg, doc:sub(10))
return
end
local base_url = 'http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&format=json&limit=1&api_key=' .. config.lastfm_api_key .. '&user='
local input = get_input(msg.text)
if not input then
local data = load_data('lastfm.json')
if data[tostring(msg.from.id)] then
input = data[tostring(msg.from.id)]
elseif msg.from.username then
input = msg.from.username
elseif string.match(msg.text, '^/fmset') then
if not input then
sendReply(msg, doc)
elseif input == '-' then
lastfm[msg.from.id_str] = nil
sendReply(msg, 'Your last.fm username has been forgotten.')
else
return send_msg(msg, 'Please provide a valid last.fm username.\nYou can set yours with /fmset.')
lastfm[msg.from.id_str] = input
sendReply(msg, 'Your last.fm username has been set to "' .. input .. '".')
end
save_data('lastfm.json', lastfm)
return
end
local jstr, res = HTTP.request(base_url..input)
local url = 'http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&format=json&limit=1&api_key=' .. config.lastfm_api_key .. '&user='
local username
if input then
username = input
elseif lastfm[msg.from.id_str] then
username = lastfm[msg.from.id_str]
elseif msg.from.username then
username = msg.from.username
else
sendReply(msg, 'Please specify your last.fm username or set it with /fmset.')
return
end
url = url .. URL.escape(username)
jstr, res = HTTPS.request(url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if jdat.error then
return send_msg(msg, 'Please provide a valid last.fm username.\nYou can set yours with /fmset.')
end
if not jdat.recenttracks.track then
return send_msg(msg, 'No history for that user.')
sendReply(msg, jdat.error)
return
end
local jdat = jdat.recenttracks.track[1] or jdat.recenttracks.track
local message = '🎵 ' .. msg.from.first_name .. ' last listened to:\n'
if jdat['@attr'] and jdat['@attr'].nowplaying then
message = '🎵 ' .. msg.from.first_name .. ' is listening to:\n'
if not jdat then
sendReply(msg, 'No history for this user.')
return
end
local name = jdat.name or 'Unknown'
local artist
local message = input or msg.from.first_name
message = '🎵 ' .. message
if jdat['@attr'] and jdat['@attr'].nowplaying then
message = message .. ' is currently listening to:\n'
else
message = message .. ' last listened to:\n'
end
local title = jdat.name or 'Unknown'
local artist = 'Unknown'
if jdat.artist then
artist = jdat.artist['#text']
else
artist = 'Unknown'
end
local message = message .. name .. ' - ' .. artist
send_message(msg.chat.id, message)
message = message .. title .. ' - ' .. artist
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,18 +0,0 @@
local PLUGIN = {}
PLUGIN.triggers = {
'^/lmgtfy'
}
function PLUGIN.action(msg)
if not msg.reply_to_message then return end
msg = msg.reply_to_message
local message = 'http://lmgtfy.com/?q=' .. URL.escape(msg.text)
send_msg(msg, message)
end
return PLUGIN

View File

@ -1,373 +1,296 @@
--[[
-- Moderation for Liberbot groups.
-- The bot must be made an admin.
-- Put this near the top, after blacklist.
-- If you want to enable antisquig, put that at the top, before blacklist.
This plugin will ONLY WORK in Liberbot-administered groups.
local triggers = {
'^/modhelp[@'..bot.username..']*$',
'^/modlist[@'..bot.username..']*$',
'^/modcast[@'..bot.username..']*',
'^/add[@'..bot.username..']*$',
'^/remove[@'..bot.username..']*$',
'^/promote[@'..bot.username..']*$',
'^/demote[@'..bot.username..']*',
'^/modkick[@'..bot.username..']*',
'^/modban[@'..bot.username..']*',
}
This works using the settings in the "moderation" section of config.lua.
"realm" should be set to the group ID of the admin group. A negative number.
"data" will be the file name of where the moderation 'database' will be stored. The file will be created if it does not exist.
"admins" is a table of administrators for the Liberbot admin group. They will have the power to add groups and moderators to the database. The value can be a nickname for the admin, but it only needs to be true for it to work.
local commands = {
Your bot should have privacy mode disabled.
['^/modhelp[@'..bot.username..']*$'] = function(msg)
]]--
local moddat = load_data('moderation.json')
local help = {}
help.trigger = '^/modhelp'
help.action = function(msg)
local data = load_data('moderation.json')
local do_send = false
if data[tostring(msg.chat.id)] and data[tostring(msg.chat.id)][tostring(msg.from.id)] then do_send = true end
if config.moderation.admins[tostring(msg.from.id)] then do_send = true end
if do_send == false then return end
local message = [[
Moderator commands:
/modban - Ban a user via reply or username.
/modkick - Kick a user via reply or username.
/modlist - Get a list of moderators for this group.
Administrator commands:
/add - Add this group to the database.
/remove - Remove this group from the database.
/promote - Promote a user via reply.
/demote - Demote a user via reply.
/modcast - Send a broastcast to every group.
/hammer - Ban a user from all groups via reply or username.
]]
send_message(msg.chat.id, message)
end
local ban = {}
ban.trigger = '^/modban'
ban.action = function(msg)
if msg.flood then
msg.chat.id = msg.flood
end
local data = load_data('moderation.json')
if not data[tostring(msg.chat.id)] then return end
if not data[tostring(msg.chat.id)][tostring(msg.from.id)] then
if not config.moderation.admins[tostring(msg.from.id)] then
return
if not moddat[msg.chat.id_str] then
return config.errors.moderation
end
end
local target = get_target(msg)
if not target then
return send_message(msg.chat.id, 'No one to remove.\nBots must be removed by username.')
end
local message = [[
/modlist - List the moderators and administrators of this group.
Moderator commands:
/modkick - Kick a user from this group.
/modban - Ban a user from this group.
Administrator commands:
/add - Add this group to the moderation system.
/remove - Remove this group from the moderation system.
/promote - Promote a user to a moderator.
/demote - Demote a moderator to a user.
/modcast - Send a broadcast to every moderated group.
]]
if msg.reply_to_message and data[tostring(msg.chat.id)][tostring(msg.reply_to_message.from.id)] then
return send_message(msg.chat.id, 'Cannot remove a moderator.')
end
return message
local chat_id = math.abs(msg.chat.id)
end,
send_message(config.moderation.realm, '/ban ' .. target .. ' from ' .. chat_id)
['^/modlist[@'..bot.username..']*$'] = function(msg)
if msg.reply_to_message then
target = msg.reply_to_message.from.first_name
end
local moddat = load_data('moderation.json')
send_message(config.moderation.realm, target .. ' banned from ' .. msg.chat.title .. ' by ' .. msg.from.first_name .. '.')
end
local kick = {}
kick.trigger = '^/modkick'
kick.action = function(msg)
if msg.flood then
msg.chat.id = msg.flood
end
local data = load_data('moderation.json')
if not data[tostring(msg.chat.id)] then return end
if not data[tostring(msg.chat.id)][tostring(msg.from.id)] then
if not config.moderation.admins[tostring(msg.from.id)] then
return
if not moddat[msg.chat.id_str] then
return config.errors.moderation
end
end
local target = get_target(msg)
if not target then
return send_message(msg.chat.id, 'No one to remove.\nBots must be removed by username.')
end
local message = ''
if msg.reply_to_message and data[tostring(msg.chat.id)][tostring(msg.reply_to_message.from.id)] then
return send_message(msg.chat.id, 'Cannot remove a moderator.')
end
local chat_id = math.abs(msg.chat.id)
send_message(config.moderation.realm, '/kick ' .. target .. ' from ' .. chat_id)
if msg.reply_to_message then
target = msg.reply_to_message.from.first_name
end
send_message(config.moderation.realm, target .. ' kicked from ' .. msg.chat.title .. ' by ' .. msg.from.first_name .. '.')
end
local add = {}
add.trigger = '^/[mod]*add$'
add.action = function(msg)
local data = load_data('moderation.json')
if not config.moderation.admins[tostring(msg.from.id)] then return end
if data[tostring(msg.chat.id)] then
return send_message(msg.chat.id, 'Group is already added.')
end
data[tostring(msg.chat.id)] = {}
save_data('moderation.json', data)
send_message(msg.chat.id, 'Group has been added.')
end
local rem = {}
rem.trigger = '^/[mod]*rem[ove]*$'
rem.action = function(msg)
local data = load_data('moderation.json')
if not config.moderation.admins[tostring(msg.from.id)] then return end
if not data[tostring(msg.chat.id)] then
return send_message(msg.chat.id, 'Group is not added.')
end
data[tostring(msg.chat.id)] = nil
save_data('moderation.json', data)
send_message(msg.chat.id, 'Group has been removed.')
end
local promote = {}
promote.trigger = '^/[mod]*prom[ote]*$'
promote.action = function(msg)
local data = load_data('moderation.json')
local chatid = tostring(msg.chat.id)
if not config.moderation.admins[tostring(msg.from.id)] then return end
if not data[chatid] then
return send_message(msg.chat.id, 'Group is not added.')
end
if not msg.reply_to_message then
return send_message(msg.chat.id, 'Promotions must be done via reply.')
end
local targid = tostring(msg.reply_to_message.from.id)
if data[chatid][targid] then
return send_message(msg.chat.id, msg.reply_to_message.from.first_name..' is already a moderator.')
end
if config.moderation.admins[targid] then
return send_message(msg.chat.id, 'Administrators do not need to be promoted.')
end
if not msg.reply_to_message.from.username then
msg.reply_to_message.from.username = msg.reply_to_message.from.first_name
end
data[chatid][targid] = msg.reply_to_message.from.first_name
save_data('moderation.json', data)
send_message(msg.chat.id, msg.reply_to_message.from.first_name..' has been promoted.')
end
local demote = {}
demote.trigger = '^/[mod]*dem[ote]*'
demote.action = function(msg)
local data = load_data('moderation.json')
if not config.moderation.admins[tostring(msg.from.id)] then return end
if not data[tostring(msg.chat.id)] then
return send_message(msg.chat.id, 'Group is not added.')
end
local input = get_input(msg.text)
if not input then
if msg.reply_to_message then
input = msg.reply_to_message.from.id
else
return send_msg('Demotions must be done by reply or by specifying a moderator\'s ID.')
for k,v in pairs(moddat[msg.chat.id_str]) do
message = message .. ' - ' .. v .. ' (' .. k .. ')\n'
end
if message ~= '' then
message = 'Moderators for ' .. msg.chat.title .. ':\n' .. message .. '\n'
end
message = message .. 'Administrators for ' .. config.moderation.realm_name .. ':\n'
for k,v in pairs(config.moderation.admins) do
message = message .. ' - ' .. v .. ' (' .. k .. ')\n'
end
return message
end,
['^/modcast[@'..bot.username..']*'] = function(msg)
local message = msg.text:input()
if not message then
return 'You must include a message.'
end
if msg.chat.id ~= config.moderation.admin_group then
return 'This command must be run in the administration group.'
end
if not config.moderation.admins[msg.from.id_str] then
return config.errors.not_admin
end
local moddat = load_data('moderation.json')
for k,v in pairs(moddat) do
sendMessage(k, message)
end
return 'Your broadcast has been sent.'
end,
['^/add[@'..bot.username..']*$'] = function(msg)
if not config.moderation.admins[msg.from.id_str] then
return config.errors.not_admin
end
local moddat = load_data('moderation.json')
if moddat[msg.chat.id_str] then
return 'I am already moderating this group.'
end
moddat[msg.chat.id_str] = {}
save_data('moderation.json', moddat)
return 'I am now moderating this group.'
end,
['^/remove[@'..bot.username..']*$'] = function(msg)
if not config.moderation.admins[msg.from.id_str] then
return config.errors.not_admin
end
local moddat = load_data('moderation.json')
if not moddat[msg.chat.id_str] then
return config.errors.moderation
end
moddat[msg.chat.id_str] = nil
save_data('moderation.json', moddat)
return 'I am no longer moderating this group.'
end,
['^/promote[@'..bot.username..']*$'] = function(msg)
local moddat = load_data('moderation.json')
if not moddat[msg.chat.id_str] then
return config.errors.moderation
end
if not config.moderation.admins[msg.from.id_str] then
return config.errors.not_admin
end
if not msg.reply_to_message then
return 'Promotions must be done via reply.'
end
local modid = tostring(msg.reply_to_message.from.id)
local modname = msg.reply_to_message.from.first_name
if config.moderation.admins[modid] then
return modname .. ' is already an administrator.'
end
if moddat[msg.chat.id_str][modid] then
return modname .. ' is already a moderator.'
end
moddat[msg.chat.id_str][modid] = modname
save_data('moderation.json', moddat)
return modname .. ' is now a moderator.'
end,
['^/demote[@'..bot.username..']*'] = function(msg)
local moddat = load_data('moderation.json')
if not moddat[msg.chat.id_str] then
return config.errors.moderation
end
if not config.moderation.admins[msg.from.id_str] then
return config.errors.not_admin
end
local modid = msg.text:input()
if not modid then
if msg.reply_to_message then
modid = tostring(msg.reply_to_message.from.id)
else
return 'Demotions must be done via reply or specification of a moderator\'s ID.'
end
end
if config.moderation.admins[modid] then
return config.moderation.admins[modid] .. ' is an administrator.'
end
if not moddat[msg.chat.id_str][modid] then
return 'User is not a moderator.'
end
local modname = moddat[msg.chat.id_str][modid]
moddat[msg.chat.id_str][modid] = nil
save_data('moderation.json', moddat)
return modname .. ' is no longer a moderator.'
end,
['/modkick[@'..bot.username..']*'] = function(msg)
local moddat = load_data('moderation.json')
if not moddat[msg.chat.id_str] then
return config.errors.moderation
end
if not moddat[msg.chat.id_str][msg.from.id_str] then
if not config.moderation.admins[msg.from.id_str] then
return config.errors.not_mod
end
end
local userid = msg.text:input()
local usernm = userid
if not userid then
if msg.reply_to_message then
userid = tostring(msg.reply_to_message.from.id)
usernm = msg.reply_to_message.from.first_name
else
return 'Kicks must be done via reply or specification of a user/bot\'s ID or username.'
end
end
if moddat[msg.chat.id_str][userid] or config.moderation.admins[userid] then
return 'You cannot kick a moderator.'
end
sendMessage(config.moderation.admin_group, '/kick ' .. userid .. ' from ' .. math.abs(msg.chat.id))
sendMessage(config.moderation.admin_group, usernm .. ' kicked from ' .. msg.chat.title .. ' by ' .. msg.from.first_name .. '.')
end,
['^/modban[@'..bot.username..']*'] = function(msg)
local moddat = load_data('moderation.json')
if not moddat[msg.chat.id_str] then
return config.errors.moderation
end
if not moddat[msg.chat.id_str][msg.from.id_str] then
if not config.moderation.admins[msg.from.id_str] then
return config.errors.not_mod
end
end
local userid = msg.text:input()
local usernm = userid
if not userid then
if msg.reply_to_message then
userid = tostring(msg.reply_to_message.from.id)
usernm = msg.reply_to_message.from.first_name
else
return 'Bans must be done via reply or specification of a user/bot\'s ID or username.'
end
end
if moddat[msg.chat.id_str][userid] or config.moderation.admins[userid] then
return 'You cannot ban a moderator.'
end
sendMessage(config.moderation.admin_group, '/ban ' .. userid .. ' from ' .. math.abs(msg.chat.id))
sendMessage(config.moderation.admin_group, usernm .. ' banned from ' .. msg.chat.title .. ' by ' .. msg.from.first_name .. '.')
end
if not data[tostring(msg.chat.id)][tostring(input)] then
return send_message(msg.chat.id, input..' is not a moderator.')
end
data[tostring(msg.chat.id)][tostring(input)] = nil
save_data('moderation.json', data)
send_message(msg.chat.id, input..' has been demoted.')
end
local broadcast = {}
broadcast.trigger = '^/modcast'
broadcast.action = function(msg)
local data = load_data('moderation.json')
if not config.moderation.admins[tostring(msg.from.id)] then return end
if msg.chat.id ~= config.moderation.realm then
return send_message(msg.chat.id, 'This command must be run in the admin group.')
end
local message = get_input(msg.text)
if not message then
return send_message(msg.chat.id, 'You must specify a message to broadcast.')
end
for k,v in pairs(data) do
send_message(k, message)
end
end
local modlist = {}
modlist.trigger = '^/modlist'
modlist.action = function(msg)
local data = load_data('moderation.json')
if not data[tostring(msg.chat.id)] then
return send_message(msg.chat.id, 'Group is not added.')
end
local message = ''
for k,v in pairs(data[tostring(msg.chat.id)]) do
message = message ..' - '..v.. ' (' .. k .. ')\n'
end
if message ~= '' then
message = 'Moderators for ' .. msg.chat.title .. ':\n' .. message .. '\n'
end
message = message .. 'Administrators for ' .. config.moderation.realmname .. ':\n'
for k,v in pairs(config.moderation.admins) do
message = message ..' - '..v.. ' (' .. k .. ')\n'
end
send_message(msg.chat.id, message)
end
local badmin = {}
badmin.trigger = '^/hammer'
badmin.action = function(msg)
if msg.flood then
msg.chat.id = msg.flood
end
if not config.moderation.admins[tostring(msg.from.id)] then return end
local target = get_target(msg)
if not target then
return send_message(msg.chat.id, 'No one to remove.\nBots must be removed by username.')
end
send_message(config.moderation.realm, '/ban ' .. target .. ' from all')
if msg.reply_to_message then
target = msg.reply_to_message.from.first_name
end
send_message(config.moderation.realm, target .. ' was banhammered by ' .. msg.from.first_name .. '.')
end
local modactions = {
help,
ban,
kick,
add,
rem,
promote,
demote,
broadcast,
modlist,
badmin
}
local triggers = {
'^/modhelp',
'^/modlist',
'^/modcast',
'^/[mod]*add$',
'^/[mod]*rem[ove]*$',
'^/[mod]*prom[ote]*$',
'^/[mod]*dem[ote]*',
'^/modkick',
'^/modban',
'^/hammer'
}
local action = function(msg)
for k,v in pairs(modactions) do
if string.match(msg.text, v.trigger) then
return v.action(msg)
for k,v in pairs(commands) do
if string.match(msg.text, k) then
local output = v(msg)
if output then
sendReply(msg, output)
end
return
end
end
end
return {
triggers = triggers,
action = action
action = action,
triggers = triggers
}

View File

@ -1,42 +1,42 @@
local doc = [[
/nick <nickname>
Set your nickname for the bot to call you.
Use -- to clear your nickname.
Set your nickname. Use "/whoami" to check your nickname and "/nick -" to delete it.
]]
local triggers = {
'^/nick'
'^/nick[@'..bot.username..']*'
}
local action = function(msg)
local data = load_data('nicknames.json')
local id = tostring(msg.from.id)
local input = get_input(msg.text)
local input = msg.text:input()
if not input then
local message = ''
if data[id] then
message = '\nYour nickname is currently ' .. data[id] .. '.'
end
return send_msg(msg, doc..message)
sendReply(msg, doc)
return true
end
if input == '--' then
data[id] = nil
save_data('nicknames.json', data)
send_msg(msg, 'Your nickname has been deleted.')
return
if string.len(input) > 32 then
sendReply(msg, 'The character limit for nicknames is 32.')
return true
end
input = input:sub(1,64):gsub('\n',' ')
data[id] = input
save_data('nicknames.json', data)
send_msg(msg, 'Your nickname has been set to ' .. input .. '.')
nicks = load_data('nicknames.json')
if input == '-' then
nicks[msg.from.id_str] = nil
sendReply(msg, 'Your nickname has been deleted.')
else
nicks[msg.from.id_str] = input
sendReply(msg, 'Your nickname has been set to "' .. input .. '".')
end
save_data('nicknames.json', nicks)
return true
end
return {
doc = doc,
action = action,
triggers = triggers,
action = action
doc = doc
}

View File

@ -1,40 +0,0 @@
local PLUGIN = {}
PLUGIN.doc = [[
/weather <location>
Returns the current temperature and weather conditions for a specified location.
Non-city locations are accepted; "/weather Buckingham Palace" will return the weather for Westminster.
]]
PLUGIN.triggers = {
'^/weather'
}
function PLUGIN.action(msg)
local input = get_input(msg.text)
if not input then
return send_msg(msg, PLUGIN.doc)
end
coords = get_coords(input)
if not coords then
return send_msg(msg, config.locale.errors.results)
end
local url = 'http://api.openweathermap.org/data/2.5/weather?lat=' .. coords.lat .. '&lon=' .. coords.lon
local jstr, res = HTTP.request(url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
end
local jdat = JSON.decode(jstr)
local celsius = jdat.main.temp - 273.15
local fahrenheit = tonumber(string.format("%.2f", celsius * (9/5) + 32))
local message = celsius .. '°C | ' .. fahrenheit .. '°F, ' .. jdat.weather[1].description .. '.'
send_msg(msg, message)
end
return PLUGIN

View File

@ -1,42 +1,46 @@
local PLUGIN = {}
PLUGIN.doc = [[
/dex <pokemon>
Get Pokedex information for a given Pokemon.
Includes national ID number, type, height, weight, and a description from a random regional dex.
local doc = [[
/pokedex <query>
Returns a Pokedex entry from pokeapi.co.
]]
PLUGIN.triggers = {
'^/dex'
local triggers = {
'^/[poke]*dex[@'..bot.username..']*'
}
function PLUGIN.action(msg)
local action = function(msg)
local input = get_input(msg.text:lower())
local input = msg.text_lower:input()
if not input then
return send_msg(msg, PLUGIN.doc)
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
sendReply(msg, doc)
return
end
end
local base_url = 'http://pokeapi.co'
local poke_type = nil
local url = 'http://pokeapi.co'
local dex_url = base_url .. '/api/v1/pokemon/' .. input
local dex_url = url .. '/api/v1/pokemon/' .. input
local dex_jstr, res = HTTP.request(dex_url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.results)
sendReply(msg, config.errors.connection)
return
end
local dex_jdat = JSON.decode(dex_jstr)
local desc_url = base_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)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.errors.connection)
return
end
local desc_jdat = JSON.decode(desc_jstr)
for k,v in pairs(dex_jdat.types) do
local poke_type
for i,v in ipairs(dex_jdat.types) do
local type_name = v.name:gsub("^%l", string.upper)
if not poke_type then
poke_type = type_name
@ -46,12 +50,14 @@ function PLUGIN.action(msg)
end
poke_type = poke_type .. ' type'
local info_line = 'Height: ' .. dex_jdat.height/10 .. 'm, Weight: ' .. dex_jdat.weight/10 .. 'kg'
local message = dex_jdat.name .. ' #' .. dex_jdat.national_id .. '\n' .. poke_type .. '\nHeight: ' .. dex_jdat.height/10 .. 'm, Weight: ' .. dex_jdat.weight/10 .. 'kg\n' .. desc_jdat.description:gsub('POKMON', 'POKeMON')
local m = dex_jdat.name ..' #'.. dex_jdat.national_id ..'\n'.. poke_type ..'\n'.. info_line ..'\n'.. desc_jdat.description:gsub('POKMON', 'POKeMON')
send_msg(msg, m)
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,17 +1,13 @@
local PLUGIN = {}
PLUGIN.doc = [[
local doc = [[
/pun
Get a random pun.
Have a recommendation? PM @topkecleon.
Returns a pun.
]]
PLUGIN.triggers = {
'^/pun$',
'^/pun@'
local triggers = {
'^/pun[@'..bot.username..']*'
}
PLUGIN.puns = {
local puns = {
"The person who invented the door-knock won the No-bell prize.",
"I couldn't work out how to fasten my seatbelt. Then it clicked.",
"Never trust atoms; they make up everything.",
@ -135,9 +131,14 @@ PLUGIN.puns = {
"In democracy, it's your vote that counts. In feudalism, it's your count that votes."
}
function PLUGIN.action(msg)
math.randomseed(os.time())
send_msg(msg, PLUGIN.puns[math.random(#PLUGIN.puns)])
local action = function(msg)
sendReply(msg, puns[math.random(#puns)])
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,47 +0,0 @@
local doc = [[
/reactions
Get a list of the available reaction emoticons.
]]
local triggers = {
['¯\\_(ツ)_/¯'] = '/shrug$',
['( ͡° ͜ʖ ͡°)'] = '/lenny$',
['(╯°□°)╯︵ ┻━┻'] = '/flip$',
[' o'] = '/homo$',
['ಠ_ಠ'] = '/look$',
['SHOTS FIRED'] = '/shot$'
}
local action = function(msg)
local message = string.lower(msg.text)
for k,v in pairs(triggers) do
if string.match(message, v) then
message = k
end
end
if msg.reply_to_message then
send_msg(msg.reply_to_message, message)
else
send_message(msg.chat.id, message)
end
end
-- The following block of code will generate a list of reactions add the trigger "/reactions" to display it.
-- Thanks to @Imandaneshi for the idea and early implementation.
local help = ''
for k,v in pairs(triggers) do
if v ~= '^/reactions?' then
help = help .. v:gsub('%$', ': ') .. k .. '\n'
end
end
triggers[help] = '^/reactions'
return {
triggers = triggers,
action = action,
doc = doc
}

37
plugins/reactions.lua Executable file
View File

@ -0,0 +1,37 @@
local doc = [[
/reactions
Returns a list of "reaction" emoticon commands.
]]
local triggers = {
['¯\\_(ツ)_/¯'] = '/shrug$',
['( ͡° ͜ʖ ͡°)'] = '/lenny$',
['(╯°□°)╯︵ ┻━┻'] = '/flip$',
[' o'] = '/homo$',
['ಠ_ಠ'] = '/look$',
['SHOTS FIRED'] = '/shot$'
}
-- Generate a "help" message triggered by "/reactions".
local help = ''
for k,v in pairs(triggers) do
help = help .. v:gsub('%$', ': ') .. k .. '\n'
end
triggers[help] = '^/reactions$'
local action = function(msg)
for k,v in pairs(triggers) do
if string.match(msg.text_lower, v) then
sendMessage(msg.chat.id, k)
return
end
end
end
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,84 +1,66 @@
local PLUGIN = {}
PLUGIN.doc = [[
local doc = [[
/reddit [r/subreddit | query]
This command returns top results for a given query or subreddit. NSFW posts are marked as such.
Returns the four (if group) or eight (if private message) top posts for the given subreddit or query, or from the frontpage.
]]
PLUGIN.triggers = {
'^/reddit',
'^/r$',
'^/r '
local triggers = {
'^/r[eddit]*[@'..bot.username..']*$',
'^/r[eddit]*[@'..bot.username..']* ',
'^/r/'
}
function PLUGIN.action(msg)
local action = function(msg)
local input = get_input(msg.text)
local jdat = {}
local message = ''
if input then
if string.match(input, '^r/') then
local url = 'http://www.reddit.com/' .. first_word(input) .. '/.json'
local jstr, res = HTTP.request(url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
end
jdat = JSON.decode(jstr)
if #jdat.data.children == 0 then
return send_msg(msg, config.locale.errors.results)
end
else
local url = 'http://www.reddit.com/search.json?q=' .. URL.escape(input)
local jstr, res = HTTP.request(url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
end
jdat = JSON.decode(jstr)
if #jdat.data.children == 0 then
return send_msg(msg, config.locale.errors.results)
end
end
else
url = 'https://www.reddit.com/.json'
local jstr, res = HTTP.request(url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
end
jdat = JSON.decode(jstr)
end
msg.text_lower = msg.text_lower:gsub('/r/', '/r r/')
local input = msg.text_lower:input()
local url
local limit = 4
if #jdat.data.children < limit then
limit = #jdat.data.children
if msg.chat.id == msg.from.id then
limit = 8
end
for i = 1, limit do
if input then
if input:match('^r/') then
url = 'http://www.reddit.com/' .. input .. '/.json?limit=' .. limit
else
url = 'http://www.reddit.com/search.json?q=' .. input .. '&limit=' .. limit
end
else
url = 'http://www.reddit.com/.json?limit=' .. limit
end
if jdat.data.children[i].data.over_18 then
local jstr, res = HTTP.request(url)
if res ~= 200 then
sendReply(msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if #jdat.data.children == 0 then
sendReply(msg, config.errors.results)
return
end
local message = ''
for i,v in ipairs(jdat.data.children) do
if v.data.over_18 then
message = message .. '[NSFW] '
end
url = '\n'
if not jdat.data.children[i].data.is_self then
url = '\n' .. jdat.data.children[i].data.url .. '\n'
local long_url = '\n'
if not v.data.is_self then
long_url = '\n' .. v.data.url .. '\n'
end
local short_url = '[redd.it/' .. jdat.data.children[i].data.id .. '] '
message = message .. short_url .. jdat.data.children[i].data.title .. url
local short_url = '[redd.it/' .. v.data.id .. '] '
message = message .. short_url .. v.data.title .. long_url
end
send_msg(msg, message)
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,70 +0,0 @@
reminders = {}
local doc = [[
/remind <delay> <message>
Set a reminder for yourself. First argument is the number of minutes until you wish to be reminded.
]]
local triggers = {
'^/remind'
}
local action = function(msg)
local input = get_input(msg.text)
if not input then
return send_msg(msg, doc)
end
local delay = first_word(input)
if not tonumber(delay) then
return send_msg(msg, 'The delay must be a number.')
end
if string.len(msg.text) <= string.len(delay) + 9 then
return send_msg(msg, 'Please include a reminder.')
end
local text = string.sub(msg.text, string.len(delay)+10)
if msg.from.username then
text = text .. '\n@' .. msg.from.username
end
local delay = tonumber(delay)
local rem = {
alarm = os.time() + (delay * 60),
chat_id = msg.chat.id,
text = text
}
table.insert(reminders, rem)
if delay <= 1 then
delay = (delay * 60) .. ' seconds'
else
delay = delay .. ' minutes'
end
local message = 'Your reminder has been set for ' .. delay .. ' from now:\n' .. text
send_msg(msg, message)
end
local cron = function()
for i,v in ipairs(reminders) do
if os.time() > v.alarm then
send_message(v.chat_id, text)
table.remove(reminders, i)
end
end
end
return {
doc = doc,
triggers = triggers,
action = action,
cron = cron
}

View File

@ -1,136 +1,129 @@
local PLUGIN = {}
PLUGIN.doc = [[
/slap [victim]
Slap someone!
local doc = [[
/slap [target]
Give someone a good slap (or worse) through reply or specification of a target.
]]
PLUGIN.triggers = {
'^/slap'
local triggers = {
'^/slap[@'..bot.username..']*'
}
function PLUGIN.getSlap(slapper, victim)
slaps = {
victim .. " was shot by " .. slapper .. ".",
victim .. " was pricked to death.",
victim .. " walked into a cactus while trying to escape " .. slapper .. ".",
victim .. " drowned.",
victim .. " drowned whilst trying to escape " .. slapper .. ".",
victim .. " blew up.",
victim .. " was blown up by " .. slapper .. ".",
victim .. " hit the ground too hard.",
victim .. " fell from a high place.",
victim .. " fell off a ladder.",
victim .. " fell into a patch of cacti.",
victim .. " was doomed to fall by " .. slapper .. ".",
victim .. " was blown from a high place by " .. slapper .. ".",
victim .. " was squashed by a falling anvil.",
victim .. " went up in flames.",
victim .. " burned to death.",
victim .. " was burnt to a crisp whilst fighting " .. slapper .. ".",
victim .. " walked into a fire whilst fighting " .. slapper .. ".",
victim .. " tried to swim in lava.",
victim .. " tried to swim in lava while trying to escape " .. slapper .. ".",
victim .. " was struck by lightning.",
victim .. " was slain by " .. slapper .. ".",
victim .. " got finished off by " .. slapper .. ".",
victim .. " was killed by magic.",
victim .. " was killed by " .. slapper .. " using magic.",
victim .. " starved to death.",
victim .. " suffocated in a wall.",
victim .. " fell out of the world.",
victim .. " was knocked into the void by " .. slapper .. ".",
victim .. " withered away.",
victim .. " was pummeled by " .. slapper .. ".",
victim .. " was fragged by " .. slapper .. ".",
victim .. " was desynchronized.",
victim .. " was wasted.",
victim .. " was busted.",
victim .. "'s bones are scraped clean by the desolate wind.",
victim .. " has died of dysentery.",
victim .. " fainted.",
victim .. " is out of usable Pokemon! " .. victim .. " whited out!",
victim .. " is out of usable Pokemon! " .. victim .. " blacked out!",
victim .. " whited out!",
victim .. " blacked out!",
victim .. " says goodbye to this cruel world.",
victim .. " got rekt.",
victim .. " was sawn in half by " .. slapper .. ".",
victim .. " died. I blame " .. slapper .. ".",
victim .. " was axe-murdered by " .. slapper .. ".",
victim .. "'s melon was split by " .. slapper .. ".",
victim .. " was slice and diced by " .. slapper .. ".",
victim .. " was split from crotch to sternum by " .. slapper .. ".",
victim .. "'s death put another notch in " .. slapper .. "'s axe.",
victim .. " died impossibly!",
victim .. " died from " .. slapper .. "'s mysterious tropical disease.",
victim .. " escaped infection by dying.",
victim .. " played hot-potato with a grenade.",
victim .. " was knifed by " .. slapper .. ".",
victim .. " fell on his sword.",
victim .. " ate a grenade.",
victim .. " practiced being " .. slapper .. "'s clay pigeon.",
victim .. " is what's for dinner!",
victim .. " was terminated by " .. slapper .. ".",
victim .. " was shot before being thrown out of a plane.",
victim .. " was not invincible.",
victim .. " has encountered an error.",
victim .. " died and reincarnated as a goat.",
slapper .. " threw " .. victim .. " off a building.",
victim .. " is sleeping with the fishes.",
victim .. " got a premature burial.",
slapper .. " replaced all of " .. victim .. "'s music with Nickelback.",
slapper .. " spammed " .. victim .. "'s email.",
slapper .. " made " .. victim .. " a knuckle sandwich.",
slapper .. " slapped " .. victim .. " with pure nothing.",
slapper .. " hit " .. victim .. " with a small, interstellar spaceship.",
victim .. " was quickscoped by " .. slapper .. ".",
slapper .. " put " .. victim .. " in check-mate.",
slapper .. " RSA-encrypted " .. victim .. " and deleted the private key.",
slapper .. " put " .. victim .. " in the friendzone.",
slapper .. " slaps " .. victim .. " with a DMCA takedown request!",
victim .. " became a corpse blanket for " .. slapper .. ".",
"Death is when the monsters get you. Death comes for " .. victim .. ".",
"Cowards die many times before their death. " .. victim .. " never tasted death but once."
}
return slaps[math.random(#slaps)]
end
local slaps = {
'$victim was shot by $victor.',
'$victim was pricked to death.',
'$victim walked into a cactus while trying to escape $victor.',
'$victim drowned.',
'$victim drowned whilst trying to escape $victor.',
'$victim blew up.',
'$victim was blown up by $victor.',
'$victim hit the ground too hard.',
'$victim fell from a high place.',
'$victim fell off a ladder.',
'$victim fell into a patch of cacti.',
'$victim was doomed to fall by $victor.',
'$victim was blown from a high place by $victor.',
'$victim was squashed by a falling anvil.',
'$victim went up in flames.',
'$victim burned to death.',
'$victim was burnt to a crisp whilst fighting $victor.',
'$victim walked into a fire whilst fighting $victor.',
'$victim tried to swim in lava.',
'$victim tried to swim in lava while trying to escape $victor.',
'$victim was struck by lightning.',
'$victim was slain by $victor.',
'$victim got finished off by $victor.',
'$victim was killed by magic.',
'$victim was killed by $victor using magic.',
'$victim starved to death.',
'$victim suffocated in a wall.',
'$victim fell out of the world.',
'$victim was knocked into the void by $victor.',
'$victim withered away.',
'$victim was pummeled by $victor.',
'$victim was fragged by $victor.',
'$victim was desynchronized.',
'$victim was wasted.',
'$victim was busted.',
'$victim\'s bones are scraped clean by the desolate wind.',
'$victim has died of dysentery.',
'$victim fainted.',
'$victim is out of usable Pokemon! $victim whited out!',
'$victim is out of usable Pokemon! $victim blacked out!',
'$victim whited out!',
'$victim blacked out!',
'$victim says goodbye to this cruel world.',
'$victim got rekt.',
'$victim was sawn in half by $victor.',
'$victim died. I blame $victor.',
'$victim was axe-murdered by $victor.',
'$victim\'s melon was split by $victor.',
'$victim was slice and diced by $victor.',
'$victim was split from crotch to sternum by $victor.',
'$victim\'s death put another notch in $victor\'s axe.',
'$victim died impossibly!',
'$victim died from $victor\'s mysterious tropical disease.',
'$victim escaped infection by dying.',
'$victim played hot-potato with a grenade.',
'$victim was knifed by $victor.',
'$victim fell on his sword.',
'$victim ate a grenade.',
'$victim practiced being $victor\'s clay pigeon.',
'$victim is what\'s for dinner!',
'$victim was terminated by $victor.',
'$victim was shot before being thrown out of a plane.',
'$victim was not invincible.',
'$victim has encountered an error.',
'$victim died and reincarnated as a goat.',
'$victor threw $victim off a building.',
'$victim is sleeping with the fishes.',
'$victim got a premature burial.',
'$victor replaced all of $victim\'s music with Nickelback.',
'$victor spammed $victim\'s email.',
'$victor made $victim a knuckle sandwich.',
'$victor slapped $victim with pure nothing.',
'$victor hit $victim with a small, interstellar spaceship.',
'$victim was quickscoped by $victor.',
'$victor put $victim in check-mate.',
'$victor RSA-encrypted $victim and deleted the private key.',
'$victor put $victim in the friendzone.',
'$victor slaps $victim with a DMCA takedown request!',
'$victim became a corpse blanket for $victor.',
'Death is when the monsters get you. Death comes for $victim.',
'Cowards die many times before their death. $victim never tasted death but once.'
}
function PLUGIN.action(msg)
local action = function(msg)
math.randomseed(os.time())
local slapper, victim, sid, vid
victim = get_input(msg.text)
if victim then
slapper = msg.from.first_name
else
victim = msg.from.first_name
vid = msg.from.id
slapper = bot.first_name
end
local nicks = load_data('nicknames.json')
local victim = msg.text:input()
if msg.reply_to_message then
victim = msg.reply_to_message.from.first_name
vid = msg.reply_to_message.from.id
slapper = msg.from.first_name
sid = msg.from.id
if slapper == victim then
slapper = bot.first_name
sid = bot.id
if nicks[tostring(msg.reply_to_message.from.id)] then
victim = nicks[tostring(msg.reply_to_message.from.id)]
else
victim = msg.reply_to_message.from.first_name
end
end
nicks = load_data('nicknames.json') -- Try to replace slapper/victim names with nicknames.
sid = tostring(sid)
vid = tostring(vid)
if nicks[sid] then slapper = nicks[sid] end
if nicks[vid] then victim = nicks[vid] end
local victor = msg.from.first_name
if nicks[msg.from.id_str] then
victor = nicks[msg.from.id_str]
end
local message = PLUGIN.getSlap(slapper, victim)
send_message(msg.chat.id, latcyr(message))
if not victim then
victim = victor
victor = bot.first_name
end
local message = slaps[math.random(#slaps)]
message = message:gsub('$victim', victim)
message = message:gsub('$victor', victor)
sendMessage(msg.chat.id, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,52 +0,0 @@
-- Spotify Plugin for bot based on otouto
-- ByTiagoDanin - Telegram.me/tiagodanin
local PLUGIN = {}
PLUGIN.doc = [[
/spotify <music>
Track Spotify music.
]]
PLUGIN.triggers = {
'^/spoti$',
'^/spotify'
}
function PLUGIN.action(msg)
local input = get_input(msg.text)
if not input then
return send_msg(msg, PLUGIN.doc)
end
--URL API
local BASE_URL = "https://api.spotify.com/v1/search"
local URLP = "?q=".. (URL.escape(input) or "").."&type=track&limit=5" -- Limit 5
-- Decode json
local decj, tim = HTTPS.request(BASE_URL..URLP)
if tim ~=200 then return nil end
-- Table
local spotify = JSON.decode(decj)
local tables = {}
for pri,result in ipairs(spotify.tracks.items) do
table.insert(tables, {
spotify.tracks.total,
result.name .. ' - ' .. result.artists[1].name,
result.external_urls.spotify
})
end
-- Print Tables
local gets = ""
for pri,cont in ipairs(tables) do
gets=gets.."▶️ "..cont[2].."\n"..cont[3].."\n"
end
-- ERRO 404
local text_end = gets -- Text END
if gets == "" then
text_end = "Not found music"
end
-- Send MSG
send_msg(msg, text_end)
end
return PLUGIN

View File

@ -1,48 +1,53 @@
-- time_offset is the number of seconds necessary to correct your system clock to UTC.
local PLUGIN = {}
PLUGIN.doc = [[
local doc = [[
/time <location>
Sends the time and timezone for a given location.
Returns the time, date, and timezone for the given location.
]]
PLUGIN.triggers = {
'^/time'
local triggers = {
'^/time[@'..bot.username..']*'
}
function PLUGIN.action(msg)
local action = function(msg)
local input = get_input(msg.text)
local input = msg.text:input()
if not input then
return send_msg(msg, PLUGIN.doc)
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
sendReply(msg, doc)
return
end
end
local coords = get_coords(input)
if not coords then
return send_msg(msg, config.locale.errors.results)
if type(coords) == 'string' then
sendReply(msg, coords)
return
end
local url = 'https://maps.googleapis.com/maps/api/timezone/json?location=' .. coords.lat ..','.. coords.lon .. '&timestamp='..os.time()
local jstr, res = HTTPS.request(url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
local timestamp = os.time() + jdat.rawOffset + jdat.dstOffset + config.time_offset
local utcoff = (jdat.rawOffset + jdat.dstOffset) / 3600
if utcoff == math.abs(utcoff) then
utcoff = '+' .. utcoff
end
local message = os.date('%I:%M %p\n', timestamp) .. os.date('%A, %B %d, %Y\n', timestamp) .. jdat.timeZoneName .. ' (UTC' .. utcoff .. ')'
send_msg(msg, message)
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,41 +1,40 @@
-- Glanced at https://github.com/yagop/telegram-bot/blob/master/plugins/translate.lua
local PLUGIN = {}
PLUGIN.triggers = {
'^/translate'
}
PLUGIN.doc = [[
/translate [target lang]
Reply to a message to translate it to the default language.
local doc = [[
/translate [text]
Translates input or the replied-to message into the bot's language.
]]
PLUGIN.action = function(msg)
local triggers = {
'^/translate[@'..bot.username..']*'
}
if not msg.reply_to_message then
return send_msg(msg, PLUGIN.doc)
local action = function(msg)
local input = msg.text:input()
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
sendReply(msg, doc)
return
end
end
local tl = config.locale.translate or 'en'
local input = get_input(msg.text)
if input then
tl = input
end
local url = 'http://translate.google.com/translate_a/single?client=t&ie=UTF-8&oe=UTF-8&hl=en&dt=t&tl=' .. tl .. '&sl=auto&text=' .. URL.escape(msg.reply_to_message.text)
local str, res = HTTP.request(url)
local url = 'https://translate.google.com/translate_a/single?client=t&ie=UTF-8&oe=UTF-8&hl=en&dt=t&sl=auto&tl=' .. config.lang .. '&text=' .. URL.escape(input)
local str, res = HTTPS.request(url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.errors.connection)
return
end
local output = str:gmatch("%[%[%[\"(.*)\"")():gsub("\"(.*)", "")
local output = latcyr(output)
local output = latcyr(str:gmatch("%[%[%[\"(.*)\"")():gsub("\"(.*)", ""))
send_msg(msg.reply_to_message, output)
sendReply(msg.reply_to_message or msg, output)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,48 +1,50 @@
local PLUGIN = {}
PLUGIN.doc = [[
/ud <term>
Returns the first definition for a given term from Urban Dictionary.
local doc = [[
/urbandictionary <query>
Returns a definition from Urban Dictionary.
]]
PLUGIN.triggers = {
'^/ud',
'^/urbandictionary',
'^/urban'
local triggers = {
'^/u[rban]*d[ictionary]*[@'..bot.username..']*',
'^/urban[@'..bot.username..']*'
}
function PLUGIN.action(msg)
local action = function(msg)
local input = get_input(msg.text)
local input = msg.text:input()
if not input then
if msg.reply_to_message then
msg = msg.reply_to_message
input = msg.text
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
return send_msg(msg, PLUGIN.doc)
sendReply(msg, doc)
return
end
end
local url = 'http://api.urbandictionary.com/v0/define?term=' .. URL.escape(input)
local jstr, res = HTTP.request(url)
local jstr, res = HTTP.request(url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if jdat.result_type == "no_results" then
return send_msg(msg, config.locale.errors.results)
sendReply(msg, config.errors.results)
return
end
message = '"' .. jdat.list[1].word .. '"\n' .. trim_string(jdat.list[1].definition)
local message = '"' .. jdat.list[1].word .. '"\n' .. jdat.list[1].definition:trim()
if string.len(jdat.list[1].example) > 0 then
message = message .. '\n\nExample:\n' .. trim_string(jdat.list[1].example)
message = message .. '\n\nExample:\n' .. jdat.list[1].example:trim()
end
send_msg(msg, message)
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,41 +1,56 @@
local PLUGIN = {}
if not config.owm_api_key then
print('Missing config value: owm_api_key.')
print('weather.lua will not be enabled.')
return
end
PLUGIN.doc = [[
local doc = [[
/weather <location>
Returns the current temperature and weather conditions for a specified location.
Non-city locations are accepted; "/weather Buckingham Palace" will return the weather for Westminster.
Results and weather data are powered by Yahoo.
Returns the current weather conditions for a given location.
]]
PLUGIN.triggers = {
'^/weather'
local triggers = {
'^/weather[@'..bot.username..']*'
}
function PLUGIN.action(msg)
local action = function(msg)
local input = get_input(msg.text)
local input = msg.text:input()
if not input then
return send_msg(msg, PLUGIN.doc)
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
sendReply(msg, doc)
return
end
end
local url = 'https://query.yahooapis.com/v1/public/yql?q=select%20item.condition%20from%20weather.forecast%20where%20woeid%20in%20%28select%20woeid%20from%20geo.places%281%29%20where%20text%3D%22' .. URL.escape(input) .. '%22%29&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys'
local coords = get_coords(input)
if type(coords) == 'string' then
sendReply(msg, coords)
return
end
local url = 'http://api.openweathermap.org/data/2.5/weather?APPID=' .. config.owm_api_key .. '&lat=' .. coords.lat .. '&lon=' .. coords.lon
local jstr, res = HTTP.request(url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if not jdat.query.results then
return send_msg(msg, config.locale.errors.results)
end
local data = jdat.query.results.channel.item.condition
local fahrenheit = data.temp
local celsius = string.format('%.0f', (fahrenheit - 32) * 5/9)
local message = celsius .. '°C | ' .. fahrenheit .. '°F, ' .. data.text .. '.'
local celsius = string.format('%.2f', jdat.main.temp - 273.15)
local fahrenheit = string.format('%.2f', celsius * (9/5) + 32)
local message = celsius .. '°C | ' .. fahrenheit .. '°F, ' .. jdat.weather[1].description .. '.'
send_msg(msg, message)
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,34 +1,13 @@
local PLUGIN = {}
PLUGIN.doc = [[
/whoami
Get the user ID for yourself and the group. Use it in a reply to get info for the sender of the original message.
]]
PLUGIN.triggers = {
'^/whoami',
'^/ping',
'^/who$'
local triggers = {
'^/who[ami]*[@'..bot.username..']*$'
}
function PLUGIN.action(msg)
if msg.from.id == msg.chat.id then
to_name = '@' .. bot.username .. ' (' .. bot.id .. ')'
else
to_name = string.gsub(msg.chat.title, '_', ' ') .. ' (' .. string.gsub(msg.chat.id, '-', '') .. ')'
end
local action = function(msg)
if msg.reply_to_message then
msg = msg.reply_to_message
end
local nicknames = load_data('nicknames.json')
local message = ''
if nicknames[tostring(msg.from.id)] then
message = 'Hi, ' .. nicknames[tostring(msg.from.id)] .. '!\n'
end
local from_name = msg.from.first_name
if msg.from.last_name then
from_name = from_name .. ' ' .. msg.from.last_name
@ -38,10 +17,25 @@ function PLUGIN.action(msg)
end
from_name = from_name .. ' (' .. msg.from.id .. ')'
local message = message .. 'You are ' .. from_name .. ' and you are messaging ' .. to_name .. '.'
local to_name
if msg.chat.title then
to_name = msg.chat.title .. ' (' .. math.abs(msg.chat.id) .. ').'
else
to_name = '@' .. bot.username .. ', AKA ' .. bot.first_name .. ' (' .. bot.id .. ').'
end
send_msg(msg, message)
local message = 'You are ' .. from_name .. ' and you are messaging ' .. to_name
local nicks = load_data('nicknames.json')
if nicks[msg.from.id_str] then
message = message .. '\nYour nickname is ' .. nicks[msg.from.id_str] .. '.'
end
sendReply(msg, message)
end
return PLUGIN
return {
action = action,
triggers = triggers
}

View File

@ -1,70 +1,67 @@
local doc = [[
/wiki <topic>
Search Wikipedia for a relevant article and return its summary.
/wikipedia <query>
Returns an article from Wikipedia.
]]
local triggers = {
'^/wiki',
'^/w '
'^/w[iki[pedia]*]*[@'..bot.username..']*$',
'^/w[iki[pedia]*]*[@'..bot.username..']* '
}
local action = function(msg)
local gurl = 'http://ajax.googleapis.com/ajax/services/search/web?v=1.0&rsz=1&q=site:wikipedia.org%20'
local wurl = 'http://en.wikipedia.org/w/api.php?action=query&prop=extracts&format=json&exchars=4000&exsectionformat=plain&titles='
local input = get_input(msg.text)
local input = msg.text:input()
if not input then
return send_msg(msg, doc)
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
sendReply(msg, doc)
return
end
end
local jstr, res = HTTP.request(gurl..URL.escape(input))
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
end
local title = JSON.decode(jstr)
local url = title.responseData.results[1].url
title = title.responseData.results[1].titleNoFormatting
title = title:gsub(' %- Wikipedia, the free encyclopedia', '')
local gurl = 'https://ajax.googleapis.com/ajax/services/search/web?v=1.0&rsz=1&q=site:wikipedia.org%20'
local wurl = 'https://en.wikipedia.org/w/api.php?action=query&prop=extracts&format=json&exchars=4000&exsectionformat=plain&titles='
jstr, res = HTTPS.request(wurl..URL.escape(title))
local jstr, res = HTTPS.request(gurl .. URL.escape(input))
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.error.connection)
return
end
local jdat = JSON.decode(jstr)
local url = jdat.responseData.results[1].url
local title = jdat.responseData.results[1].titleNoFormatting:gsub(' %- Wikipedia, the free encyclopedia', '')
jstr, res = HTTPS.request(wurl .. URL.escape(title))
if res ~= 200 then
sendReply(msg, config.error.connection)
return
end
local text = JSON.decode(jstr).query.pages
for k,v in pairs(text) do
text = v.extract
break -- Seriously, there's probably a way more elegant solution.
end
if not text then
return send_msg(msg, config.locale.errors.results)
sendReply(msg, config.error.connection)
return
end
--[[ Uncomment this block for more than one-paragraph summaries.
local l = text:find('<h2>')
if l then
text = text:sub(1, l-2)
end
]]--
text = text:gsub('</?.->', '')
local l = text:find('\n') -- Comment this block for more than one-paragraph summaries.
local l = text:find('\n')
if l then
text = text:sub(1, l-1)
end
text = text .. '\n' .. url
send_msg(msg, text)
sendReply(msg, text)
end
return {
doc = doc,
triggers = triggers,
action = action,
typing = true
triggers = triggers,
doc = doc
}

View File

@ -1,52 +1,56 @@
local PLUGIN = {}
PLUGIN.doc = [[
/xkcd [search]
This command returns an xkcd strip, its number, and its "secret" text. You may search for a specific strip or get a random one.
local doc = [[
/xkcd [query]
Returns an xkcd strip and its alt text. If there is no query, it will be randomized.
]]
PLUGIN.triggers = {
'^/xkcd'
local triggers = {
'^/xkcd[@'..bot.username..']*'
}
function PLUGIN.action(msg)
local action = function(msg)
local input = get_input(msg.text)
local url = 'http://xkcd.com/info.0.json'
local jstr, res = HTTP.request(url)
local input = msg.text:input()
local jstr, res = HTTP.request('http://xkcd.com/info.0.json')
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.errors.connection)
return
end
local latest = JSON.decode(jstr).num
local jdat
local res_url
if input then
url = 'http://ajax.googleapis.com/ajax/services/search/web?v=1.0&safe=active&q=site%3axkcd%2ecom%20' .. URL.escape(input)
local jstr, res = HTTP.request(url)
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)
if res ~= 200 then
print('here')
return send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.errors.connection)
return
end
jdat = JSON.decode(jstr)
local jdat = JSON.decode(jstr)
if #jdat.responseData.results == 0 then
return send_msg(msg, config.locale.errors.results)
sendReply(msg, config.errors.results)
return
end
url = jdat.responseData.results[1].url .. 'info.0.json'
res_url = jdat.responseData.results[1].url .. 'info.0.json'
else
math.randomseed(os.time())
url = 'http://xkcd.com/' .. math.random(latest) .. '/info.0.json'
res_url = 'http://xkcd.com/' .. math.random(latest) .. '/info.0.json'
end
local jstr, res = HTTP.request(url)
local jstr, res = HTTP.request(res_url)
if res ~= 200 then
return send_msg(msg, config.locale.errors.connection)
sendReply(msg, config.errors.connection)
return
end
jdat = JSON.decode(jstr)
local jdat = JSON.decode(jstr)
local message = '[' .. jdat.num .. '] ' .. jdat.alt .. '\n' .. jdat.img
send_message(msg.chat.id, message, false, msg.message_id)
sendMessage(msg.chat.id, message, false, msg.message_id)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}

View File

@ -1,44 +1,44 @@
-- Youtube Plugin for bot based on otouto
-- Glanced at https://github.com/yagop/telegram-bot/blob/master/plugins/youtube.lua
local PLUGIN = {}
-- Thanks to @TiagoDanin for writing the original plugin.
PLUGIN.doc = [[
/youtube <query>
Search videos on YouTube.
local doc = [[
/youtube <query>
Returns the top result from YouTube.
]]
PLUGIN.triggers = {
'^/youtube',
'^/yt'
local triggers = {
'^/y[ou]*t[ube]*[@'..bot.username..']*'
}
function PLUGIN.action(msg)
-- BASE
local input = get_input(msg.text)
if not input then
return send_msg(msg, PLUGIN.doc)
end
--URL API
local url = 'https://www.googleapis.com/youtube/v3/search?'
url = url..'part=snippet'..'&maxResults=4'..'&type=video'
url = url..'&q='..URL.escape(input).."&key=AIzaSyAfe7SI8kwQqaoouvAmevBfKumaLf-3HzI"
-- JSON
local res,code = HTTPS.request(url)
if code ~= 200 then return nil end
local data_JSON = JSON.decode(res)
-- Print Items
local text = ""
for k,item in pairs(data_JSON.items) do
text = text .. item.snippet.title .. '\n' .. 'http://youtu.be/' .. item.id.videoId .. '\n\n'
end
-- END - ERRO 404
local text_end = text
if text == "" then
text_end = "Not found video"
end
-- Send MSG
send_message(msg.chat.id, text_end)
local action = function(msg)
local input = msg.text:input()
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
sendReply(msg, doc)
return
end
end
local url = 'https://www.googleapis.com/youtube/v3/search?key=AIzaSyAfe7SI8kwQqaoouvAmevBfKumaLf-3HzI&type=video&part=snippet&maxResults=1&q=' .. URL.escape(input)
local jstr, res = HTTPS.request(url)
if res ~= 200 then
sendReply(msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
local message = 'https://www.youtube.com/watch?v=' .. jdat.items[1].id.videoId
sendMessage(msg.chat.id, message, false, msg.message_id)
end
return PLUGIN
return {
action = action,
triggers = triggers,
doc = doc
}