initial commie bastard
This commit is contained in:
parent
d65ed5e63f
commit
236c8bebdb
@ -1,2 +1,3 @@
|
||||
# otouto
|
||||
The popular Telegram assistant bot, now on the bot API.
|
||||
A plugin-wielding Telegram bot using the new API.
|
||||
The latest version runs on @mokubot. v1 runs on @otouto.
|
||||
|
79
bindings.lua
Normal file
79
bindings.lua
Normal file
@ -0,0 +1,79 @@
|
||||
-- bindings.lua
|
||||
-- Functions for the Telegram API.
|
||||
-- Requires ssl.https ('HTTPS'), socket.url ('URL'), and a json decoder ('JSON').
|
||||
-- Also requires config.BOT_API_KEY.
|
||||
|
||||
local BASE_URL = 'https://api.telegram.org/bot' .. config.BOT_API_KEY .. '/'
|
||||
|
||||
local function send_request(url)
|
||||
|
||||
local dat, res = HTTPS.request(url)
|
||||
local tab = JSON.decode(dat)
|
||||
|
||||
if res ~= 200 then
|
||||
print('Connection error.')
|
||||
return false
|
||||
end
|
||||
|
||||
if not tab.ok then
|
||||
print(tab.description)
|
||||
return false
|
||||
end
|
||||
|
||||
return tab
|
||||
|
||||
end
|
||||
|
||||
function get_me()
|
||||
|
||||
local url = BASE_URL .. 'getMe'
|
||||
return send_request(url)
|
||||
|
||||
end
|
||||
|
||||
function get_updates(offset)
|
||||
|
||||
local url = BASE_URL .. 'getUpdates'
|
||||
|
||||
if offset then
|
||||
url = url .. '?offset=' .. offset
|
||||
end
|
||||
|
||||
return send_request(url)
|
||||
|
||||
end
|
||||
|
||||
function send_message(chat_id, text, disable_web_page_preview, reply_to_message_id)
|
||||
|
||||
local url = BASE_URL .. 'sendMessage?chat_id=' .. chat_id .. '&text=' .. URL.escape(text)
|
||||
|
||||
if disable_web_page_preview == true then
|
||||
url = url .. '&disable_web_page_preview=true'
|
||||
end
|
||||
|
||||
if reply_to_message_id then
|
||||
url = url .. '&reply_to_message_id=' .. reply_to_message_id
|
||||
end
|
||||
|
||||
return send_request(url)
|
||||
|
||||
end
|
||||
|
||||
function send_chat_action(chat_id, action)
|
||||
|
||||
local url = BASE_URL .. 'sendChatAction?chat_id=' .. chat_id .. '&action=' .. action
|
||||
return send_request(url)
|
||||
|
||||
end
|
||||
|
||||
function send_location(chat_id, latitude, longitude, reply_to_message_id)
|
||||
|
||||
local url = BASE_URL .. 'sendLocation?chat_id=' .. chat_id .. '&latitude=' .. latitude .. '&longitude=' .. longitude
|
||||
|
||||
if reply_to_message_id then
|
||||
url = url .. '&reply_to_message_id=' .. reply_to_message_id
|
||||
end
|
||||
|
||||
return send_request(url)
|
||||
|
||||
end
|
99
bot.lua
Normal file
99
bot.lua
Normal file
@ -0,0 +1,99 @@
|
||||
-- bot.lua
|
||||
-- Run this!
|
||||
|
||||
HTTP = require('socket.http')
|
||||
HTTPS = require('ssl.https')
|
||||
JSON = require('dkjson')
|
||||
URL = require('socket.url')
|
||||
|
||||
VERSION = 2.01
|
||||
|
||||
function on_msg_receive(msg)
|
||||
|
||||
if msg.date < os.time() -5 then return end -- don't react to old messages
|
||||
if not msg.text then return end -- don't react to media messages
|
||||
if msg.forward_from then return end -- don't react to forwarded messages
|
||||
|
||||
local lower = string.lower(msg.text)
|
||||
for i,v in pairs(plugins) do
|
||||
for j,w in pairs(v.triggers) do
|
||||
if string.match(lower, w) then
|
||||
send_chat_action(msg.chat.id, 'typing')
|
||||
v.action(msg)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function bot_init()
|
||||
|
||||
print('\nLoading configuration...')
|
||||
|
||||
local jstr = io.open('config.json')
|
||||
local jstr = jstr:read('*all')
|
||||
config = JSON.decode(jstr)
|
||||
print(#config.plugins .. ' plugins enabled.')
|
||||
|
||||
require('bindings')
|
||||
require('utilities')
|
||||
|
||||
print('\nFetching bot information...')
|
||||
|
||||
bot = get_me().result
|
||||
for k,v in pairs(bot) do
|
||||
print('',k,v)
|
||||
end
|
||||
|
||||
print('Bot information retrieved!\n')
|
||||
print('Loading plugins...')
|
||||
|
||||
plugins = {}
|
||||
for i,v in ipairs(config.plugins) do
|
||||
print('',v)
|
||||
local p = loadfile('plugins/'..v)()
|
||||
table.insert(plugins, p)
|
||||
end
|
||||
|
||||
print('Done! Plugins loaded: ' .. #plugins .. '\n')
|
||||
print('Generating help message...')
|
||||
|
||||
help_message = 'Available commands:\n'
|
||||
for i,v in ipairs(plugins) do
|
||||
if v.doc then
|
||||
local a = string.sub(v.doc, 1, string.find(v.doc, '\n')-1)
|
||||
print(a)
|
||||
help_message = help_message .. ' - ' .. a .. '\n'
|
||||
end
|
||||
end
|
||||
help_message = help_message .. [[
|
||||
*Arguments: <required> [optional]
|
||||
Use "!help <command>" for specific information.
|
||||
otouto v]] .. VERSION .. [[ by @topkecleon.
|
||||
]]
|
||||
|
||||
print('Help message generated!\n')
|
||||
|
||||
is_started = true
|
||||
|
||||
end
|
||||
|
||||
bot_init()
|
||||
reminders = {}
|
||||
last_update = 0
|
||||
while is_started == true do
|
||||
|
||||
for i,v in ipairs(get_updates(last_update).result) do
|
||||
if v.update_id > last_update then
|
||||
last_update = v.update_id
|
||||
on_msg_receive(v.message)
|
||||
end
|
||||
end
|
||||
|
||||
for k,v in pairs(reminders) do
|
||||
if os.time() > v.alarm then
|
||||
send_message(v.chat_id, 'Reminder: '..v.text)
|
||||
table.remove(reminders, i)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
40
config.json
Normal file
40
config.json
Normal file
@ -0,0 +1,40 @@
|
||||
{
|
||||
"BOT_API_KEY": "",
|
||||
"ADMIN_ID": 0,
|
||||
"BIBLIA_API_KEY": "",
|
||||
"GIPHY_API_KEY": "",
|
||||
"TIME_OFFSET": 0,
|
||||
"plugins": [
|
||||
"8ball.lua",
|
||||
"admin.lua",
|
||||
"bandersnatch.lua",
|
||||
"bible.lua",
|
||||
"btc.lua",
|
||||
"calc.lua",
|
||||
"commit.lua",
|
||||
"dice.lua",
|
||||
"dogify.lua",
|
||||
"echo.lua",
|
||||
"fortune.lua",
|
||||
"gImages.lua",
|
||||
"giphy.lua",
|
||||
"gMaps.lua",
|
||||
"gSearch.lua",
|
||||
"hackernews.lua",
|
||||
"help.lua",
|
||||
"hex.lua",
|
||||
"imdb.lua",
|
||||
"personality.lua",
|
||||
"pokedex.lua",
|
||||
"reddit.lua",
|
||||
"remind.lua",
|
||||
"shrug.lua",
|
||||
"slap.lua",
|
||||
"time.lua",
|
||||
"urbandictionary.lua",
|
||||
"weather.lua",
|
||||
"whoami.lua",
|
||||
"xkcd.lua"
|
||||
]
|
||||
}
|
||||
|
20
plugin.lua
Normal file
20
plugin.lua
Normal file
@ -0,0 +1,20 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!example
|
||||
Info about the command.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!example',
|
||||
'^!e$'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
local message = 'Example output.'
|
||||
send_msg(msg, message)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
54
plugins/8ball.lua
Normal file
54
plugins/8ball.lua
Normal file
@ -0,0 +1,54 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!8ball
|
||||
Magic 8-ball. Returns a standard 8ball message, unless called with "y/n", where it will return a less verbose answer.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!helix',
|
||||
'^!8ball',
|
||||
'y/n%p?$'
|
||||
}
|
||||
|
||||
PLUGIN.answers = {
|
||||
"It is certain.",
|
||||
"It is decidedly so.",
|
||||
"Without a doubt.",
|
||||
"Yes, definitely.",
|
||||
"You may rely on it.",
|
||||
"As I see it, yes.",
|
||||
"Most likely.",
|
||||
"Outlook: good.",
|
||||
"Yes.",
|
||||
"Signs point to yes.",
|
||||
"Reply hazy try again.",
|
||||
"Ask again later.",
|
||||
"Better not tell you now.",
|
||||
"Cannot predict now.",
|
||||
"Concentrate and ask again.",
|
||||
"Don't count on it.",
|
||||
"My reply is no.",
|
||||
"My sources say no.",
|
||||
"Outlook: not so good.",
|
||||
"Very doubtful.",
|
||||
"There is a time and place for everything, but not now."
|
||||
}
|
||||
|
||||
PLUGIN.yesno = {'Absolutely.', 'In your dreams.', 'Yes.', 'No.', 'Maybe.'}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
math.randomseed(os.time())
|
||||
|
||||
if string.match(string.lower(msg.text), 'y/n') then
|
||||
message = PLUGIN.yesno[math.random(#PLUGIN.yesno)]
|
||||
else
|
||||
message = PLUGIN.answers[math.random(#PLUGIN.answers)]
|
||||
end
|
||||
|
||||
send_msg(msg, message)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
39
plugins/admin.lua
Normal file
39
plugins/admin.lua
Normal file
@ -0,0 +1,39 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!admin '
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
local input = get_input(msg.text)
|
||||
|
||||
local message = 'Command not found.'
|
||||
|
||||
if msg.from.id ~= config.ADMIN_ID then
|
||||
message = 'Permission denied.'
|
||||
|
||||
elseif string.lower(first_word(input)) == 'run' then
|
||||
|
||||
local output = string.sub(input, 5)
|
||||
local output = io.popen(output)
|
||||
message = output:read('*all')
|
||||
output:close()
|
||||
|
||||
elseif string.lower(first_word(input)) == 'reload' then
|
||||
|
||||
bot_init()
|
||||
message = 'Bot reloaded!'
|
||||
|
||||
elseif string.lower(first_word(input)) == 'halt' then
|
||||
|
||||
is_started = false
|
||||
message = 'Shutting down...'
|
||||
|
||||
end
|
||||
|
||||
send_msg(msg, message)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
33
plugins/bandersnatch.lua
Normal file
33
plugins/bandersnatch.lua
Normal file
@ -0,0 +1,33 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!bandersnatch
|
||||
This is a Benedict Cumberbatch name generator.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!bandersnatch',
|
||||
'^!bc$'
|
||||
}
|
||||
|
||||
PLUGIN.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" }
|
||||
|
||||
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" }
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
math.randomseed(os.time())
|
||||
|
||||
local message = ''
|
||||
if math.random(10) == 10 then
|
||||
message = PLUGIN.fullnames[math.random(#PLUGIN.fullnames)]
|
||||
else
|
||||
message = PLUGIN.firstnames[math.random(#PLUGIN.firstnames)] .. ' ' .. PLUGIN.lastnames[math.random(#PLUGIN.lastnames)]
|
||||
end
|
||||
|
||||
send_msg(msg, message)
|
||||
end
|
||||
|
||||
return PLUGIN
|
32
plugins/bible.lua
Normal file
32
plugins/bible.lua
Normal file
@ -0,0 +1,32 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
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
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!bible',
|
||||
'^!b '
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
local input = get_input(msg.text)
|
||||
if not input then
|
||||
return send_msg(msg, PLUGIN.doc)
|
||||
end
|
||||
|
||||
local url = 'http://api.biblia.com/v1/bible/content/KJV.txt?key=' .. config.BIBLIA_API_KEY .. '&passage=' .. URL.escape(input)
|
||||
local message, res = HTTP.request(url)
|
||||
|
||||
if res ~= 200 then
|
||||
message = 'Connection error.'
|
||||
end
|
||||
|
||||
send_msg(msg, message)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
55
plugins/btc.lua
Normal file
55
plugins/btc.lua
Normal file
@ -0,0 +1,55 @@
|
||||
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, 'Connection error.')
|
||||
end
|
||||
|
||||
local jdat = JSON.decode(jstr)
|
||||
|
||||
if string.len(msg.text) > 6 then
|
||||
arg1 = string.upper(string.sub(msg.text, 6, 8))
|
||||
end
|
||||
if string.len(msg.text) > 9 then
|
||||
arg2 = tonumber(string.sub(msg.text, 10))
|
||||
end
|
||||
|
||||
for k,v in pairs(jdat) do
|
||||
if k == arg1 then
|
||||
url = v .. '/'
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if url then
|
||||
jstr, b = HTTPS.request(url)
|
||||
else
|
||||
return send_msg(msg, 'Error: Currency not found.')
|
||||
end
|
||||
|
||||
jdat = JSON.decode(jstr)
|
||||
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
|
30
plugins/calc.lua
Normal file
30
plugins/calc.lua
Normal file
@ -0,0 +1,30 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.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.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!calc'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
local input = get_input(msg.text)
|
||||
if not input then
|
||||
return send_msg(msg, PLUGIN.doc)
|
||||
end
|
||||
|
||||
local url = 'http://api.mathjs.org/v1/?expr=' .. URL.escape(input)
|
||||
local message, res = HTTP.request(url)
|
||||
|
||||
if res ~= 200 then
|
||||
return send_msg(msg, 'Connection error.')
|
||||
end
|
||||
|
||||
send_msg(msg, message)
|
||||
end
|
||||
|
||||
return PLUGIN
|
||||
|
420
plugins/commit.lua
Normal file
420
plugins/commit.lua
Normal file
@ -0,0 +1,420 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!commit
|
||||
http://whatthecommit.com.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!commit'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
math.randomseed(os.time())
|
||||
send_msg(msg, PLUGIN.commits[math.random(#PLUGIN.commits)])
|
||||
end
|
||||
|
||||
PLUGIN.commits = {
|
||||
"One does not simply merge into master",
|
||||
"Merging the merge",
|
||||
"Another bug bites the dust",
|
||||
"de-misunderestimating",
|
||||
"Some shit.",
|
||||
"add actual words",
|
||||
"I CAN HAZ COMMENTZ.",
|
||||
"giggle.",
|
||||
"Whatever.",
|
||||
"Finished fondling.",
|
||||
"FONDLED THE CODE",
|
||||
"this is how we generate our shit.",
|
||||
"unh",
|
||||
"It works!",
|
||||
"unionfind is no longer being molested.",
|
||||
"Well, it's doing something.",
|
||||
"I'M PUSHING.",
|
||||
"Whee.",
|
||||
"Whee, good night.",
|
||||
"It'd be nice if type errors caused the compiler to issue a type error",
|
||||
"Fucking templates.",
|
||||
"I hate this fucking language.",
|
||||
"marks",
|
||||
"that coulda been bad",
|
||||
"hoo boy",
|
||||
"It was the best of times, it was the worst of times",
|
||||
"Fucking egotistical bastard. adds expandtab to vimrc",
|
||||
"if you're not using et, fuck off",
|
||||
"WHO THE FUCK CAME UP WITH MAKE?",
|
||||
"This is a basic implementation that works.",
|
||||
"By works, I meant 'doesnt work'. Works now..",
|
||||
"Last time I said it works? I was kidding. Try this.",
|
||||
"Just stop reading these for a while, ok..",
|
||||
"Give me a break, it's 2am. But it works now.",
|
||||
"Make that it works in 90% of the cases. 3:30.",
|
||||
"Ok, 5am, it works. For real.",
|
||||
"FOR REAL.",
|
||||
"I don't know what these changes are supposed to accomplish but somebody told me to make them.",
|
||||
"I don't get paid enough for this shit.",
|
||||
"fix some fucking errors",
|
||||
"first blush",
|
||||
"So my boss wanted this button ...",
|
||||
"uhhhhhh",
|
||||
"forgot we're not using a smart language",
|
||||
"include shit",
|
||||
"To those I leave behind, good luck!",
|
||||
"things occurred",
|
||||
"i dunno, maybe this works",
|
||||
"8==========D",
|
||||
"No changes made",
|
||||
"whooooooooooooooooooooooooooo",
|
||||
"clarify further the brokenness of C++. why the fuck are we using C++?",
|
||||
".",
|
||||
"Friday 5pm",
|
||||
"changes",
|
||||
"A fix I believe, not like I tested or anything",
|
||||
"Useful text",
|
||||
"pgsql is being a pain",
|
||||
"pgsql is more strict, increase the hackiness up to 11",
|
||||
"c&p fail",
|
||||
"syntax",
|
||||
"fix",
|
||||
"just shoot me",
|
||||
"arrrggghhhhh fixed!",
|
||||
"someone fails and it isn't me",
|
||||
"totally more readable",
|
||||
"better grepping",
|
||||
"fix",
|
||||
"fix bug, for realz",
|
||||
"fix /sigh",
|
||||
"Does this work",
|
||||
"MOAR BIFURCATION",
|
||||
"bifurcation",
|
||||
"REALLY FUCKING FIXED",
|
||||
"FIX",
|
||||
"better ignores",
|
||||
"More ignore",
|
||||
"more ignores",
|
||||
"more ignores",
|
||||
"more ignores",
|
||||
"more ignores",
|
||||
"more ignores",
|
||||
"more ignored words",
|
||||
"more fixes",
|
||||
"really ignore ignored worsd",
|
||||
"fixes",
|
||||
"/sigh",
|
||||
"fix",
|
||||
"fail",
|
||||
"pointless limitation",
|
||||
"omg what have I done?",
|
||||
"added super-widget 2.0.",
|
||||
"tagging release w.t.f.",
|
||||
"I can't believe it took so long to fix this.",
|
||||
"I must have been drunk.",
|
||||
"This is why the cat shouldn't sit on my keyboard.",
|
||||
"This is why git rebase is a horrible horrible thing.",
|
||||
"ajax-loader hotness, oh yeah",
|
||||
"small is a real HTML tag, who knew.",
|
||||
"WTF is this.",
|
||||
"Do things better, faster, stronger",
|
||||
"Use a real JS construct, WTF knows why this works in chromium.",
|
||||
"Added a banner to the default admin page. Please have mercy on me =(",
|
||||
"needs more cow bell",
|
||||
"Switched off unit test X because the build had to go out now and there was no time to fix it properly.",
|
||||
"Updated",
|
||||
"I must sleep... it's working... in just three hours...",
|
||||
"I was wrong...",
|
||||
"Completed with no bugs...",
|
||||
"Fixed a little bug...",
|
||||
"Fixed a bug in NoteLineCount... not seriously...",
|
||||
"woa!! this one was really HARD!",
|
||||
"Made it to compile...",
|
||||
"changed things...",
|
||||
"touched...",
|
||||
"i think i fixed a bug...",
|
||||
"perfect...",
|
||||
"Moved something to somewhere... goodnight...",
|
||||
"oops, forgot to add the file",
|
||||
"Corrected mistakes",
|
||||
"oops",
|
||||
"oops!",
|
||||
"put code that worked where the code that didn't used to be",
|
||||
"Nothing to see here, move along",
|
||||
"I am even stupider than I thought",
|
||||
"I don't know what the hell I was thinking.",
|
||||
"fixed errors in the previous commit",
|
||||
"Committed some changes",
|
||||
"Some bugs fixed",
|
||||
"Minor updates",
|
||||
"Added missing file in previous commit",
|
||||
"bug fix",
|
||||
"typo",
|
||||
"bara bra grejjor",
|
||||
"Continued development...",
|
||||
"Does anyone read this? I'll be at the coffee shop accross the street.",
|
||||
"That's just how I roll",
|
||||
"work in progress",
|
||||
"minor changes",
|
||||
"some brief changes",
|
||||
"assorted changes",
|
||||
"lots and lots of changes",
|
||||
"another big bag of changes",
|
||||
"lots of changes after a lot of time",
|
||||
"LOTS of changes. period",
|
||||
"Test commit. Please ignore",
|
||||
"I'm just a grunt. Don't blame me for this awful PoS.",
|
||||
"I did it for the lulz!",
|
||||
"I'll explain this when I'm sober .. or revert it",
|
||||
"Obligatory placeholder commit message",
|
||||
"A long time ago, in a galaxy far far away...",
|
||||
"Fixed the build.",
|
||||
"various changes",
|
||||
"One more time, but with feeling.",
|
||||
"Handled a particular error.",
|
||||
"Fixed unnecessary bug.",
|
||||
"Removed code.",
|
||||
"Added translation.",
|
||||
"Updated build targets.",
|
||||
"Refactored configuration.",
|
||||
"Locating the required gigapixels to render...",
|
||||
"Spinning up the hamster...",
|
||||
"Shovelling coal into the server...",
|
||||
"Programming the flux capacitor",
|
||||
"The last time I tried this the monkey didn't survive. Let's hope it works better this time.",
|
||||
"I should have had a V8 this morning.",
|
||||
"640K ought to be enough for anybody",
|
||||
"pay no attention to the man behind the curtain",
|
||||
"a few bits tried to escape, but we caught them",
|
||||
"Who has two thumbs and remembers the rudiments of his linear algebra courses? Apparently, this guy.",
|
||||
"workaround for ant being a pile of fail",
|
||||
"Don't push this commit",
|
||||
"rats",
|
||||
"squash me",
|
||||
"fixed mistaken bug",
|
||||
"Final commit, ready for tagging",
|
||||
"-m \'So I hear you like commits ...\'",
|
||||
"epic",
|
||||
"need another beer",
|
||||
"Well the book was obviously wrong.",
|
||||
"lolwhat?",
|
||||
"Another commit to keep my CAN streak going.",
|
||||
"I cannot believe that it took this long to write a test for this.",
|
||||
"TDD: 1, Me: 0",
|
||||
"Yes, I was being sarcastic.",
|
||||
"Apparently works-for-me is a crappy excuse.",
|
||||
"tl;dr",
|
||||
"I would rather be playing SC2.",
|
||||
"Crap. Tonight is raid night and I am already late.",
|
||||
"I know what I am doing. Trust me.",
|
||||
"You should have trusted me.",
|
||||
"Is there an award for this?",
|
||||
"Is there an achievement for this?",
|
||||
"I'm totally adding this to epic win. +300",
|
||||
"This really should not take 19 minutes to build.",
|
||||
"fixed the israeli-palestinian conflict",
|
||||
"SHIT ===> GOLD",
|
||||
"Committing in accordance with the prophecy.",
|
||||
"It compiles! Ship it!",
|
||||
"LOL!",
|
||||
"Reticulating splines...",
|
||||
"SEXY RUSSIAN CODES WAITING FOR YOU TO CALL",
|
||||
"s/import/include/",
|
||||
"extra debug for stuff module",
|
||||
"debug line test",
|
||||
"debugo",
|
||||
"remove debug<br/>all good",
|
||||
"debug suff",
|
||||
"more debug... who overwrote!",
|
||||
"these confounded tests drive me nuts",
|
||||
"For great justice.",
|
||||
"QuickFix.",
|
||||
"oops - thought I got that one.",
|
||||
"removed echo and die statements, lolz.",
|
||||
"somebody keeps erasing my changes.",
|
||||
"doh.",
|
||||
"pam anderson is going to love me.",
|
||||
"added security.",
|
||||
"arrgghh... damn this thing for not working.",
|
||||
"jobs... steve jobs",
|
||||
"and a comma",
|
||||
"this is my quickfix branch and i will use to do my quickfixes",
|
||||
"Fix my stupidness",
|
||||
"and so the crazy refactoring process sees the sunlight after some months in the dark!",
|
||||
"gave up and used tables.",
|
||||
"[Insert your commit message here. Be sure to make it descriptive.]",
|
||||
"Removed test case since code didn't pass QA",
|
||||
"removed tests since i can't make them green",
|
||||
"stuff",
|
||||
"more stuff",
|
||||
"Become a programmer, they said. It'll be fun, they said.",
|
||||
"Same as last commit with changes",
|
||||
"foo",
|
||||
"just checking if git is working properly...",
|
||||
"fixed some minor stuff, might need some additional work.",
|
||||
"just trolling the repo",
|
||||
"All your codebase are belong to us.",
|
||||
"Somebody set up us the bomb.",
|
||||
"should work I guess...",
|
||||
"To be honest, I do not quite remember everything I changed here today. But it is all good, I tell ya.",
|
||||
"well crap.",
|
||||
"herpderp (redux)",
|
||||
"herpderp",
|
||||
"Derp",
|
||||
"derpherp",
|
||||
"Herping the derp",
|
||||
"sometimes you just herp the derp so hard it herpderps",
|
||||
"Derp. Fix missing constant post rename",
|
||||
"Herping the fucking derp right here and now.",
|
||||
"Derp, asset redirection in dev mode",
|
||||
"mergederp",
|
||||
"Derp search/replace fuckup",
|
||||
"Herpy dooves.",
|
||||
"Derpy hooves",
|
||||
"derp, helper method rename",
|
||||
"Herping the derp derp (silly scoping error)",
|
||||
"Herp derp I left the debug in there and forgot to reset errors.",
|
||||
"Reset error count between rows. herpderp",
|
||||
"hey, what's that over there?!",
|
||||
"hey, look over there!",
|
||||
"It worked for me...",
|
||||
"Does not work.",
|
||||
"Either Hot Shit or Total Bollocks",
|
||||
"Arrrrgggg",
|
||||
"Don’t mess with Voodoo",
|
||||
"I expected something different.",
|
||||
"Todo!!!",
|
||||
"This is supposed to crash",
|
||||
"No changes after this point.",
|
||||
"I know, I know, this is not how I’m supposed to do it, but I can't think of something better.",
|
||||
"Don’t even try to refactor it.",
|
||||
"(c) Microsoft 1988",
|
||||
"Please no changes this time.",
|
||||
"Why The Fuck?",
|
||||
"We should delete this crap before shipping.",
|
||||
"Shit code!",
|
||||
"ALL SORTS OF THINGS",
|
||||
"Herpderp, shoulda check if it does really compile.",
|
||||
"I CAN HAZ PYTHON, I CAN HAZ INDENTS",
|
||||
"Major fixup.",
|
||||
"less french words",
|
||||
"breathe, =, breathe",
|
||||
"IEize",
|
||||
"this doesn't really make things faster, but I tried",
|
||||
"this should fix it",
|
||||
"forgot to save that file",
|
||||
"Glue. Match sticks. Paper. Build script!",
|
||||
"Argh! About to give up :(",
|
||||
"Blaming regex.",
|
||||
"oops",
|
||||
"it's friday",
|
||||
"yo recipes",
|
||||
"Not sure why",
|
||||
"lol digg",
|
||||
"grrrr",
|
||||
"For real, this time.",
|
||||
"Feed. You. Stuff. No time.",
|
||||
"I don't give a damn 'bout my reputation",
|
||||
"DEAL WITH IT",
|
||||
"commit",
|
||||
"tunning",
|
||||
"I really should've committed this when I finished it...",
|
||||
"It's getting hard to keep up with the crap I've trashed",
|
||||
"I honestly wish I could remember what was going on here...",
|
||||
"I must enjoy torturing myself",
|
||||
"For the sake of my sanity, just ignore this...",
|
||||
"That last commit message about silly mistakes pales in comparision to this one",
|
||||
"My bad",
|
||||
"Still can't get this right...",
|
||||
"Nitpicking about alphabetizing methods, minor OCD thing",
|
||||
"Committing fixes in the dark, seriously, who killed my power!?",
|
||||
"You can't see it, but I'm making a very angry face right now",
|
||||
"Fix the fixes",
|
||||
"It's secret!",
|
||||
"Commit committed....",
|
||||
"No time to commit.. My people need me!",
|
||||
"Something fixed",
|
||||
"I'm hungry",
|
||||
"asdfasdfasdfasdfasdfasdfadsf",
|
||||
"hmmm",
|
||||
"formatted all",
|
||||
"Replace all whitespaces with tabs.",
|
||||
"s/ / /g",
|
||||
"I'm too foo for this bar",
|
||||
"Things went wrong...",
|
||||
"??! what the ...",
|
||||
"This solves it.",
|
||||
"Working on tests (haha)",
|
||||
"fixed conflicts (LOL merge -s ours; push -f)",
|
||||
"last minute fixes.",
|
||||
"fuckup.",
|
||||
"Revert \"fuckup\".",
|
||||
"should work now.",
|
||||
"final commit.",
|
||||
"done. going to bed now.",
|
||||
"buenas those-things.",
|
||||
"Your commit is writing checks your merge can't cash.",
|
||||
"This branch is so dirty, even your mom can't clean it.",
|
||||
"wip",
|
||||
"Revert \"just testing, remember to revert\"",
|
||||
"bla",
|
||||
"harharhar",
|
||||
"restored deleted entities just to be sure",
|
||||
"added some filthy stuff",
|
||||
"bugger",
|
||||
"lol",
|
||||
"oopsie B|",
|
||||
"Copy pasta fail. still had a instead of a",
|
||||
"Now added delete for real",
|
||||
"grmbl",
|
||||
"move your body every every body",
|
||||
"Trying to fake a conflict",
|
||||
"And a commit that I don't know the reason of...",
|
||||
"ffs",
|
||||
"that's all folks",
|
||||
"Fucking submodule bull shit",
|
||||
"apparently i did something…",
|
||||
"bump to 0.0.3-dev:wq",
|
||||
"pep8 - cause I fell like doing a barrel roll",
|
||||
"pep8 fixer",
|
||||
"it is hump day _^_",
|
||||
"happy monday _ bleh _",
|
||||
"after of this commit remember do a git reset hard",
|
||||
"someday I gonna kill someone for this shit...",
|
||||
"magic, have no clue but it works",
|
||||
"I am sorry",
|
||||
"dirty hack, have a better idea ?",
|
||||
"Code was clean until manager requested to fuck it up",
|
||||
" - Temporary commit.",
|
||||
":(:(",
|
||||
"...",
|
||||
"GIT :/",
|
||||
"stopped caring 10 commits ago",
|
||||
"Testing in progress ;)",
|
||||
"Fixed Bug",
|
||||
"Fixed errors",
|
||||
"Push poorly written test can down the road another ten years",
|
||||
"commented out failing tests",
|
||||
"I'm human",
|
||||
"TODO: write meaningful commit message",
|
||||
"Pig",
|
||||
"SOAP is a piece of shit",
|
||||
"did everything",
|
||||
"project lead is allergic to changes...",
|
||||
"making this thing actually usable.",
|
||||
"I was told to leave it alone, but I have this thing called OCD, you see",
|
||||
"Whatever will be, will be 8{",
|
||||
"It's 2015; why are we using ColdFusion?!",
|
||||
"#GrammarNazi",
|
||||
"Future self, please forgive me and don't hit me with the baseball bat again!",
|
||||
"Hide those navs, boi!",
|
||||
"Who knows...",
|
||||
"Who knows WTF?!",
|
||||
"I should get a raise for this.",
|
||||
"Done, to whoever merges this, good luck.",
|
||||
"Not one conflict, today was a good day.",
|
||||
"First Blood",
|
||||
"Fixed the fuck out of #526!",
|
||||
"I'm too old for this shit!",
|
||||
"One little whitespace gets its very own commit! Oh, life is so erratic!"
|
||||
}
|
||||
|
||||
return PLUGIN
|
71
plugins/dice.lua
Normal file
71
plugins/dice.lua
Normal file
@ -0,0 +1,71 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!roll [range]
|
||||
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.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!roll'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
math.randomseed(os.time())
|
||||
|
||||
local input = get_input(msg.text)
|
||||
if not input then
|
||||
input = 6
|
||||
else
|
||||
input = string.upper(input)
|
||||
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, 'Invalid syntax.')
|
||||
end
|
||||
else
|
||||
return send_msg(msg, 'Invalid syntax.')
|
||||
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, 'Invalid syntax.')
|
||||
end
|
||||
|
||||
if tonumber(range) < 2 then
|
||||
return send_msg(msg, 'Invalid syntax.')
|
||||
end
|
||||
|
||||
if tonumber(rolls) > 100 then
|
||||
return send_msg(msg, 'Maximum dice is 100.')
|
||||
end
|
||||
|
||||
if tonumber(range) > 100000 then
|
||||
return send_msg(msg, 'Maximum range is 100000.')
|
||||
end
|
||||
|
||||
for i = 1, tonumber(rolls) do
|
||||
results = results .. math.random(range) .. '\t'
|
||||
end
|
||||
|
||||
send_msg(msg, results)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
||||
|
28
plugins/dogify.lua
Normal file
28
plugins/dogify.lua
Normal file
@ -0,0 +1,28 @@
|
||||
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, ' ', '')
|
||||
|
||||
url = 'http://dogr.io/' .. input .. '.png'
|
||||
|
||||
send_message(msg.chat.id, url, false, msg.message_id)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
23
plugins/echo.lua
Normal file
23
plugins/echo.lua
Normal file
@ -0,0 +1,23 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!echo <text>
|
||||
Repeat a string.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!echo'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
local input = get_input(msg.text)
|
||||
if not input then
|
||||
return send_msg(msg, PLUGIN.doc)
|
||||
end
|
||||
|
||||
send_msg(msg, latcyr(input))
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
22
plugins/fortune.lua
Normal file
22
plugins/fortune.lua
Normal file
@ -0,0 +1,22 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
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)
|
||||
end
|
||||
|
||||
return PLUGIN
|
67
plugins/gImages.lua
Normal file
67
plugins/gImages.lua
Normal file
@ -0,0 +1,67 @@
|
||||
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.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!images?',
|
||||
'^!img',
|
||||
'^!i ',
|
||||
'^!insfw'
|
||||
}
|
||||
|
||||
PLUGIN.exts = {
|
||||
'.png$',
|
||||
'.jpg$',
|
||||
'.jpeg$',
|
||||
'.jpe$',
|
||||
'.gif$'
|
||||
}
|
||||
|
||||
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'
|
||||
end
|
||||
|
||||
local input = get_input(msg.text)
|
||||
if not input then
|
||||
return send_msg(msg, PLUGIN.doc)
|
||||
end
|
||||
|
||||
url = url .. '&q=' .. URL.escape(input)
|
||||
|
||||
local jstr, res = HTTP.request(url)
|
||||
|
||||
if res ~= 200 then
|
||||
send_msg(target, 'Connection error.', ok_cb, false)
|
||||
return
|
||||
end
|
||||
|
||||
local jdat = JSON.decode(jstr)
|
||||
|
||||
if #jdat.responseData.results < 1 then
|
||||
send_msg(target, 'No results found.', ok_cb, false)
|
||||
return
|
||||
end
|
||||
|
||||
is_real = false
|
||||
while is_real == false do
|
||||
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
|
||||
|
||||
send_message(msg.chat.id, result_url, false, msg.message_id)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
40
plugins/gMaps.lua
Normal file
40
plugins/gMaps.lua
Normal file
@ -0,0 +1,40 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!loc <location>
|
||||
Sends location data for query, taken from Google Maps. Works for countries, cities, landmarks, etc.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!loc'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
local input = get_input(msg.text)
|
||||
if not input then
|
||||
return send_msg(msg, PLUGIN.doc)
|
||||
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, 'Connection error.')
|
||||
end
|
||||
|
||||
local jdat = JSON.decode(jstr)
|
||||
|
||||
if jdat.status ~= 'OK' then
|
||||
local message = 'Error: \"' .. input .. '\" not found.'
|
||||
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)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
||||
|
57
plugins/gSearch.lua
Normal file
57
plugins/gSearch.lua
Normal file
@ -0,0 +1,57 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.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.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!g ',
|
||||
'^!google',
|
||||
'^!gnsfw'
|
||||
}
|
||||
|
||||
function PLUGIN.action(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)
|
||||
if not input then
|
||||
return send_msg(msg, PLUGIN.doc)
|
||||
end
|
||||
|
||||
url = url .. '&q=' .. URL.escape(input)
|
||||
|
||||
local jstr, res = HTTP.request(url)
|
||||
|
||||
if res ~= 200 then
|
||||
return send_msg(msg, 'Connection error.')
|
||||
end
|
||||
|
||||
local jdat = JSON.decode(jstr)
|
||||
|
||||
if #jdat.responseData.results < 1 then
|
||||
return send_msg(msg, 'No results found.')
|
||||
end
|
||||
|
||||
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'
|
||||
end
|
||||
|
||||
send_msg(msg, message)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
53
plugins/giphy.lua
Normal file
53
plugins/giphy.lua
Normal file
@ -0,0 +1,53 @@
|
||||
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.
|
||||
]]
|
||||
|
||||
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, 'Connection error.')
|
||||
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, 'Connection error.')
|
||||
end
|
||||
local jdat = JSON.decode(jstr)
|
||||
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
|
35
plugins/hackernews.lua
Normal file
35
plugins/hackernews.lua
Normal file
@ -0,0 +1,35 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!hackernews
|
||||
Returns some top stories from Hacker News. Four in a group or eight in a private message.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!hackernews',
|
||||
'^!hn$'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
38
plugins/help.lua
Normal file
38
plugins/help.lua
Normal file
@ -0,0 +1,38 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!help [command]
|
||||
Get list of basic information for all commands, or more detailed documentation on a specified command.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!help',
|
||||
'^!h$'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
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
|
||||
|
||||
if msg.from.id ~= msg.chat.id then
|
||||
if not send_message(msg.from.id, help_message, true, msg.message_id) then
|
||||
return send_msg(msg, help_message) -- Unable to PM user who hasn't PM'd first.
|
||||
end
|
||||
return send_msg(msg, 'I have sent you the requested information in a private message.')
|
||||
else
|
||||
return send_msg(msg, help_message)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
29
plugins/hex.lua
Normal file
29
plugins/hex.lua
Normal file
@ -0,0 +1,29 @@
|
||||
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, 'Invalid number.')
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
40
plugins/imdb.lua
Normal file
40
plugins/imdb.lua
Normal file
@ -0,0 +1,40 @@
|
||||
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.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!imdb'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
local input = get_input(msg.text)
|
||||
if not input then
|
||||
return send_msg(msg, PLUGIN.doc)
|
||||
end
|
||||
|
||||
local url = 'http://www.imdbapi.com/?t=' .. URL.escape(input)
|
||||
local jstr, res = HTTP.request(url)
|
||||
local jdat = JSON.decode(jstr)
|
||||
|
||||
if res ~= 200 then
|
||||
return send_msg(msg, 'Error connecting to server.')
|
||||
end
|
||||
|
||||
if jdat.Response ~= 'True' then
|
||||
return send_msg(msg, jdat.Error)
|
||||
end
|
||||
|
||||
local message = jdat.Title ..' ('.. jdat.Year ..')\n'
|
||||
message = message .. jdat.imdbRating ..' | '.. jdat.Runtime ..' | '.. jdat.Genre ..'\n'
|
||||
message = message .. jdat.Plot .. '\n'
|
||||
message = message .. 'http://imdb.com/title/' .. jdat.imdbID
|
||||
|
||||
send_msg(msg, message)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
38
plugins/personality.lua
Normal file
38
plugins/personality.lua
Normal file
@ -0,0 +1,38 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'otouto%p?$',
|
||||
'^tadaima%p?$',
|
||||
'^i\'m home%p?$',
|
||||
'^i\'m back%p?$'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg) -- I WISH LUA HAD PROPER REGEX SUPPORT
|
||||
|
||||
local input = string.lower(msg.text)
|
||||
|
||||
for i = 2, #PLUGIN.triggers do
|
||||
if string.match(input, PLUGIN.triggers[i]) then
|
||||
return send_message(msg.chat.id, 'Welcome back, ' .. msg.from.first_name .. '!')
|
||||
end
|
||||
end
|
||||
|
||||
if input:match('thanks,? otouto') or input:match('thank you,? otouto') then
|
||||
return send_message(msg.chat.id, 'No problem, ' .. msg.from.first_name .. '!')
|
||||
end
|
||||
|
||||
if input:match('hello,? otouto') or input:match('hey,? otouto') or input:match('hi,? otouto') then
|
||||
return send_message(msg.chat.id, 'Hi, ' .. msg.from.first_name .. '!')
|
||||
end
|
||||
|
||||
if input:match('i hate you,? otouto') or input:match('screw you,? otouto') or input:match('fuck you,? otouto') then
|
||||
return send_msg(msg, '; _ ;')
|
||||
end
|
||||
|
||||
if string.match(input, 'i love you,? otouto') then
|
||||
return send_msg(msg, '<3')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
57
plugins/pokedex.lua
Normal file
57
plugins/pokedex.lua
Normal file
@ -0,0 +1,57 @@
|
||||
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.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!dex'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
local input = get_input(msg.text)
|
||||
if not input then
|
||||
return send_msg(msg, PLUGIN.doc)
|
||||
end
|
||||
|
||||
local base_url = 'http://pokeapi.co'
|
||||
local poke_type = nil
|
||||
|
||||
local dex_url = base_url .. '/api/v1/pokemon/' .. input
|
||||
local dex_jstr, res = HTTP.request(dex_url)
|
||||
if res ~= 200 then
|
||||
return send_msg(msg, 'Pokemon not found..')
|
||||
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_jstr, res = HTTP.request(desc_url)
|
||||
if res ~= 200 then
|
||||
return send_msg(msg, 'Connection error.')
|
||||
end
|
||||
|
||||
local desc_jdat = JSON.decode(desc_jstr)
|
||||
|
||||
for k,v in pairs(dex_jdat.types) do
|
||||
local type_name = v.name:gsub("^%l", string.upper)
|
||||
if not poke_type then
|
||||
poke_type = type_name
|
||||
else
|
||||
poke_type = poke_type .. ' / ' .. type_name
|
||||
end
|
||||
end
|
||||
poke_type = poke_type .. ' type'
|
||||
|
||||
local info_line = 'Height: ' .. dex_jdat.height/10 .. 'm, Weight: ' .. dex_jdat.weight/10 .. 'kg'
|
||||
|
||||
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)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
142
plugins/pun.lua
Normal file
142
plugins/pun.lua
Normal file
@ -0,0 +1,142 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!pun
|
||||
Get a random pun.
|
||||
Have a recommendation? PM @topkecleon.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!pun'
|
||||
}
|
||||
|
||||
PLUGIN.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.",
|
||||
"Singing in the shower is all fun and games until you get shampoo in your mouth - Then it becomes a soap opera.",
|
||||
"I can't believe I got fired from the calendar factory. All I did was take a day off.",
|
||||
"To the guy who invented zero: Thanks for nothing!",
|
||||
"Enough with the cripple jokes! I just can't stand them.",
|
||||
"I've accidentally swallowed some Scrabble tiles. My next crap could spell disaster.",
|
||||
"How does Moses make his tea? Hebrews it.",
|
||||
"Did you hear about the guy who got hit in the head with a can of soda? He was lucky it was a soft drink.",
|
||||
"When William joined the army he disliked the phrase 'fire at will'.",
|
||||
"There was a sign on the lawn at a rehab center that said 'Keep off the Grass'.",
|
||||
"I wondered why the baseball was getting bigger. Then it hit me.",
|
||||
"I can hear music coming out of my printer. I think the paper's jamming again.",
|
||||
"I have a few jokes about unemployed people, but none of them work",
|
||||
"Want to hear a construction joke? I'm working on it",
|
||||
"I always take a second pair of pants when I go golfing, in case I get a hole in one.",
|
||||
"I couldn't remember how to throw a boomerang, but then it came back to me.",
|
||||
"I've decided that my wifi will be my valentine. IDK, we just have this connection.",
|
||||
"A prisoner's favorite punctuation mark is the period. It marks the end of his sentence.",
|
||||
"I used to go fishing with Skrillex, but he kept dropping the bass.",
|
||||
"Two antennae met on a roof and got married. The wedding was okay, but the reception was incredible.",
|
||||
"A book just fell on my head. I've only got my shelf to blame.",
|
||||
"I dropped my steak on the floor. Now it's ground beef.",
|
||||
"I used to have a fear of hurdles, but I got over it.",
|
||||
"The outcome of war does not prove who is right, but only who is left.",
|
||||
"Darth Vader tries not to burn his food, but it always comes out a little on the dark side.",
|
||||
"The store keeps calling me to buy more furniture, but all I wanted was a one night stand.",
|
||||
"This girl said she recognized me from the vegetarian club, but I'd never met herbivore.",
|
||||
"Police arrested two kids yesterday, one was drinking battery acid, the other was eating fireworks. They charged one and let the other one off...",
|
||||
"No more Harry Potter jokes guys. I'm Sirius.",
|
||||
"It was hard getting over my addiction to hokey pokey, but I've turned myself around.",
|
||||
"It takes a lot of balls to golf the way I do.",
|
||||
"Why did everyone want to hang out with the mushroom? Because he was a fungi.",
|
||||
"How much does a hipster weigh? An instagram.",
|
||||
"I used to be addicted to soap, but I'm clean now.",
|
||||
"When life gives you melons, you’re probably dyslexic.",
|
||||
"What's with all the blind jokes? I just don't see the point.",
|
||||
"If Apple made a car, would it have Windows?",
|
||||
"Need an ark? I Noah guy.",
|
||||
"The scarecrow won an award because he was outstanding in his field.",
|
||||
"What's the difference between a man in a tux on a bicycle, and a man in a sweatsuit on a trycicle? A tire.",
|
||||
"What do you do with a sick chemist? If you can't helium, and you can't curium, you'll just have to barium.",
|
||||
"I'm reading a book about anti-gravity. It's impossible to put down.",
|
||||
"Trying to write with a broken pencil is pointless.",
|
||||
"When TVs go on vacation, they travel to remote islands.",
|
||||
"I was going to tell a midget joke, but it's too short.",
|
||||
"Jokes about German sausage are the wurst.",
|
||||
"How do you organize a space party? You planet.",
|
||||
"Sleeping comes so naturally to me, I could do it with my eyes closed.",
|
||||
"I'm glad I know sign language; it's pretty handy.",
|
||||
"Atheism is a non-prophet organization.",
|
||||
"Velcro: What a rip-off!",
|
||||
"If they made a Minecraft movie, it would be a blockbuster.",
|
||||
"I don't trust people with graph paper. They're always plotting something",
|
||||
"I had a friend who was addicted to brake fluid. He says he can stop anytime.",
|
||||
"The form said I had Type A blood, but it was a Type O.",
|
||||
"I went to to the shop to buy eight Sprites - I came home and realised I'd picked 7Up.",
|
||||
"There was an explosion at a pie factory. 3.14 people died.",
|
||||
"A man drove his car into a tree and found out how a Mercedes bends.",
|
||||
"The experienced carpenter really nailed it, but the new guy screwed everything up.",
|
||||
"I didn't like my beard at first, but then it grew on me.",
|
||||
"Smaller babies may be delivered by stork, but the heavier ones need a crane.",
|
||||
"What's the definition of a will? It's a dead giveaway.",
|
||||
"I was going to look for my missing watch, but I could never find the time.",
|
||||
"I hate elevators, and I often take steps to avoid them.",
|
||||
"Did you hear about the guy whose whole left side was cut off? He's all right now.",
|
||||
"It's not that the man did not know how to juggle, he just didn't have the balls to do it.",
|
||||
"I used to be a loan shark, but I lost interest",
|
||||
"I don't trust these stairs; they're always up to something.",
|
||||
"My friend's bakery burned down last night. Now his business is toast.",
|
||||
"Don't trust people that do acupuncture; they're back stabbers.",
|
||||
"The man who survived mustard gas and pepper spray is now a seasoned veteran.",
|
||||
"Police were called to a daycare where a three-year-old was resisting a rest.",
|
||||
"When Peter Pan punches, they Neverland",
|
||||
"The shoemaker did not deny his apprentice anything he needed. He gave him his awl.",
|
||||
"I did a theatrical performance about puns. It was a play on words.",
|
||||
"Show me a piano falling down a mineshaft and I'll show you A-flat minor.",
|
||||
"Have you ever tried to eat a clock? It's very time consuming.",
|
||||
"There was once a cross-eyed teacher who couldn't control his pupils.",
|
||||
"A new type of broom came out and it is sweeping the nation.",
|
||||
"I relish the fact that you've mustard the strength to ketchup to me.",
|
||||
"I knew a woman who owned a taser. Man, was she stunning!",
|
||||
"What did the grape say when it got stepped on? Nothing - but it let out a little whine.",
|
||||
"It was an emotional wedding. Even the cake was in tiers.",
|
||||
"When a clock is hungry it goes back four seconds.",
|
||||
"The dead batteries were given out free of charge.",
|
||||
"Why are there no knock-knock jokes about America? Because freedom rings.",
|
||||
"When the cannibal showed up late to dinner, they gave him the cold shoulder.",
|
||||
"I should have been sad when my flashlight died, but I was delighted.",
|
||||
"Why don't tennis players ever get marries? Love means nothing to them.",
|
||||
"Pterodactyls can't be heard going to the bathroom because the P is silent.",
|
||||
"Mermaids make calls on their shell phones.",
|
||||
"What do you call an aardvark with three feet? A yaardvark.",
|
||||
"Captain Kirk has three ears: A right ear, a left ear, and a final front ear.",
|
||||
"How do celebrities stay cool? They have a lot of fans.",
|
||||
"Without geometry, life is pointless.",
|
||||
"Did you hear about the cow who tried to jump over a barbed-wire fence? It ended in udder destruction.",
|
||||
"The truth may ring like a bell, but it is seldom ever tolled.",
|
||||
"I used to work for the IRS, but my job was too taxing.",
|
||||
"I used to be a programmer, but then I lost my drive.",
|
||||
"Pediatricians are doctors with little patients.",
|
||||
"I finally fired my masseuse today. She always rubbed me the wrong way.",
|
||||
"I stayed up all night wondering where the sun went. Then it dawned on me.",
|
||||
"What's the difference between a man and his dog? The man wears a suit; the dog just pants.",
|
||||
"A psychic midget who escapes from prison is a small medium at large.",
|
||||
"I've been to the dentist several times, so I know the drill.",
|
||||
"The roundest knight at King Arthur's round table was Sir Cumference. He acquired his size from too much pi.",
|
||||
"She was only a whiskey maker, but he loved her still.",
|
||||
"Male deer have buck teeth.",
|
||||
"Whiteboards are remarkable.",
|
||||
"Visitors in Cuba are always Havana good time.",
|
||||
"Why does electricity shock people? It doesn't know how to conduct itself.",
|
||||
"Lancelot had a scary dream about his horse. It was a knight mare.",
|
||||
"A tribe of cannibals caught a missionary and ate him. Afterward, they all had violent food poisoning. This just goes to show that you can't keep a good man down.",
|
||||
"Heaven for gamblers is a paradise.",
|
||||
"Old wheels aren't thrown away, they're just retired.",
|
||||
"Horses are very stable animals.",
|
||||
"Banks don't crash, they just lose their balance.",
|
||||
"The career of a skier can go downhill very fast.",
|
||||
"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)])
|
||||
end
|
||||
|
||||
return PLUGIN
|
84
plugins/reddit.lua
Normal file
84
plugins/reddit.lua
Normal file
@ -0,0 +1,84 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!reddit [r/subreddit | query]
|
||||
This command returns top results for a given query or subreddit. NSFW posts are marked as such.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!reddit',
|
||||
'^!r$',
|
||||
'^!r '
|
||||
}
|
||||
|
||||
function PLUGIN.action(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, 'Connection error.')
|
||||
end
|
||||
jdat = JSON.decode(jstr)
|
||||
if #jdat.data.children == 0 then
|
||||
return send_msg(msg, 'Subreddit not found.')
|
||||
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, 'Connection error.')
|
||||
end
|
||||
jdat = JSON.decode(jstr)
|
||||
if #jdat.data.children == 0 then
|
||||
return send_msg(msg, 'No results found.')
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
else
|
||||
|
||||
url = 'https://www.reddit.com/.json'
|
||||
local jstr, res = HTTP.request(url)
|
||||
if res ~= 200 then
|
||||
return send_msg(msg, 'Connection error.')
|
||||
end
|
||||
jdat = JSON.decode(jstr)
|
||||
|
||||
end
|
||||
|
||||
local limit = 4
|
||||
if #jdat.data.children < limit then
|
||||
limit = #jdat.data.children
|
||||
end
|
||||
|
||||
for i = 1, limit do
|
||||
|
||||
if jdat.data.children[i].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'
|
||||
end
|
||||
|
||||
local short_url = '[redd.it/' .. jdat.data.children[i].data.id .. '] '
|
||||
message = message .. short_url .. jdat.data.children[i].data.title .. url
|
||||
|
||||
end
|
||||
|
||||
send_msg(msg, message)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
55
plugins/remind.lua
Normal file
55
plugins/remind.lua
Normal file
@ -0,0 +1,55 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!remind <delay> <message>
|
||||
Set a reminder for yourself. First argument is the number of minutes until you wish to be reminded.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!remind$',
|
||||
'^!remind '
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
local input = get_input(msg.text)
|
||||
if not input then
|
||||
return send_msg(msg, PLUGIN.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) -- this is gross
|
||||
if msg.from.username then
|
||||
text = text .. '\n@' .. msg.from.username
|
||||
end
|
||||
|
||||
local delay = tonumber(delay)
|
||||
|
||||
local reminder = {
|
||||
alarm = os.time() + (delay * 60),
|
||||
chat_id = msg.chat.id,
|
||||
text = text
|
||||
}
|
||||
|
||||
table.insert(reminders, reminder)
|
||||
|
||||
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
|
||||
|
||||
return PLUGIN
|
12
plugins/shrug.lua
Normal file
12
plugins/shrug.lua
Normal file
@ -0,0 +1,12 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!shrug',
|
||||
'/shrug'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
send_msg(msg, '¯\\_(ツ)_/¯')
|
||||
end
|
||||
|
||||
return PLUGIN
|
116
plugins/slap.lua
Normal file
116
plugins/slap.lua
Normal file
@ -0,0 +1,116 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!slap [victim]
|
||||
Slap someone!
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!slap'
|
||||
}
|
||||
|
||||
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 by " .. slapper .. ".",
|
||||
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 .. " 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
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
math.randomseed(os.time())
|
||||
|
||||
local victim = get_input(msg.text)
|
||||
if victim then
|
||||
slapper = msg.from.first_name
|
||||
else
|
||||
victim = msg.from.first_name
|
||||
slapper = 'otouto'
|
||||
end
|
||||
|
||||
local message = PLUGIN.getSlap(slapper, victim)
|
||||
send_message(target, message)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
41
plugins/time.lua
Normal file
41
plugins/time.lua
Normal file
@ -0,0 +1,41 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!time <location>
|
||||
Sends the time and timezone for a given location.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!time'
|
||||
}
|
||||
|
||||
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
|
||||
local message = 'Error: \"' .. input .. '\" not found.'
|
||||
return send_msg(msg, message)
|
||||
end
|
||||
|
||||
local url = 'http://maps.googleapis.com/maps/api/timezone/json?location=' .. coords.lat ..','.. coords.lon .. '×tamp='..os.time()
|
||||
local jstr, res = HTTPS.request(url)
|
||||
if res ~= 200 then
|
||||
return send_msg(msg, 'Connection error.')
|
||||
end
|
||||
local jdat = JSON.decode(jstr)
|
||||
|
||||
local timestamp = os.time() + jdat.rawOffset + jdat.dstOffset + config.TIME_OFFSET
|
||||
timestamp = os.date("%H:%M on %A, %B %d.", timestamp)
|
||||
local timeloc = (string.gsub((string.sub(jdat.timeZoneId, string.find(jdat.timeZoneId, '/')+1)), '_', ' '))
|
||||
local message = "The time in " .. timeloc .. " is " .. timestamp
|
||||
|
||||
send_msg(msg, message)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
42
plugins/urbandictionary.lua
Normal file
42
plugins/urbandictionary.lua
Normal file
@ -0,0 +1,42 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!ud <term>
|
||||
Returns the first definition for a given term from Urban Dictionary.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!ud',
|
||||
'^!urbandictionary'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
local input = get_input(msg.text)
|
||||
if not input then
|
||||
return send_msg(msg, PLUGIN.doc)
|
||||
end
|
||||
|
||||
local url = 'http://api.urbandictionary.com/v0/define?term=' .. URL.escape(input)
|
||||
local jstr, res = HTTP.request(url)
|
||||
|
||||
if res ~= 200 then
|
||||
return send_msg(msg, 'Connection error.')
|
||||
end
|
||||
|
||||
local jdat = JSON.decode(jstr)
|
||||
|
||||
if jdat.result_type == "no_results" then
|
||||
return send_msg(msg, 'No results found.')
|
||||
end
|
||||
|
||||
message = '"' .. jdat.list[1].word .. '"\n' .. trim_string(jdat.list[1].definition)
|
||||
if string.len(jdat.list[1].example) > 0 then
|
||||
message = message .. '\n\nExample:\n' .. trim_string(jdat.list[1].example)
|
||||
end
|
||||
|
||||
send_msg(msg, message)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
41
plugins/weather.lua
Normal file
41
plugins/weather.lua
Normal file
@ -0,0 +1,41 @@
|
||||
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
|
||||
local message = 'Error: \"' .. input .. '\" not found.'
|
||||
return send_msg(msg, message)
|
||||
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, 'Connection error.')
|
||||
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 = jdat.name .. ': ' .. celsius .. '°C / ' .. fahrenheit .. '°F, ' .. jdat.weather[1].description .. '.'
|
||||
|
||||
send_msg(msg, message)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
37
plugins/whoami.lua
Normal file
37
plugins/whoami.lua
Normal file
@ -0,0 +1,37 @@
|
||||
local PLUGIN = {}
|
||||
|
||||
PLUGIN.doc = [[
|
||||
!whoami
|
||||
Get the user ID for yourself and the group.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!whoami',
|
||||
'^!ping',
|
||||
'^/ping'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
local from_name = msg.from.first_name
|
||||
if msg.from.last_name then
|
||||
from_name = from_name .. ' ' .. msg.from.last_name
|
||||
end
|
||||
if msg.from.username then
|
||||
from_name = '@' .. msg.from.username .. ', AKA ' .. from_name
|
||||
end
|
||||
from_name = from_name .. ' (' .. msg.from.id .. ')'
|
||||
|
||||
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 message = 'You are ' .. from_name .. ' and you are messaging ' .. to_name .. '.'
|
||||
|
||||
send_msg(msg, message)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
47
plugins/xkcd.lua
Normal file
47
plugins/xkcd.lua
Normal file
@ -0,0 +1,47 @@
|
||||
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.
|
||||
]]
|
||||
|
||||
PLUGIN.triggers = {
|
||||
'^!xkcd'
|
||||
}
|
||||
|
||||
function PLUGIN.action(msg)
|
||||
|
||||
local input = get_input(msg.text)
|
||||
local url = 'http://xkcd.com/info.0.json'
|
||||
local jstr, res = HTTP.request(url)
|
||||
if res ~= 200 then
|
||||
return send_msg(msg, 'Connection error.')
|
||||
end
|
||||
local latest = JSON.decode(jstr).num
|
||||
|
||||
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)
|
||||
if res ~= 200 then
|
||||
print('here')
|
||||
return send_msg(msg, 'Connection error.')
|
||||
end
|
||||
url = JSON.decode(jstr).responseData.results[1].url .. 'info.0.json'
|
||||
else
|
||||
math.randomseed(os.time())
|
||||
url = 'http://xkcd.com/' .. math.random(latest) .. '/info.0.json'
|
||||
end
|
||||
|
||||
local jstr, res = HTTP.request(url)
|
||||
if res ~= 200 then
|
||||
return send_msg(msg, 'Connection error.')
|
||||
end
|
||||
local jdat = JSON.decode(jstr)
|
||||
|
||||
local message = '[' .. jdat.num .. '] ' .. jdat.alt .. '\n' .. jdat.img
|
||||
|
||||
send_message(msg.chat.id, message, false, msg.message_id)
|
||||
|
||||
end
|
||||
|
||||
return PLUGIN
|
84
utilities.lua
Normal file
84
utilities.lua
Normal file
@ -0,0 +1,84 @@
|
||||
-- utilities.lua
|
||||
-- Functions shared among plugins.
|
||||
|
||||
function first_word(str, idx) -- get the indexed word in a string
|
||||
str = string.gsub(str, '\n', ' ')
|
||||
if not string.find(str, ' ') then return str end
|
||||
str = str .. ' '
|
||||
if not idx then idx = 1 end
|
||||
if idx ~= 1 then
|
||||
for i = 2, idx do
|
||||
str = string.sub(str, string.find(str, ' ') + 1)
|
||||
end
|
||||
end
|
||||
str = string.sub(str, 1, string.find(str, ' '))
|
||||
return string.sub(str, 1, -2)
|
||||
end
|
||||
|
||||
function get_input(text) -- returns string or false
|
||||
if not string.find(text, ' ') then
|
||||
return false
|
||||
end
|
||||
return string.sub(text, string.find(text, ' ')+1)
|
||||
end
|
||||
|
||||
function trim_string(text) -- another alias
|
||||
return string.gsub(text, "^%s*(.-)%s*$", "%1")
|
||||
end
|
||||
|
||||
local lc_list = {
|
||||
-- Latin = 'Cyrillic'
|
||||
['A'] = 'А',
|
||||
['B'] = 'В',
|
||||
['C'] = 'С',
|
||||
['E'] = 'Е',
|
||||
['I'] = 'І',
|
||||
['J'] = 'Ј',
|
||||
['K'] = 'К',
|
||||
['M'] = 'М',
|
||||
['H'] = 'Н',
|
||||
['O'] = 'О',
|
||||
['P'] = 'Р',
|
||||
['S'] = 'Ѕ',
|
||||
['T'] = 'Т',
|
||||
['X'] = 'Х',
|
||||
['Y'] = 'Ү',
|
||||
['a'] = 'а',
|
||||
['c'] = 'с',
|
||||
['e'] = 'е',
|
||||
['i'] = 'і',
|
||||
['j'] = 'ј',
|
||||
['o'] = 'о',
|
||||
['s'] = 'ѕ',
|
||||
['x'] = 'х',
|
||||
['y'] = 'у',
|
||||
['!'] = 'ǃ'
|
||||
}
|
||||
|
||||
function latcyr(str)
|
||||
for k,v in pairs(lc_list) do
|
||||
str = string.gsub(str, k, v)
|
||||
end
|
||||
return str
|
||||
end
|
||||
|
||||
function send_msg(msg, message)
|
||||
send_message(msg.chat.id, message, true, msg.message_id)
|
||||
end
|
||||
|
||||
function get_coords(input)
|
||||
|
||||
local url = 'http://maps.googleapis.com/maps/api/geocode/json?address=' .. URL.escape(input)
|
||||
local jstr, res = HTTP.request(url)
|
||||
if res ~= 200 then
|
||||
return false
|
||||
end
|
||||
|
||||
local jdat = JSON.decode(jstr)
|
||||
if jdat.status == 'ZERO_RESULTS' then
|
||||
return false
|
||||
end
|
||||
|
||||
return { lat = jdat.results[1].geometry.location.lat, lon = jdat.results[1].geometry.location.lng }
|
||||
|
||||
end
|
Reference in New Issue
Block a user