Begin library-friendly structuring

This commit is contained in:
Brayden Banks
2016-05-26 09:32:40 -07:00
parent 732b55369a
commit c51fbedb7b
53 changed files with 1 additions and 1 deletions

View File

@@ -1,33 +0,0 @@
local about = {}
local bot = require('bot')
local utilities = require('utilities')
about.command = 'about'
about.doc = '`Returns information about the bot.`'
about.triggers = {
''
}
function about:action(msg, config)
-- Filthy hack, but here is where we'll stop forwarded messages from hitting
-- other plugins.
if msg.forward_from then return end
local output = config.about_text .. '\nBased on otouto v'..bot.version..' by topkecleon.'
if (msg.new_chat_participant and msg.new_chat_participant.id == self.info.id)
or msg.text_lower:match('^'..config.cmd_pat..'about')
or msg.text_lower:match('^'..config.cmd_pat..'about@'..self.info.username:lower())
or msg.text_lower:match('^'..config.cmd_pat..'start') then
utilities.send_message(self, msg.chat.id, output, true)
return
end
return true
end
return about

File diff suppressed because it is too large Load Diff

View File

@@ -1,87 +0,0 @@
-- Credit to Heitor (tg:Wololo666; gh:heitorPB) for this plugin.
local apod = {}
local HTTPS = require('ssl.https')
local JSON = require('dkjson')
local URL = require('socket.url')
local utilities = require('utilities')
apod.command = 'apod [date]'
function apod:init(config)
apod.triggers = utilities.triggers(self.info.username, config.cmd_pat)
:t('apod', true):t('apodhd', true):t('apodtext', true).table
apod.doc = [[```
]]..config.cmd_pat..[[apod [query]
Returns the Astronomy Picture of the Day.
If the query is a date, in the format YYYY-MM-DD, the APOD of that day is returned.
]]..config.cmd_pat..[[apodhd [query]
Returns the image in HD, if available.
]]..config.cmd_pat..[[apodtext [query]
Returns the explanation of the APOD.
Source: nasa.gov
```]]
end
function apod:action(msg, config)
if not config.nasa_api_key then
config.nasa_api_key = 'DEMO_KEY'
end
local input = utilities.input(msg.text)
local date = '*'
local disable_page_preview = false
local url = 'https://api.nasa.gov/planetary/apod?api_key=' .. config.nasa_api_key
if input then
if input:match('(%d+)%-(%d+)%-(%d+)$') then
url = url .. '&date=' .. URL.escape(input)
date = date .. input
else
utilities.send_message(self, msg.chat.id, apod.doc, true, msg.message_id, true)
return
end
else
date = date .. os.date("%F")
end
date = date .. '*\n'
local jstr, res = HTTPS.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if jdat.error then
utilities.send_reply(self, msg, config.errors.results)
return
end
local img_url = jdat.url
if string.match(msg.text, '^'..config.cmd_pat..'apodhd*') then
img_url = jdat.hdurl or jdat.url
end
local output = date .. '[' .. jdat.title .. '](' .. img_url .. ')'
if string.match(msg.text, '^'..config.cmd_pat..'apodtext*') then
output = output .. '\n' .. jdat.explanation
disable_page_preview = true
end
if jdat.copyright then
output = output .. '\nCopyright: ' .. jdat.copyright
end
utilities.send_message(self, msg.chat.id, output, disable_page_preview, nil, true)
end
return apod

View File

@@ -1,35 +0,0 @@
local bandersnatch = {}
local utilities = require('utilities')
bandersnatch.command = 'bandersnatch'
function bandersnatch:init(config)
bandersnatch.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('bandersnatch'):t('bc').table
bandersnatch.doc = [[```
Shun the frumious Bandersnatch.
Alias: ]]..config.cmd_pat..[[bc
```]]
end
local fullnames = { "Wimbledon Tennismatch", "Rinkydink Curdlesnoot", "Butawhiteboy Cantbekhan", "Benadryl Claritin", "Bombadil Rivendell", "Wanda's Crotchfruit", "Biblical Concubine", "Syphilis Cankersore", "Buckminster Fullerene", "Bourgeoisie Capitalist" }
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" }
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 bandersnatch:action(msg)
local output
if math.random(10) == 10 then
output = fullnames[math.random(#fullnames)]
else
output = firstnames[math.random(#firstnames)] .. ' ' .. lastnames[math.random(#lastnames)]
end
utilities.send_message(self, msg.chat.id, '_'..output..'_', true, nil, true)
end
return bandersnatch

View File

@@ -1,53 +0,0 @@
local bible = {}
local HTTP = require('socket.http')
local URL = require('socket.url')
local utilities = require('utilities')
function bible:init(config)
if not config.biblia_api_key then
print('Missing config value: biblia_api_key.')
print('bible.lua will not be enabled.')
return
end
bible.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('bible', true):t('b', true).table
bible.doc = [[```
]]..config.cmd_pat..[[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.
Alias: ]]..config.cmd_pat..[[b
```]]
end
bible.command = 'bible <reference>'
function bible:action(msg, config)
local input = utilities.input(msg.text)
if not input then
utilities.send_message(self, msg.chat.id, bible.doc, true, msg.message_id, true)
return
end
local url = 'http://api.biblia.com/v1/bible/content/ASV.txt?key=' .. config.biblia_api_key .. '&passage=' .. URL.escape(input)
local output, res = HTTP.request(url)
if not output or res ~= 200 or output:len() == 0 then
url = 'http://api.biblia.com/v1/bible/content/KJVAPOC.txt?key=' .. config.biblia_api_key .. '&passage=' .. URL.escape(input)
output, res = HTTP.request(url)
end
if not output or res ~= 200 or output:len() == 0 then
output = config.errors.results
end
if output:len() > 4000 then
output = 'The text is too long to post here. Try being more specific.'
end
utilities.send_reply(self, msg, output)
end
return bible

View File

@@ -1,45 +0,0 @@
-- 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 blacklist = {}
local utilities = require('utilities')
function blacklist:init()
if not self.database.blacklist then
self.database.blacklist = {}
end
end
blacklist.triggers = {
''
}
function blacklist:action(msg, config)
if self.database.blacklist[msg.from.id_str] then return end
if self.database.blacklist[msg.chat.id_str] then return end
if not msg.text:match('^'..config.cmd_pat..'blacklist') then return true end
if msg.from.id ~= config.admin then return end
local target = utilities.user_from_message(self, msg)
if target.err then
utilities.send_reply(self, msg, target.err)
return
end
if tonumber(target.id) < 0 then
target.name = 'Group'
end
if self.database.blacklist[tostring(target.id)] then
self.database.blacklist[tostring(target.id)] = nil
utilities.send_reply(self, msg, target.name .. ' has been removed from the blacklist.')
else
self.database.blacklist[tostring(target.id)] = true
utilities.send_reply(self, msg, target.name .. ' has been added to the blacklist.')
end
end
return blacklist

View File

@@ -1,43 +0,0 @@
local calc = {}
local URL = require('socket.url')
local HTTPS = require('ssl.https')
local utilities = require('utilities')
calc.command = 'calc <expression>'
function calc:init(config)
calc.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('calc', true).table
calc.doc = [[```
]]..config.cmd_pat..[[calc <expression>
Returns solutions to mathematical expressions and conversions between common units. Results provided by mathjs.org.
```]]
end
function calc:action(msg, config)
local input = utilities.input(msg.text)
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
utilities.send_message(self, msg.chat.id, calc.doc, true, msg.message_id, true)
return
end
end
local url = 'https://api.mathjs.org/v1/?expr=' .. URL.escape(input)
local output = HTTPS.request(url)
if not output then
utilities.send_reply(self, msg, config.errors.connection)
return
end
output = '`' .. output .. '`'
utilities.send_message(self, msg.chat.id, output, true, msg.message_id, true)
end
return calc

View File

@@ -1,38 +0,0 @@
local cats = {}
local HTTP = require('socket.http')
local utilities = require('utilities')
function cats:init(config)
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
cats.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('cat').table
end
cats.command = 'cat'
cats.doc = '`Returns a cat!`'
function cats:action(msg, config)
local url = 'http://thecatapi.com/api/images/get?format=html&type=jpg'
if config.thecatapi_key then
url = url .. '&api_key=' .. config.thecatapi_key
end
local str, res = HTTP.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, onfig.errors.connection)
return
end
str = str:match('<img src="(.-)">')
local output = '[Cat!]('..str..')'
utilities.send_message(self, msg.chat.id, output, false, nil, true)
end
return cats

View File

@@ -1,79 +0,0 @@
-- Put this absolutely at the end, even after greetings.lua.
local chatter = {}
local HTTP = require('socket.http')
local URL = require('socket.url')
local JSON = require('dkjson')
local bindings = require('bindings')
function chatter:init(config)
if not config.simsimi_key then
print('Missing config value: simsimi_key.')
print('chatter.lua will not be enabled.')
return
end
chatter.triggers = {
''
}
end
chatter.base_url = 'http://%sapi.simsimi.com/request.p?key=%s&lc=%s&ft=1.0&text=%s'
function chatter:action(msg, config)
if msg.text == '' then return true end
if (
not (
msg.text_lower:match('^'..self.info.first_name:lower()..',')
or msg.text_lower:match('^@'..self.info.username:lower()..',')
or msg.from.id == msg.chat.id
--Uncomment the following line for Al Gore-like conversation.
--or (msg.reply_to_message and msg.reply_to_message.from.id == self.info.id)
)
or msg.text:match('^'..config.cmd_pat)
or msg.text == ''
) then
return true
end
bindings.sendChatAction(self, { action = 'typing' } )
local input = msg.text_lower:gsub(self.info.first_name, 'simsimi')
input = input:gsub('@'..self.info.username, 'simsimi')
local sandbox = self.config.simsimi_trial and 'sandbox.' or ''
local url = chatter.base_url:format(sandbox, config.simsimi_key, self.config.lang, URL.escape(input))
local jstr, res = HTTP.request(url)
if res ~= 200 then
utilities.send_message(self, msg.chat.id, config.errors.chatter_connection)
return
end
local jdat = JSON.decode(jstr)
if not jdat.response or jdat.response:match('^I HAVE NO RESPONSE.') then
utilities.send_message(self, msg.chat.id, config.errors.chatter_response)
return
end
local output = jdat.response
-- Clean up the response here.
output = utilities.trim(output)
-- Simsimi will often refer to itself. Replace "simsimi" with the bot name.
output = output:gsub('%aimi?%aimi?', self.info.first_name)
-- Self-explanatory.
output = output:gsub('USER', msg.from.first_name)
-- Capitalize the first letter.
output = output:gsub('^%l', string.upper)
-- Add a period if there is no punctuation.
output = output:gsub('%P$', '%1.')
utilities.send_message(self, msg.chat.id, output)
end
return chatter

View File

@@ -1,430 +0,0 @@
-- Commits from https://github.com/ngerakines/commitment.
local commit = {}
local utilities = require('utilities')
commit.command = 'commit'
commit.doc = '`Returns a commit message from whatthecommit.com.`'
function commit:init(config)
commit.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('commit').table
end
local 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",
"Dont 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 Im supposed to do it, but I can't think of something better.",
"Dont 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!",
"please dont let this be the problem",
"good: no crash. bad: nothing happens",
"trying",
"trying harder",
"i tried",
"fml"
}
function commit:action(msg)
local output = '`'..commits[math.random(#commits)]..'`'
utilities.send_message(self, msg.chat.id, output, true, nil, true)
end
return commit

View File

@@ -1,56 +0,0 @@
local control = {}
local bot = require('bot')
local utilities = require('utilities')
local cmd_pat -- Prevents the command from being uncallable.
function control:init(config)
cmd_pat = config.cmd_pat
control.triggers = utilities.triggers(self.info.username, cmd_pat,
{'^'..cmd_pat..'script'}):t('reload', true):t('halt').table
end
function control:action(msg, config)
if msg.from.id ~= config.admin then
return
end
if msg.date < os.time() - 1 then return end
if msg.text_lower:match('^'..cmd_pat..'reload') then
for pac, _ in pairs(package.loaded) do
if pac:match('^plugins%.') then
package.loaded[pac] = nil
end
end
package.loaded['bindings'] = nil
package.loaded['utilities'] = nil
package.loaded['config'] = nil
if msg.text_lower:match('%+config') then for k, v in pairs(require('config')) do
config[k] = v
end end
bot.init(self, config)
utilities.send_reply(self, msg, 'Bot reloaded!')
elseif msg.text_lower:match('^'..cmd_pat..'halt') then
self.is_started = false
utilities.send_reply(self, msg, 'Stopping bot!')
elseif msg.text_lower:match('^'..cmd_pat..'script') then
local input = msg.text_lower:match('^'..cmd_pat..'script\n(.+)')
if not input then
utilities.send_reply(self, msg, 'usage: ```\n'..cmd_pat..'script\n'..cmd_pat..'command <arg>\n...\n```', true)
return
end
input = input .. '\n'
for command in input:gmatch('(.-)\n') do
command = utilities.trim(command)
msg.text = command
bot.on_msg_receive(self, msg)
end
end
end
return control

View File

@@ -1,61 +0,0 @@
local currency = {}
local HTTPS = require('ssl.https')
local utilities = require('utilities')
currency.command = 'cash [amount] <from> to <to>'
function currency:init(config)
currency.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('cash', true).table
currency.doc = [[```
]]..config.cmd_pat..[[cash [amount] <from> to <to>
Example: ]]..config.cmd_pat..[[cash 5 USD to EUR
Returns exchange rates for various currencies.
Source: Google Finance.
```]]
end
function currency:action(msg, config)
local input = msg.text:upper()
if not input:match('%a%a%a TO %a%a%a') then
utilities.send_message(self, msg.chat.id, currency.doc, true, msg.message_id, true)
return
end
local from = input:match('(%a%a%a) TO')
local to = input:match('TO (%a%a%a)')
local amount = utilities.get_word(input, 2)
amount = tonumber(amount) or 1
local result = 1
local url = 'https://www.google.com/finance/converter'
if from ~= to then
url = url .. '?from=' .. from .. '&to=' .. to .. '&a=' .. amount
local str, res = HTTPS.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
str = str:match('<span class=bld>(.*) %u+</span>')
if not str then
utilities.send_reply(self, msg, config.errors.results)
return
end
result = string.format('%.2f', str)
end
local output = amount .. ' ' .. from .. ' = ' .. result .. ' ' .. to .. '\n\n'
output = output .. os.date('!%F %T UTC') .. '\nSource: Google Finance`'
output = '```\n' .. output .. '\n```'
utilities.send_message(self, msg.chat.id, output, true, nil, true)
end
return currency

View File

@@ -1,56 +0,0 @@
local dice = {}
local utilities = require('utilities')
dice.command = 'roll <nDr>'
function dice:init(config)
dice.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('roll', true).table
dice.doc = [[```
]]..config.cmd_pat..[[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.
```]]
end
function dice:action(msg)
local input = utilities.input(msg.text_lower)
if not input then
utilities.send_message(self, msg.chat.id, dice.doc, true, msg.message_id, true)
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
utilities.send_message(self, msg.chat.id, dice.doc, true, msg.message_id, true)
return
end
count = tonumber(count)
range = tonumber(range)
if range < 2 then
utilities.send_reply(self, msg, 'The minimum range is 2.')
return
end
if range > 1000 or count > 1000 then
utilities.send_reply(self, msg, 'The maximum range and count are 1000.')
return
end
local output = '*' .. count .. 'd' .. range .. '*\n`'
for _ = 1, count do
output = output .. math.random(range) .. '\t'
end
output = output .. '`'
utilities.send_message(self, msg.chat.id, output, true, msg.message_id, true)
end
return dice

View File

@@ -1,51 +0,0 @@
local dilbert = {}
local HTTP = require('socket.http')
local URL = require('socket.url')
local bindings = require('bindings')
local utilities = require('utilities')
dilbert.command = 'dilbert [date]'
function dilbert:init(config)
dilbert.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('dilbert', true).table
dilbert.doc = [[```
]]..config.cmd_pat..[[dilbert [YYYY-MM-DD]
Returns the latest Dilbert strip or that of the provided date.
Dates before the first strip will return the first strip. Dates after the last trip will return the last strip.
Source: dilbert.com
```]]
end
function dilbert:action(msg, config)
bindings.sendChatAction(self, { chat_id = msg.chat.id, action = 'upload_photo' } )
local input = utilities.input(msg.text)
if not input then input = os.date('%F') end
if not input:match('^%d%d%d%d%-%d%d%-%d%d$') then input = os.date('%F') end
local url = 'http://dilbert.com/strip/' .. URL.escape(input)
local str, res = HTTP.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local strip_filename = '/tmp/' .. input .. '.gif'
local strip_file = io.open(strip_filename)
if strip_file then
strip_file:close()
strip_file = strip_filename
else
local strip_url = str:match('<meta property="og:image" content="(.-)"/>')
strip_file = utilities.download_file(strip_url, '/tmp/' .. input .. '.gif')
end
local strip_title = str:match('<meta property="article:publish_date" content="(.-)"/>')
bindings.sendPhoto(self, { chat_id = msg.chat.id, caption = strip_title }, { photo = strip_file } )
end
return dilbert

View File

@@ -1,34 +0,0 @@
local echo = {}
local utilities = require('utilities')
echo.command = 'echo <text>'
function echo:init(config)
echo.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('echo', true).table
echo.doc = [[```
]]..config.cmd_pat..[[echo <text>
Repeats a string of text.
```]]
end
function echo:action(msg)
local input = utilities.input(msg.text)
if not input then
utilities.send_message(self, msg.chat.id, echo.doc, true, msg.message_id, true)
else
local output
if msg.chat.type == 'supergroup' then
output = '*Echo:*\n"' .. utilities.md_escape(input) .. '"'
else
output = utilities.md_escape(utilities.char.zwnj..input)
end
utilities.send_message(self, msg.chat.id, output, true, nil, true)
end
end
return echo

View File

@@ -1,58 +0,0 @@
local eightball = {}
local utilities = require('utilities')
eightball.command = '8ball'
eightball.doc = '`Returns an answer from a magic 8-ball!`'
function eightball:init(config)
eightball.triggers = utilities.triggers(self.info.username, config.cmd_pat,
{'[Yy]/[Nn]%p*$'}):t('8ball', true).table
end
local ball_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."
}
local yesno_answers = {
'Absolutely.',
'In your dreams.',
'Yes.',
'No.'
}
function eightball:action(msg)
local output
if msg.text_lower:match('y/n%p?$') then
output = yesno_answers[math.random(#yesno_answers)]
else
output = ball_answers[math.random(#ball_answers)]
end
utilities.send_reply(self, msg, output)
end
return eightball

View File

@@ -1,31 +0,0 @@
-- Requires that the "fortune" program is installed on your computer.
local fortune = {}
local utilities = require('utilities')
function fortune:init(config)
local s = io.popen('fortune'):read('*all')
if s:match('not found$') then
print('fortune is not installed on this computer.')
print('fortune.lua will not be enabled.')
return
end
fortune.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('fortune').table
end
fortune.command = 'fortune'
fortune.doc = '`Returns a UNIX fortune.`'
function fortune:action(msg)
local fortunef = io.popen('fortune')
local output = fortunef:read('*all')
output = '```\n' .. output .. '\n```'
utilities.send_message(self, msg.chat.id, output, true, nil, true)
fortunef:close()
end
return fortune

View File

@@ -1,78 +0,0 @@
-- You need a Google API key and a Google Custom Search Engine set up to use this, in config.google_api_key and config.google_cse_key, respectively.
-- You must also sign up for the CSE in the Google Developer Console, and enable image results.
local gImages = {}
local HTTPS = require('ssl.https')
local URL = require('socket.url')
local JSON = require('dkjson')
local utilities = require('utilities')
function gImages:init(config)
if not config.google_api_key then
print('Missing config value: google_api_key.')
print('gImages.lua will not be enabled.')
return
elseif not config.google_cse_key then
print('Missing config value: google_cse_key.')
print('gImages.lua will not be enabled.')
return
end
gImages.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('image', true):t('i', true):t('insfw', true).table
gImages.doc = [[```
]]..config.cmd_pat..[[image <query>
Returns a randomized top result from Google Images. Safe search is enabled by default; use "]]..config.cmd_pat..[[insfw" to disable it. NSFW results will not display an image preview.
Alias: ]]..config.cmd_pat..[[i
```]]
end
gImages.command = 'image <query>'
function gImages:action(msg, config)
local input = utilities.input(msg.text)
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
utilities.send_message(self, msg.chat.id, gImages.doc, true, msg.message_id, true)
return
end
end
local url = 'https://www.googleapis.com/customsearch/v1?&searchType=image&imgSize=xlarge&alt=json&num=8&start=1&key=' .. config.google_api_key .. '&cx=' .. config.google_cse_key
if not string.match(msg.text, '^'..config.cmd_pat..'i[mage]*nsfw') then
url = url .. '&safe=high'
end
url = url .. '&q=' .. URL.escape(input)
local jstr, res = HTTPS.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if jdat.searchInformation.totalResults == '0' then
utilities.send_reply(self, msg, config.errors.results)
return
end
local i = math.random(jdat.queries.request[1].count)
local img_url = jdat.items[i].link
local img_title = jdat.items[i].title
local output = '[' .. img_title .. '](' .. img_url .. ')'
if msg.text:match('nsfw') then
utilities.send_reply(self, '*NSFW*\n'..msg, output)
else
utilities.send_message(self, msg.chat.id, output, false, nil, true)
end
end
return gImages

View File

@@ -1,44 +0,0 @@
local gMaps = {}
local bindings = require('bindings')
local utilities = require('utilities')
gMaps.command = 'location <query>'
function gMaps:init(config)
gMaps.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('location', true):t('loc', true).table
gMaps.doc = [[```
]]..config.cmd_pat..[[location <query>
Returns a location from Google Maps.
Alias: ]]..config.cmd_pat..[[loc
```]]
end
function gMaps:action(msg, config)
local input = utilities.input(msg.text)
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
utilities.send_message(self, msg.chat.id, gMaps.doc, true, msg.message_id, true)
return
end
end
local coords = utilities.get_coords(input, config)
if type(coords) == 'string' then
utilities.send_reply(self, msg, coords)
return
end
bindings.sendLocation(self, {
chat_id = msg.chat.id,
latitude = coords.lat,
longitude = coords.lon,
reply_to_message_id = msg.message_id
} )
end
return gMaps

View File

@@ -1,81 +0,0 @@
local gSearch = {}
local HTTPS = require('ssl.https')
local URL = require('socket.url')
local JSON = require('dkjson')
local utilities = require('utilities')
gSearch.command = 'google <query>'
function gSearch:init(config)
gSearch.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('g', true):t('google', true):t('gnsfw', true).table
gSearch.doc = [[```
]]..config.cmd_pat..[[google <query>
Returns four (if group) or eight (if private message) results from Google. Safe search is enabled by default, use "]]..config.cmd_pat..[[gnsfw" to disable it.
Alias: ]]..config.cmd_pat..[[g
```]]
end
function gSearch:action(msg, config)
local input = utilities.input(msg.text)
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
utilities.send_message(self, msg.chat.id, gSearch.doc, true, msg.message_id, true)
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, '^'..config.cmd_pat..'g[oogle]*nsfw') then
url = url .. '&safe=active'
end
url = url .. '&q=' .. URL.escape(input)
local jstr, res = HTTPS.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if not jdat.responseData then
utilities.send_reply(self, msg, config.errors.connection)
return
end
if not jdat.responseData.results[1] then
utilities.send_reply(self, msg, config.errors.results)
return
end
local output = '*Google results for* _' .. input .. '_ *:*\n'
for i,_ in ipairs(jdat.responseData.results) do
local title = jdat.responseData.results[i].titleNoFormatting:gsub('%[.+%]', ''):gsub('&amp;', '&')
--[[
if title:len() > 48 then
title = title:sub(1, 45) .. '...'
end
]]--
local u = jdat.responseData.results[i].unescapedUrl
if u:find('%)') then
output = output .. '' .. title .. '\n' .. u:gsub('_', '\\_') .. '\n'
else
output = output .. '• [' .. title .. '](' .. u .. ')\n'
end
end
utilities.send_message(self, msg.chat.id, output, true, nil, true)
end
return gSearch

View File

@@ -1,59 +0,0 @@
-- Put this on the bottom of your plugin list, after help.lua.
-- If you want to configure your own greetings, copy the following table
-- (without the "config.") to your config.lua file.
local greetings = {}
local utilities = require('utilities')
function greetings:init(config)
config.greetings = config.greetings or {
['Hello, #NAME.'] = {
'hello',
'hey',
'sup',
'hi',
'good morning',
'good day',
'good afternoon',
'good evening'
},
['Goodbye, #NAME.'] = {
'bye',
'later',
'see ya',
'good night'
},
['Welcome back, #NAME.'] = {
'i\'m home',
'i\'m back'
},
['You\'re welcome, #NAME.'] = {
'thanks',
'thank you'
}
}
greetings.triggers = {
self.info.first_name:lower() .. '%p*$'
}
end
function greetings:action(msg, config)
local nick = self.database.users[msg.from.id_str].nickname or msg.from.first_name
for trigger,responses in pairs(config.greetings) do
for _,response in pairs(responses) do
if msg.text_lower:match(response..',? '..self.info.first_name:lower()) then
utilities.send_message(self, msg.chat.id, utilities.latcyr(trigger:gsub('#NAME', nick)))
return
end
end
end
return true
end
return greetings

View File

@@ -1,65 +0,0 @@
local hackernews = {}
local HTTPS = require('ssl.https')
local JSON = require('dkjson')
local bindings = require('bindings')
local utilities = require('utilities')
hackernews.command = 'hackernews'
function hackernews:init(config)
hackernews.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('hackernews', true):t('hn', true).table
hackernews.doc = [[```
Returns four (if group) or eight (if private message) top stories from Hacker News.
Alias: ]]..config.cmd_pat..[[hn
```]]
end
function hackernews:action(msg, config)
bindings.sendChatAction(self, { chat_id = msg.chat.id, action = 'typing' } )
local jstr, res = HTTPS.request('https://hacker-news.firebaseio.com/v0/topstories.json')
if res ~= 200 then
utilities.send_reply(self, 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 output = '*Hacker News:*\n'
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
utilities.send_reply(self, msg, config.errors.connection)
return
end
local res_jdat = JSON.decode(jstr)
local title = res_jdat.title:gsub('%[.+%]', ''):gsub('%(.+%)', ''):gsub('&amp;', '&')
if title:len() > 48 then
title = title:sub(1, 45) .. '...'
end
local url = res_jdat.url
if not url then
utilities.send_reply(self, msg, config.errors.connection)
return
end
if url:find('%(') then
output = output .. '' .. title .. '\n' .. url:gsub('_', '\\_') .. '\n'
else
output = output .. '• [' .. title .. '](' .. url .. ')\n'
end
end
utilities.send_message(self, msg.chat.id, output, true, nil, true)
end
return hackernews

View File

@@ -1,130 +0,0 @@
-- Plugin for the Hearthstone database provided by hearthstonejson.com.
local hearthstone = {}
--local HTTPS = require('ssl.https')
local JSON = require('dkjson')
local utilities = require('utilities')
function hearthstone:init(config)
if not self.database.hearthstone or os.time() > self.database.hearthstone.expiration then
print('Downloading Hearthstone database...')
-- This stuff doesn't play well with lua-sec. Disable it for now; hack in curl.
--local jstr, res = HTTPS.request('https://api.hearthstonejson.com/v1/latest/enUS/cards.json')
--if res ~= 200 then
-- print('Error connecting to hearthstonejson.com.')
-- print('hearthstone.lua will not be enabled.')
-- return
--end
--local jdat = JSON.decode(jstr)
local s = io.popen('curl -s https://api.hearthstonejson.com/v1/latest/enUS/cards.json'):read('*all')
local d = JSON.decode(s)
if not d then
print('Error connecting to hearthstonejson.com.')
print('hearthstone.lua will not be enabled.')
return
end
self.database.hearthstone = d
self.database.hearthstone.expiration = os.time() + 600000
print('Download complete! It will be stored for a week.')
end
hearthstone.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('hearthstone', true):t('hs').table
hearthstone.doc = [[```
]]..config.cmd_pat..[[hearthstone <query>
Returns Hearthstone card info.
Alias: ]]..config.cmd_pat..[[hs
```]]
end
hearthstone.command = 'hearthstone <query>'
local function format_card(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
-- unused?
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
function hearthstone:action(msg, config)
local input = utilities.input(msg.text_lower)
if not input then
utilities.send_message(self, msg.chat.id, hearthstone.doc, true, msg.message_id, true)
return
end
local output = ''
for _,v in pairs(self.database.hearthstone) do
if type(v) == 'table' and string.lower(v.name):match(input) then
output = output .. format_card(v) .. '\n\n'
end
end
output = utilities.trim(output)
if output:len() == 0 then
utilities.send_reply(self, msg, config.errors.results)
return
end
utilities.send_message(self, msg.chat.id, output, true, msg.message_id, true)
end
return hearthstone

View File

@@ -1,61 +0,0 @@
-- This plugin should go at the end of your plugin list in
-- config.lua, but not after greetings.lua.
local help = {}
local utilities = require('utilities')
local help_text
function help:init(config)
local commandlist = {}
help_text = '*Available commands:*\n'..config.cmd_pat
for _,plugin in ipairs(self.plugins) do
if plugin.command then
table.insert(commandlist, plugin.command)
--help_text = help_text .. '\n• '..config.cmd_pat .. plugin.command:gsub('%[', '\\[')
end
end
table.insert(commandlist, 'help [command]')
table.sort(commandlist)
help_text = help_text .. table.concat(commandlist, '\n'..config.cmd_pat) .. '\nArguments: <required> [optional]'
help_text = help_text:gsub('%[', '\\[')
help.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('help', true):t('h', true).table
end
function help:action(msg)
local input = utilities.input(msg.text_lower)
-- Attempts to send the help message via PM.
-- If msg is from a group, it tells the group whether the PM was successful.
if not input then
local res = utilities.send_message(self, msg.from.id, help_text, true, nil, true)
if not res then
utilities.send_reply(self, msg, 'Please message me privately or [click here](http://telegram.me/' .. self.info.username .. '?start=help) for a list of commands.', true)
elseif msg.chat.type ~= 'private' then
utilities.send_reply(self, msg, 'I have sent you the requested information in a private message.')
end
return
end
for _,plugin in ipairs(self.plugins) do
if plugin.command and utilities.get_word(plugin.command, 1) == input and plugin.doc then
local output = '*Help for* _' .. utilities.get_word(plugin.command, 1) .. '_ *:*\n' .. plugin.doc
utilities.send_message(self, msg.chat.id, output, true, nil, true)
return
end
end
utilities.send_reply(self, msg, 'Sorry, there is no help for that command.')
end
return help

View File

@@ -1,54 +0,0 @@
local imdb = {}
local HTTP = require('socket.http')
local URL = require('socket.url')
local JSON = require('dkjson')
local utilities = require('utilities')
imdb.command = 'imdb <query>'
function imdb:init(config)
imdb.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('imdb', true).table
imdb.doc = [[```
]]..config.cmd_pat..[[imdb <query>
Returns an IMDb entry.
```]]
end
function imdb:action(msg, config)
local input = utilities.input(msg.text)
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
utilities.send_message(self, msg.chat.id, imdb.doc, true, msg.message_id, true)
return
end
end
local url = 'http://www.omdbapi.com/?t=' .. URL.escape(input)
local jstr, res = HTTP.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if jdat.Response ~= 'True' then
utilities.send_reply(self, msg, config.errors.results)
return
end
local output = '*' .. jdat.Title .. ' ('.. jdat.Year ..')*\n'
output = output .. jdat.imdbRating ..'/10 | '.. jdat.Runtime ..' | '.. jdat.Genre ..'\n'
output = output .. '_' .. jdat.Plot .. '_\n'
output = output .. '[Read more.](http://imdb.com/title/' .. jdat.imdbID .. ')'
utilities.send_message(self, msg.chat.id, output, true, nil, true)
end
return imdb

View File

@@ -1,111 +0,0 @@
-- TODO: Add support for librefm API.
-- Just kidding, nobody actually uses that.
local lastfm = {}
local HTTP = require('socket.http')
local URL = require('socket.url')
local JSON = require('dkjson')
local utilities = require('utilities')
function lastfm:init(config)
if not config.lastfm_api_key then
print('Missing config value: lastfm_api_key.')
print('lastfm.lua will not be enabled.')
return
end
lastfm.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('lastfm', true):t('np', true):t('fmset', true).table
lastfm.doc = [[```
]]..config.cmd_pat..[[np [username]
Returns what you are or were last listening to. If you specify a username, info will be returned for that username.
]]..config.cmd_pat..[[fmset <username>
Sets your last.fm username. Otherwise, ]]..config.cmd_pat..[[np will use your Telegram username. Use "]]..config.cmd_pat..[[fmset --" to delete it.
```]]
end
lastfm.command = 'lastfm'
function lastfm:action(msg, config)
local input = utilities.input(msg.text)
if string.match(msg.text, '^'..config.cmd_pat..'lastfm') then
utilities.send_message(self, msg.chat.id, lastfm.doc, true, msg.message_id, true)
return
elseif string.match(msg.text, '^'..config.cmd_pat..'fmset') then
if not input then
utilities.send_message(self, msg.chat.id, lastfm.doc, true, msg.message_id, true)
elseif input == '--' or input == utilities.char.em_dash then
self.database.users[msg.from.id_str].lastfm = nil
utilities.send_reply(self, msg, 'Your last.fm username has been forgotten.')
else
self.database.users[msg.from.id_str].lastfm = input
utilities.send_reply(self, msg, 'Your last.fm username has been set to "' .. input .. '".')
end
return
end
local url = 'http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&format=json&limit=1&api_key=' .. config.lastfm_api_key .. '&user='
local username
local alert = ''
if input then
username = input
elseif self.database.users[msg.from.id_str].lastfm then
username = self.database.users[msg.from.id_str].lastfm
elseif msg.from.username then
username = msg.from.username
alert = '\n\nYour username has been set to ' .. username .. '.\nTo change it, use '..config.cmd_pat..'fmset <username>.'
self.database.users[msg.from.id_str].lastfm = username
else
utilities.send_reply(self, msg, 'Please specify your last.fm username or set it with '..config.cmd_pat..'fmset.')
return
end
url = url .. URL.escape(username)
local jstr, res
utilities.with_http_timeout(
1, function ()
jstr, res = HTTP.request(url)
end)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if jdat.error then
utilities.send_reply(self, msg, 'Please specify your last.fm username or set it with '..config.cmd_pat..'fmset.')
return
end
jdat = jdat.recenttracks.track[1] or jdat.recenttracks.track
if not jdat then
utilities.send_reply(self, msg, 'No history for this user.' .. alert)
return
end
local output = input or msg.from.first_name
output = '🎵 ' .. output
if jdat['@attr'] and jdat['@attr'].nowplaying then
output = output .. ' is currently listening to:\n'
else
output = output .. ' last listened to:\n'
end
local title = jdat.name or 'Unknown'
local artist = 'Unknown'
if jdat.artist then
artist = jdat.artist['#text']
end
output = output .. title .. ' - ' .. artist .. alert
utilities.send_message(self, msg.chat.id, output)
end
return lastfm

View File

@@ -1,53 +0,0 @@
local luarun = {}
local utilities = require('utilities')
local URL = require('socket.url')
local JSON = require('dkjson')
function luarun:init(config)
luarun.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('lua', true):t('return', true).table
end
function luarun:action(msg, config)
if msg.from.id ~= config.admin then
return true
end
local input = utilities.input(msg.text)
if not input then
utilities.send_reply(self, msg, 'Please enter a string to load.')
return
end
if msg.text_lower:match('^'..config.cmd_pat..'return') then
input = 'return ' .. input
end
local output = loadstring( [[
local bot = require('bot')
local bindings = require('bindings')
local utilities = require('utilities')
local JSON = require('dkjson')
local URL = require('socket.url')
local HTTP = require('socket.http')
local HTTPS = require('ssl.https')
return function (self, msg, config) ]] .. input .. [[ end
]] )()(self, msg, config)
if output == nil then
output = 'Done!'
else
if type(output) == 'table' then
local s = JSON.encode(output, {indent=true})
if URL.escape(s):len() < 4000 then
output = s
end
end
output = '```\n' .. tostring(output) .. '\n```'
end
utilities.send_message(self, msg.chat.id, output, true, msg.message_id, true)
end
return luarun

View File

@@ -1,29 +0,0 @@
local me = {}
local utilities = require('utilities')
function me:init(config)
me.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('me', true).table
end
function me:action(msg, config)
local target = self.database.users[msg.from.id_str]
if msg.from.id == config.admin and (msg.reply_to_message or utilities.input(msg.text)) then
target = utilities.user_from_message(self, msg, true)
if target.err then
utilities.send_reply(self, msg, target.err)
return
end
end
local output = ''
for k,v in pairs(target) do
output = output .. '*' .. k .. ':* `' .. tostring(v) .. '`\n'
end
utilities.send_message(self, msg.chat.id, output, true, nil, true)
end
return me

View File

@@ -1,51 +0,0 @@
local nick = {}
local utilities = require('utilities')
nick.command = 'nick <nickname>'
function nick:init(config)
nick.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('nick', true).table
nick.doc = [[```
]]..config.cmd_pat..[[nick <nickname>
Set your nickname. Use "]]..config.cmd_pat..[[nick --" to delete it.
```]]
end
function nick:action(msg, config)
local target = msg.from
if msg.from.id == config.admin and msg.reply_to_message then
target = msg.reply_to_message.from
target.id_str = tostring(target.id)
target.name = target.first_name
if target.last_name then
target.name = target.first_name .. ' ' .. target.last_name
end
end
local output
local input = utilities.input(msg.text)
if not input then
if self.database.users[target.id_str].nickname then
output = target.name .. '\'s nickname is "' .. self.database.users[target.id_str].nickname .. '".'
else
output = target.name .. ' currently has no nickname.'
end
elseif utilities.utf8_len(input) > 32 then
output = 'The character limit for nicknames is 32.'
elseif input == '--' or input == utilities.char.em_dash then
self.database.users[target.id_str].nickname = nil
output = target.name .. '\'s nickname has been deleted.'
else
input = input:gsub('\n', ' ')
self.database.users[target.id_str].nickname = input
output = target.name .. '\'s nickname has been set to "' .. input .. '".'
end
utilities.send_reply(self, msg, output)
end
return nick

View File

@@ -1,34 +0,0 @@
local patterns = {}
local utilities = require('utilities')
patterns.triggers = {
'^/?s/.-/.-$'
}
function patterns:action(msg)
if not msg.reply_to_message then return end
local output = msg.reply_to_message.text
if msg.reply_to_message.from.id == self.info.id then
output = output:gsub('Did you mean:\n"', '')
output = output:gsub('"$', '')
end
local m1, m2 = msg.text:match('^/?s/(.-)/(.-)/?$')
if not m2 then return true end
local res
res, output = pcall(
function()
return output:gsub(m1, m2)
end
)
if res == false then
output = 'Malformed pattern!'
utilities.send_reply(self, msg, output)
else
output = output:sub(1, 4000)
output = 'Did you mean:\n"' .. output .. '"'
utilities.send_reply(self, msg.reply_to_message, output)
end
end
return patterns

View File

@@ -1,16 +0,0 @@
-- Actually the simplest plugin ever!
local ping = {}
local utilities = require('utilities')
function ping:init(config)
ping.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('ping'):t('annyong').table
end
function ping:action(msg, config)
local output = msg.text_lower:match('^'..config.cmd_pat..'ping') and 'Pong!' or 'Annyong.'
utilities.send_message(self, msg.chat.id, output)
end
return ping

View File

@@ -1,71 +0,0 @@
local pokedex = {}
local HTTP = require('socket.http')
local JSON = require('dkjson')
local bindings = require('bindings')
local utilities = require('utilities')
pokedex.command = 'pokedex <query>'
function pokedex:init(config)
pokedex.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('pokedex', true):t('dex', true).table
pokedex.doc = [[```
]]..config.cmd_pat..[[pokedex <query>
Returns a Pokedex entry from pokeapi.co.
Alias: ]]..config.cmd_pat..[[dex
```]]
end
function pokedex:action(msg, config)
bindings.sendChatAction(self, { chat_id = msg.chat.id, action = 'typing' } )
local input = utilities.input(msg.text_lower)
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
utilities.send_message(self, msg.chat.id, pokedex.doc, true, msg.message_id, true)
return
end
end
local url = 'http://pokeapi.co'
local dex_url = url .. '/api/v1/pokemon/' .. input
local dex_jstr, res = HTTP.request(dex_url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local dex_jdat = JSON.decode(dex_jstr)
local desc_url = url .. dex_jdat.descriptions[math.random(#dex_jdat.descriptions)].resource_uri
local desc_jstr, _ = HTTP.request(desc_url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local desc_jdat = JSON.decode(desc_jstr)
local poke_type
for _,v in ipairs(dex_jdat.types) do
local type_name = v.name:gsub("^%l", string.upper)
if not poke_type then
poke_type = type_name
else
poke_type = poke_type .. ' / ' .. type_name
end
end
poke_type = poke_type .. ' type'
local output = '*' .. dex_jdat.name .. '*\n#' .. dex_jdat.national_id .. ' | ' .. poke_type .. '\n_' .. desc_jdat.description:gsub('POKMON', 'Pokémon'):gsub('Pokmon', 'Pokémon') .. '_'
utilities.send_message(self, msg.chat.id, output, true, nil, true)
end
return pokedex

View File

@@ -1,47 +0,0 @@
local preview = {}
local HTTP = require('socket.http')
local utilities = require('utilities')
preview.command = 'preview <link>'
function preview:init(config)
preview.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('preview', true).table
preview.doc = [[```
]]..config.cmd_pat..[[preview <link>
Returns a full-message, "unlinked" preview.
```]]
end
function preview:action(msg)
local input = utilities.input(msg.text)
if not input then
utilities.send_message(self, msg.chat.id, preview.doc, true, nil, true)
return
end
input = utilities.get_word(input, 1)
if not input:match('^https?://.+') then
input = 'http://' .. input
end
local res = HTTP.request(input)
if not res then
utilities.send_reply(self, msg, 'Please provide a valid link.')
return
end
if res:len() == 0 then
utilities.send_reply(self, msg, 'Sorry, the link you provided is not letting us make a preview.')
return
end
-- Invisible zero-width, non-joiner.
local output = '[](' .. input .. ')'
utilities.send_message(self, msg.chat.id, output, false, nil, true)
end
return preview

View File

@@ -1,144 +0,0 @@
local pun = {}
local utilities = require('utilities')
pun.command = 'pun'
pun.doc = '`Returns a pun.`'
function pun:init(config)
pun.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('pun').table
end
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.",
"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, youre 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 married? 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 captured 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.",
"A sea lion is nothing but an ionized seal.",
"The vegetables from my garden aren't that great. I guess you could say they're mediokra."
}
function pun:action(msg)
utilities.send_reply(self, msg, puns[math.random(#puns)])
end
return pun

View File

@@ -1,52 +0,0 @@
-- Never change this plugin. It was not meant to be changed.
-- You may add reactions. You must never remove reactions.
-- You must never restructure. You must never disable this plugin.
-- - Drew, creator, a year later.
-- Nevermind, Brayden changed it.
-- - Drew, just now.
local reactions = {}
local utilities = require('utilities')
reactions.command = 'reactions'
reactions.doc = '`Returns a list of "reaction" emoticon commands.`'
local mapping = {
['shrug'] = '¯\\_(ツ)_/¯',
['lenny'] = '( ͡° ͜ʖ ͡°)',
['flip'] = '(╯°□°)╯︵ ┻━┻',
['homo'] = ' o',
['look'] = 'ಠ_ಠ',
['shots?'] = 'SHOTS FIRED',
['facepalm'] = '(-‸ლ)'
}
local help
function reactions:init(config)
-- Generate a "help" message triggered by "/reactions".
help = 'Reactions:\n'
reactions.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('reactions').table
for trigger,reaction in pairs(mapping) do
help = help .. '' .. config.cmd_pat .. trigger:gsub('.%?', '') .. ': ' .. reaction .. '\n'
table.insert(reactions.triggers, config.cmd_pat..trigger)
table.insert(reactions.triggers, config.cmd_pat..trigger..'@'..self.info.username:lower())
end
end
function reactions:action(msg, config)
if string.match(msg.text_lower, config.cmd_pat..'reactions') then
utilities.send_message(self, msg.chat.id, help)
return
end
for trigger,reaction in pairs(mapping) do
if string.match(msg.text_lower, config.cmd_pat..trigger) then
utilities.send_message(self, msg.chat.id, reaction)
return
end
end
end
return reactions

View File

@@ -1,85 +0,0 @@
local reddit = {}
local HTTP = require('socket.http')
local URL = require('socket.url')
local JSON = require('dkjson')
local utilities = require('utilities')
reddit.command = 'reddit [r/subreddit | query]'
function reddit:init(config)
reddit.triggers = utilities.triggers(self.info.username, config.cmd_pat, {'^/r/'}):t('reddit', true):t('r', true):t('r/', true).table
reddit.doc = [[```
]]..config.cmd_pat..[[reddit [r/subreddit | query]
Returns the top posts or results for a given subreddit or query. If no argument is given, returns the top posts from r/all. Querying specific subreddits is not supported.
Aliases: ]]..config.cmd_pat..[[r, /r/subreddit
```]]
end
local format_results = function(posts)
local output = ''
for _,v in ipairs(posts) do
local post = v.data
local title = post.title:gsub('%[', '('):gsub('%]', ')'):gsub('&amp;', '&')
if title:len() > 256 then
title = title:sub(1, 253)
title = utilities.trim(title) .. '...'
end
local short_url = 'redd.it/' .. post.id
local s = '[' .. title .. '](' .. short_url .. ')'
if post.domain and not post.is_self and not post.over_18 then
s = '`[`[' .. post.domain .. '](' .. post.url:gsub('%)', '\\)') .. ')`]` ' .. s
end
output = output .. '' .. s .. '\n'
end
return output
end
reddit.subreddit_url = 'http://www.reddit.com/%s/.json?limit='
reddit.search_url = 'http://www.reddit.com/search.json?q=%s&limit='
reddit.rall_url = 'http://www.reddit.com/.json?limit='
function reddit:action(msg, config)
-- Eight results in PM, four results elsewhere.
local limit = 4
if msg.chat.type == 'private' then
limit = 8
end
local text = msg.text_lower
if text:match('^/r/.') then
-- Normalize input so this hack works easily.
text = msg.text_lower:gsub('^/r/', config.cmd_pat..'r r/')
end
local input = utilities.input(text)
local source, url
if input then
if input:match('^r/.') then
input = utilities.get_word(input, 1)
url = reddit.subreddit_url:format(input) .. limit
source = '*/' .. utilities.md_escape(input) .. '*\n'
else
input = utilities.input(msg.text)
source = '*Results for* _' .. utilities.md_escape(input) .. '_ *:*\n'
input = URL.escape(input)
url = reddit.search_url:format(input) .. limit
end
else
url = reddit.rall_url .. limit
source = '*/r/all*\n'
end
local jstr, res = HTTP.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
else
local jdat = JSON.decode(jstr)
if #jdat.data.children == 0 then
utilities.send_reply(self, msg, config.errors.results)
else
local output = format_results(jdat.data.children)
output = source .. output
utilities.send_message(self, msg.chat.id, output, true, nil, true)
end
end
end
return reddit

View File

@@ -1,97 +0,0 @@
local remind = {}
local utilities = require('utilities')
remind.command = 'remind <duration> <message>'
function remind:init(config)
self.database.reminders = self.database.reminders or {}
remind.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('remind', true).table
remind.doc = [[```
]]..config.cmd_pat..[[remind <duration> <message>
Repeats a message after a duration of time, in minutes.
```]]
end
function remind:action(msg)
-- Ensure there are arguments. If not, send doc.
local input = utilities.input(msg.text)
if not input then
utilities.send_message(self, msg.chat.id, remind.doc, true, msg.message_id, true)
return
end
-- Ensure first arg is a number. If not, send doc.
local duration = utilities.get_word(input, 1)
if not tonumber(duration) then
utilities.send_message(self, msg.chat.id, remind.doc, true, msg.message_id, true)
return
end
-- Duration must be between one minute and one year (approximately).
duration = tonumber(duration)
if duration < 1 then
duration = 1
elseif duration > 526000 then
duration = 526000
end
-- Ensure there is a second arg.
local message = utilities.input(input)
if not message then
utilities.send_message(self, msg.chat.id, remind.doc, true, msg.message_id, true)
return
end
-- Make a database entry for the group/user if one does not exist.
self.database.reminders[msg.chat.id_str] = self.database.reminders[msg.chat.id_str] or {}
-- Limit group reminders to 10 and private reminders to 50.
if msg.chat.type ~= 'private' and utilities.table_size(self.database.reminders[msg.chat.id_str]) > 9 then
utilities.send_reply(self, msg, 'Sorry, this group already has ten reminders.')
return
elseif msg.chat.type == 'private' and utilities.table_size(self.database.reminders[msg.chat.id_str]) > 49 then
utilities.send_reply(msg, 'Sorry, you already have fifty reminders.')
return
end
-- Put together the reminder with the expiration, message, and message to reply to.
local reminder = {
time = os.time() + duration * 60,
message = message
}
table.insert(self.database.reminders[msg.chat.id_str], reminder)
local output = 'I will remind you in ' .. duration
if duration == 1 then
output = output .. ' minute!'
else
output = output .. ' minutes!'
end
utilities.send_reply(self, msg, output)
end
function remind:cron()
local time = os.time()
-- Iterate over the group entries in the reminders database.
for chat_id, group in pairs(self.database.reminders) do
local new_group = {}
-- Iterate over each reminder.
for _, reminder in ipairs(group) do
-- If the reminder is past-due, send it and nullify it.
-- Otherwise, add it to the replacement table.
if time > reminder.time then
local output = '*Reminder:*\n"' .. utilities.md_escape(reminder.message) .. '"'
local res = utilities.send_message(self, chat_id, output, true, nil, true)
-- If the message fails to send, save it for later.
if not res then
table.insert(new_group, reminder)
end
else
table.insert(new_group, reminder)
end
end
-- Nullify the original table and replace it with the new one.
self.database.reminders[chat_id] = new_group
-- Nullify the table if it is empty.
if #new_group == 0 then
self.database.reminders[chat_id] = nil
end
end
end
return remind

View File

@@ -1,72 +0,0 @@
local setandget = {}
local utilities = require('utilities')
function setandget:init(config)
self.database.setandget = self.database.setandget or {}
setandget.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('set', true):t('get', true).table
setandget.doc = [[```
]]..config.cmd_pat..[[set <name> <value>
Stores a value with the given name. Use "]]..config.cmd_pat..[[set <name> --" to delete the stored value.
]]..config.cmd_pat..[[get [name]
Returns the stored value or a list of stored values.
```]]
end
setandget.command = 'set <name> <value>'
function setandget:action(msg, config)
local input = utilities.input(msg.text)
self.database.setandget[msg.chat.id_str] = self.database.setandget[msg.chat.id_str] or {}
if msg.text_lower:match('^'..config.cmd_pat..'set') then
if not input then
utilities.send_message(self, msg.chat.id, setandget.doc, true, nil, true)
return
end
local name = utilities.get_word(input:lower(), 1)
local value = utilities.input(input)
if not name or not value then
utilities.send_message(self, msg.chat.id, setandget.doc, true, nil, true)
elseif value == '--' or value == '' then
self.database.setandget[msg.chat.id_str][name] = nil
utilities.send_message(self, msg.chat.id, 'That value has been deleted.')
else
self.database.setandget[msg.chat.id_str][name] = value
utilities.send_message(self, msg.chat.id, '"' .. name .. '" has been set to "' .. value .. '".', true)
end
elseif msg.text_lower:match('^'..config.cmd_pat..'get') then
if not input then
local output
if utilities.table_size(self.database.setandget[msg.chat.id_str]) == 0 then
output = 'No values have been stored here.'
else
output = '*List of stored values:*\n'
for k,v in pairs(self.database.setandget[msg.chat.id_str]) do
output = output .. '' .. k .. ': `' .. v .. '`\n'
end
end
utilities.send_message(self, msg.chat.id, output, true, nil, true)
return
end
local output
if self.database.setandget[msg.chat.id_str][input:lower()] then
output = '`' .. self.database.setandget[msg.chat.id_str][input:lower()] .. '`'
else
output = 'There is no value stored by that name.'
end
utilities.send_message(self, msg.chat.id, output, true, nil, true)
end
end
return setandget

View File

@@ -1,33 +0,0 @@
local shell = {}
local utilities = require('utilities')
function shell:init(config)
shell.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('run', true).table
end
function shell:action(msg, config)
if msg.from.id ~= config.admin then
return
end
local input = utilities.input(msg.text)
input = input:gsub('', '--')
if not input then
utilities.send_reply(self, msg, 'Please specify a command to run.')
return
end
local output = io.popen(input):read('*all')
if output:len() == 0 then
output = 'Done!'
else
output = '```\n' .. output .. '\n```'
end
utilities.send_message(self, msg.chat.id, output, true, msg.message_id, true)
end
return shell

View File

@@ -1,52 +0,0 @@
local shout = {}
local utilities = require('utilities')
shout.command = 'shout <text>'
function shout:init(config)
shout.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('shout', true).table
shout.doc = [[```
]]..config.cmd_pat..[[shout <text>
Shouts something. Input may be the replied-to message.
```]]
end
function shout:action(msg)
local input = utilities.input(msg.text)
if not input then
if msg.reply_to_message and #msg.reply_to_message.text > 0 then
input = msg.reply_to_message.text
else
utilities.send_message(self, msg.chat.id, shout.doc, true, msg.message_id, true)
return
end
end
input = utilities.trim(input)
if input:len() > 20 then
input = input:sub(1,20)
end
input = input:upper()
local output = ''
local inc = 0
for match in input:gmatch('([%z\1-\127\194-\244][\128-\191]*)') do
output = output .. match .. ' '
end
output = output .. '\n'
for match in input:sub(2):gmatch('([%z\1-\127\194-\244][\128-\191]*)') do
local spacing = ''
for _ = 1, inc do
spacing = spacing .. ' '
end
inc = inc + 1
output = output .. match .. ' ' .. spacing .. match .. '\n'
end
output = '```\n' .. utilities.trim(output) .. '\n```'
utilities.send_message(self, msg.chat.id, output, true, false, true)
end
return shout

View File

@@ -1,130 +0,0 @@
local slap = {}
local utilities = require('utilities')
slap.command = 'slap [target]'
function slap:init(config)
slap.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('slap', true).table
slap.doc = [[```
]]..config.cmd_pat..[[slap [target]
Slap somebody.
```]]
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.',
'VICTIM died of hospital gangrene.',
'VICTIM got a house call from Doctor VICTOR.',
'VICTOR beheaded VICTIM.',
'VICTIM got stoned...by an angry mob.',
'VICTOR sued the pants off VICTIM.',
'VICTIM was impeached.',
'VICTIM was one-hit KO\'d by VICTOR.',
'VICTOR sent VICTIM to /dev/null.',
'VICTOR sent VICTIM down the memory hole.'
}
function slap:action(msg)
local victor = self.database.users[msg.from.id_str]
local victim = utilities.user_from_message(self, msg, true)
local input = utilities.input(msg.text)
local victim_name = victim.nickname or victim.first_name or input
local victor_name = victor.nickname or victor.first_name
if not victim_name or victim_name == victor_name then
victim_name = victor_name
victor_name = self.info.first_name
end
local output = slaps[math.random(#slaps)]
output = output:gsub('VICTIM', victim_name)
output = output:gsub('VICTOR', victor_name)
output = utilities.char.zwnj .. output
utilities.send_message(self, msg.chat.id, output)
end
return slap

View File

@@ -1,62 +0,0 @@
local time = {}
local HTTPS = require('ssl.https')
local JSON = require('dkjson')
local utilities = require('utilities')
time.command = 'time <location>'
function time:init(config)
time.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('time', true).table
time.doc = [[```
]]..config.cmd_pat..[[time <location>
Returns the time, date, and timezone for the given location.
```]]
end
function time:action(msg, config)
local input = utilities.input(msg.text)
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
utilities.send_message(self, msg.chat.id, time.doc, true, msg.message_id, true)
return
end
end
local coords = utilities.get_coords(input, config)
if type(coords) == 'string' then
utilities.send_reply(self, msg, coords)
return
end
local now = os.time()
local utc = os.time(os.date("!*t", now))
local url = 'https://maps.googleapis.com/maps/api/timezone/json?location=' .. coords.lat ..','.. coords.lon .. '&timestamp='..utc
local jstr, res = HTTPS.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
local timestamp = now + jdat.rawOffset + jdat.dstOffset
local utcoff = (jdat.rawOffset + jdat.dstOffset) / 3600
if utcoff == math.abs(utcoff) then
utcoff = '+'.. utilities.pretty_float(utcoff)
else
utcoff = utilities.pretty_float(utcoff)
end
local output = os.date('!%I:%M %p\n', timestamp) .. os.date('!%A, %B %d, %Y\n', timestamp) .. jdat.timeZoneName .. ' (UTC' .. utcoff .. ')'
output = '```\n' .. output .. '\n```'
utilities.send_reply(self, msg, output, true)
end
return time

View File

@@ -1,51 +0,0 @@
local translate = {}
local HTTPS = require('ssl.https')
local URL = require('socket.url')
local JSON = require('dkjson')
local utilities = require('utilities')
translate.command = 'translate [text]'
function translate:init(config)
translate.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('translate', true):t('tl', true).table
translate.doc = [[```
]]..config.cmd_pat..[[translate [text]
Translates input or the replied-to message into the bot's language.
```]]
end
function translate:action(msg, config)
local input = utilities.input(msg.text)
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
utilities.send_message(self, msg.chat.id, translate.doc, true, msg.message_id, true)
return
end
end
local url = 'https://translate.yandex.net/api/v1.5/tr.json/translate?key=' .. config.yandex_key .. '&lang=' .. config.lang .. '&text=' .. URL.escape(input)
local str, res = HTTPS.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local jdat = JSON.decode(str)
if jdat.code ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local output = jdat.text[1]
output = '*Translation:*\n"' .. utilities.md_escape(output) .. '"'
utilities.send_reply(self, msg.reply_to_message or msg, output, true)
end
return translate

View File

@@ -1,57 +0,0 @@
local urbandictionary = {}
local HTTP = require('socket.http')
local URL = require('socket.url')
local JSON = require('dkjson')
local utilities = require('utilities')
urbandictionary.command = 'urbandictionary <query>'
function urbandictionary:init(config)
urbandictionary.triggers = utilities.triggers(self.info.username, config.cmd_pat)
:t('urbandictionary', true):t('ud', true):t('urban', true).table
urbandictionary.doc = [[```
]]..config.cmd_pat..[[urbandictionary <query>
Returns a definition from Urban Dictionary.
Aliases: ]]..config.cmd_pat..[[ud, ]]..config.cmd_pat..[[urban
```]]
end
function urbandictionary:action(msg, config)
local input = utilities.input(msg.text)
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
utilities.send_message(self, msg.chat.id, urbandictionary.doc, true, msg.message_id, true)
return
end
end
local url = 'http://api.urbandictionary.com/v0/define?term=' .. URL.escape(input)
local jstr, res = HTTP.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if jdat.result_type == "no_results" then
utilities.send_reply(self, msg, config.errors.results)
return
end
local output = '*' .. jdat.list[1].word .. '*\n\n' .. utilities.trim(jdat.list[1].definition)
if string.len(jdat.list[1].example) > 0 then
output = output .. '_\n\n' .. utilities.trim(jdat.list[1].example) .. '_'
end
output = output:gsub('%[', ''):gsub('%]', '')
utilities.send_message(self, msg.chat.id, output, true, nil, true)
end
return urbandictionary

View File

@@ -1,63 +0,0 @@
local weather = {}
local HTTP = require('socket.http')
local JSON = require('dkjson')
local utilities = require('utilities')
function weather:init(config)
if not config.owm_api_key then
print('Missing config value: owm_api_key.')
print('weather.lua will not be enabled.')
return
end
weather.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('weather', true).table
weather.doc = [[```
]]..config.cmd_pat..[[weather <location>
Returns the current weather conditions for a given location.
```]]
end
weather.command = 'weather <location>'
function weather:action(msg, config)
local input = utilities.input(msg.text)
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
utilities.send_message(self, msg.chat.id, weather.doc, true, msg.message_id, true)
return
end
end
local coords = utilities.get_coords(input, config)
if type(coords) == 'string' then
utilities.send_reply(self, msg, coords)
return
end
local url = 'http://api.openweathermap.org/data/2.5/weather?APPID=' .. config.owm_api_key .. '&lat=' .. coords.lat .. '&lon=' .. coords.lon
local jstr, res = HTTP.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if jdat.cod ~= 200 then
utilities.send_reply(self, msg, 'Error: City not found.')
return
end
local celsius = string.format('%.2f', jdat.main.temp - 273.15)
local fahrenheit = string.format('%.2f', celsius * (9/5) + 32)
local output = '`' .. celsius .. '°C | ' .. fahrenheit .. '°F, ' .. jdat.weather[1].description .. '.`'
utilities.send_reply(self, msg, output, true)
end
return weather

View File

@@ -1,51 +0,0 @@
local whoami = {}
local utilities = require('utilities')
whoami.command = 'whoami'
function whoami:init(config)
whoami.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('who', true):t('whoami').table
whoami.doc = [[```
Returns user and chat info for you or the replied-to message.
Alias: ]]..config.cmd_pat..[[who
```]]
end
function whoami:action(msg)
if msg.reply_to_message then
msg = msg.reply_to_message
msg.from.name = utilities.build_name(msg.from.first_name, msg.from.last_name)
end
local chat_id = math.abs(msg.chat.id)
if chat_id > 1000000000000 then
chat_id = chat_id - 1000000000000
end
local user = 'You are @%s, also known as *%s* `[%s]`'
if msg.from.username then
user = user:format(utilities.markdown_escape(msg.from.username), msg.from.name, msg.from.id)
else
user = 'You are *%s* `[%s]`,'
user = user:format(msg.from.name, msg.from.id)
end
local group = '@%s, also known as *%s* `[%s]`.'
if msg.chat.type == 'private' then
group = group:format(utilities.markdown_escape(self.info.username), self.info.first_name, self.info.id)
elseif msg.chat.username then
group = group:format(utilities.markdown_escape(msg.chat.username), msg.chat.title, chat_id)
else
group = '*%s* `[%s]`.'
group = group:format(msg.chat.title, chat_id)
end
local output = user .. ', and you are messaging ' .. group
utilities.send_message(self, msg.chat.id, output, true, msg.message_id, true)
end
return whoami

View File

@@ -1,114 +0,0 @@
local wikipedia = {}
local HTTPS = require('ssl.https')
local URL = require('socket.url')
local JSON = require('dkjson')
local utilities = require('utilities')
wikipedia.command = 'wikipedia <query>'
function wikipedia:init(config)
wikipedia.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('wikipedia', true):t('wiki', true):t('w', true).table
wikipedia.doc = [[```
]]..config.cmd_pat..[[wikipedia <query>
Returns an article from Wikipedia.
Aliases: ]]..config.cmd_pat..[[w, ]]..config.cmd_pat..[[wiki
```]]
end
local get_title = function(search)
for _,v in ipairs(search) do
if not v.snippet:match('may refer to:') then
return v.title
end
end
return false
end
function wikipedia:action(msg, config)
-- Get the query. If it's not in the message, check the replied-to message.
-- If those don't exist, send the help text.
local input = utilities.input(msg.text)
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
utilities.send_message(self, msg.chat.id, wikipedia.doc, true, msg.message_id, true)
return
end
end
-- This kinda sucks, but whatever.
input = input:gsub('#', ' sharp')
-- Disclaimer: These variables will be reused.
local jstr, res, jdat
-- All pretty standard from here.
local search_url = 'https://en.wikipedia.org/w/api.php?action=query&list=search&format=json&srsearch='
jstr, res = HTTPS.request(search_url .. URL.escape(input))
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
jdat = JSON.decode(jstr)
if jdat.query.searchinfo.totalhits == 0 then
utilities.send_reply(self, msg, config.errors.results)
return
end
local title = get_title(jdat.query.search)
if not title then
utilities.send_reply(self, msg, config.errors.results)
return
end
local res_url = 'https://en.wikipedia.org/w/api.php?action=query&prop=extracts&format=json&exchars=4000&exsectionformat=plain&titles='
jstr, res = HTTPS.request(res_url .. URL.escape(title))
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local _
local text = JSON.decode(jstr).query.pages
_, text = next(text)
if not text then
utilities.send_reply(self, msg, config.errors.results)
return
else
text = text.extract
end
-- Remove needless bits from the article, take only the first paragraph.
text = text:gsub('</?.->', '')
local l = text:find('\n')
if l then
text = text:sub(1, l-1)
end
-- This block can be annoying to read.
-- We use the initial title to make the url for later use. Then we remove
-- the extra bits that won't be in the article. We determine whether the
-- first part of the text is the title, and if so, we embolden that.
-- Otherwise, we prepend the text with a bold title. Then we append a "Read
-- More" link.
local url = 'https://en.wikipedia.org/wiki/' .. URL.escape(title)
title = title:gsub('%(.+%)', '')
local output
if string.match(text:sub(1, title:len()), title) then
output = '*' .. title .. '*' .. text:sub(title:len()+1)
else
output = '*' .. title:gsub('%(.+%)', '') .. '*\n' .. text:gsub('%[.+%]','')
end
output = output .. '\n[Read more.](' .. url:gsub('%)', '\\)') .. ')'
utilities.send_message(self, msg.chat.id, output, true, nil, true)
end
return wikipedia

View File

@@ -1,58 +0,0 @@
local xkcd = {}
local HTTP = require('socket.http')
local JSON = require('dkjson')
local utilities = require('utilities')
xkcd.command = 'xkcd [i]'
function xkcd:init(config)
xkcd.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('xkcd', true).table
xkcd.doc = [[```
]]..config.cmd_pat..[[xkcd [i]
Returns the latest xkcd strip and its alt text. If a number is given, returns that number strip. If "r" is passed in place of a number, returns a random strip.
```]]
end
function xkcd:action(msg, config)
local jstr, res = HTTP.request('http://xkcd.com/info.0.json')
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local latest = JSON.decode(jstr).num
local strip_num = latest
local input = utilities.input(msg.text)
if input then
if input == '404' then
utilities.send_message(self, msg.chat.id, '*404*\nNot found.', false, nil, true)
return
elseif tonumber(input) then
if tonumber(input) > latest then
strip_num = latest
else
strip_num = input
end
elseif input == 'r' then
strip_num = math.random(latest)
end
end
local res_url = 'http://xkcd.com/' .. strip_num .. '/info.0.json'
jstr, res = HTTP.request(res_url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
local output = '*' .. jdat.safe_title .. ' (*[' .. jdat.num .. '](' .. jdat.img .. ')*)*\n_' .. jdat.alt:gsub('_', '\\_') .. '_'
utilities.send_message(self, msg.chat.id, output, false, nil, true)
end
return xkcd

View File

@@ -1,62 +0,0 @@
-- Thanks to @TiagoDanin for writing the original plugin.
local youtube = {}
local HTTPS = require('ssl.https')
local URL = require('socket.url')
local JSON = require('dkjson')
local utilities = require('utilities')
function youtube:init(config)
if not config.google_api_key then
print('Missing config value: google_api_key.')
print('youtube.lua will not be enabled.')
return
end
youtube.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('youtube', true):t('yt', true).table
youtube.doc = [[```
]]..config.cmd_pat..[[youtube <query>
Returns the top result from YouTube.
Alias: ]]..config.cmd_pat..[[yt
```]]
end
youtube.command = 'youtube <query>'
function youtube:action(msg, config)
local input = utilities.input(msg.text)
if not input then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
utilities.send_message(self, msg.chat.id, youtube.doc, true, msg.message_id, true)
return
end
end
local url = 'https://www.googleapis.com/youtube/v3/search?key=' .. config.google_api_key .. '&type=video&part=snippet&maxResults=4&q=' .. URL.escape(input)
local jstr, res = HTTPS.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if jdat.pageInfo.totalResults == 0 then
utilities.send_reply(self, msg, config.errors.results)
return
end
local vid_url = 'https://www.youtube.com/watch?v=' .. jdat.items[1].id.videoId
local vid_title = jdat.items[1].snippet.title
vid_title = vid_title:gsub('%(.+%)',''):gsub('%[.+%]','')
local output = '[' .. vid_title .. '](' .. vid_url .. ')'
utilities.send_message(self, msg.chat.id, output, false, nil, true)
end
return youtube