Merge pull request #63 from bb010g/explicit-config

Explicit config
This commit is contained in:
Drew 2016-06-06 23:28:23 -04:00
commit 1de9e7f968
53 changed files with 611 additions and 604 deletions

116
README.md
View File

@ -35,29 +35,29 @@ When you are ready to start the bot, run `./launch.sh`. To stop the bot, send "/
Note that certain plugins, such as translate.lua and greetings.lua, will require privacy mode to be disabled. Additionally, some plugins may require or make use of various API keys:
- bing.lua: [Bing Search API](http://datamarket.azure.com/dataset/bing/search) key (`bing_api_key`)
- gImages.lua & youtube.lua: Google [API](http://console.developers.google.com) and [CSE](https://cse.google.com/cse) keys (`google_api_key`, `google_cse_key`)
- weather.lua: [OpenWeatherMap](http://openweathermap.org) API key (`owm_api_key`)
- lastfm.lua: [last.fm](http://last.fm/api) API key (`lastfm_api_key`)
- bible.lua: [Biblia](http://api.biblia.com) API key (`biblia_api_key`)
- cats.lua: [The Cat API](http://thecatapi.com) API key (optional) (`thecatapi_key`)
- apod.lua: [NASA](http://api.nasa.gov) API key (`nasa_api_key`)
- translate.lua: [Yandex](http://tech.yandex.com/keys/get) API key (`yandex_key`)
- chatter.lua: [SimSimi](http://developer.simsimi.com/signUp) API key (`simsimi_key`)
- `bing.lua`: [Bing Search API](http://datamarket.azure.com/dataset/bing/search) key (`bing_api_key`)
- `gImages.lua` & `youtube.lua`: Google [API](http://console.developers.google.com) and [CSE](https://cse.google.com/cse) keys (`google_api_key`, `google_cse_key`)
- `weather.lua`: [OpenWeatherMap](http://openweathermap.org) API key (`owm_api_key`)
- `lastfm.lua`: [last.fm](http://last.fm/api) API key (`lastfm_api_key`)
- `bible.lua`: [Biblia](http://api.biblia.com) API key (`biblia_api_key`)
- `cats.lua`: [The Cat API](http://thecatapi.com) API key (optional) (`thecatapi_key`)
- `apod.lua`: [NASA](http://api.nasa.gov) API key (`nasa_api_key`)
- `translate.lua`: [Yandex](http://tech.yandex.com/keys/get) API key (`yandex_key`)
- `chatter.lua`: [SimSimi](http://developer.simsimi.com/signUp) API key (`simsimi_key`)
* * *
## Control plugins
Some plugins are designed to be used by the bot's owner. Here are some examples, how they're used, and what they do.
| Plugin | Command | Function |
|:--------------|:-----------|:---------------------------------------------------|
| control.lua | /reload | Reloads all plugins and configuration. |
| | /halt | Shuts down the bot after saving the database. |
| | /script | Runs a list a bot commands, separated by newlines. |
| blacklist.lua | /blacklist | Blocks people from using the bot. |
| shell.lua | /run | Executes shell commands on the host system. |
| luarun.lua | /lua | Executes Lua commands in the bot's environment. |
| Plugin | Command | Function |
|:----------------|:-----------|:---------------------------------------------------|
| `control.lua` | /reload | Reloads all plugins and configuration. |
| | /halt | Shuts down the bot after saving the database. |
| | /script | Runs a list a bot commands, separated by newlines. |
| `blacklist.lua` | /blacklist | Blocks people from using the bot. |
| `shell.lua` | /run | Executes shell commands on the host system. |
| `luarun.lua` | /lua | Executes Lua commands in the bot's environment. |
* * *
@ -68,7 +68,7 @@ To get started, run `./tg-install.sh`. Note that this script is written for Ubun
Once the installation is finished, enable the `administration` plugin in your config file. **The administration plugin must be loaded before the `about` and `blacklist` plugins.** You may have reason to change the default TCP port (4567); if that is the case, remember to change it in `tg-launch.sh` as well. Run `./tg-launch.sh` in a separate screen/tmux window. You'll have to enter your phone number and go through the login process the first time. The script is set to restart tg after two seconds, so you'll need to Ctrl+C after exiting.
While tg is running, you may start/reload otouto with administration.lua enabled, and have access to a wide variety of administrative commands and automata. The administration "database" is stored in `administration.json`. To start using otouto to administrate a group (note that you must be the owner (or an administrator)), send `/gadd` to that group. For a list of commands, use `/ahelp`. Below I'll describe various functions now available to you.
While tg is running, you may start/reload otouto with `administration.lua` enabled, and have access to a wide variety of administrative commands and automata. The administration "database" is stored in `administration.json`. To start using otouto to administrate a group (note that you must be the owner (or an administrator)), send `/gadd` to that group. For a list of commands, use `/ahelp`. Below I'll describe various functions now available to you.
| Command | Function | Privilege | Internal? |
|:------------|:------------------------------------------------|:----------|:----------|
@ -151,46 +151,46 @@ Additionally, antiflood can be configured to automatically ban a user after he h
## List of plugins
| Plugin | Command | Function | Aliases |
|:--------------------|:------------------------------|:--------------------------------------------------------|:--------|
| help.lua | /help [command] | Returns a list of commands or command-specific help. | /h |
| about.lua | /about | Returns the about text as configured in config.lua. |
| ping.lua | /ping | The simplest plugin ever! |
| echo.lua | /echo text | Repeats a string of text. |
| bing.lua | /bing query | Returns Bing web results. | /g |
| gImages.lua | /images query | Returns a Google image result. | /i |
| gMaps.lua | /location query | Returns location data from Google Maps. | /loc |
| youtube.lua | /youtube query | Returns the top video result from YouTube. | /yt |
| wikipedia.lua | /wikipedia query | Returns the summary of a Wikipedia article. | /w |
| lastfm.lua | /np [username] | Returns the song you are currently listening to. |
| lastfm.lua | /fmset [username] | Sets your username for /np. /fmset -- will delete it. |
| hackernews.lua | /hackernews | Returns the latest posts from Hacker News. | /hn |
| imdb.lua | /imdb query | Returns film information from IMDb. |
| hearthstone.lua | /hearthstone query | Returns data for Hearthstone cards matching the query. | /hs |
| calc.lua | /calc expression | Returns conversions and solutions to math expressions. |
| bible.lua | /bible reference | Returns a Bible verse. | /b |
| urbandictionary.lua | /urban query | Returns the top definition from Urban Dictionary. | /ud |
| time.lua | /time query | Returns the time, date, and a timezone for a location. |
| weather.lua | /weather query | Returns current weather conditions for a given location. |
| nick.lua | /nick nickname | Set your nickname. /nick - will delete it. |
| whoami.lua | /whoami | Returns user and chat info for you or the replied-to user. | /who |
| eightball.lua | /8ball | Returns an answer from a magic 8-ball. |
| dice.lua | /roll nDr | Returns RNG dice rolls. Uses D&D notation. |
| reddit.lua | /reddit [r/subreddit ¦ query] | Returns the top results from a subreddit, query, or r/all. | /r |
| xkcd.lua | /xkcd [query] | Returns an xkcd strip and its alt text. |
| slap.lua | /slap target | Gives someone a slap (or worse). |
| commit.lua | /commit | Returns a commit message from whatthecommit.com. |
| fortune.lua | /fortune | Returns a UNIX fortune. |
| pun.lua | /pun | Returns a pun. |
| pokedex.lua | /pokedex query | Returns a Pokedex entry. | /dex |
| currency.lua | /cash [amount] cur to cur | Converts one currency to another. |
| cats.lua | /cat | Returns a cat picture. |
| reactions.lua | /reactions | Returns a list of emoticons which can be posted by the bot. |
| apod.lua | /apod [date] | Returns the NASA Astronomy Picture of the Day. |
| dilbert.lua | /dilbert [date] | Returns a Dilbert strip. |
| patterns.lua | /s/from/to/ | Search-and-replace using Lua patterns. |
| me.lua | /me | Returns user-specific data stored by the bot. |
| remind.lua | /remind <duration> <message> | Reminds a user of something after a duration of minutes. |
| Plugin | Command | Function | Aliases |
|:----------------------|:------------------------------|:--------------------------------------------------------|:--------|
| `help.lua` | /help [command] | Returns a list of commands or command-specific help. | /h |
| `about.lua` | /about | Returns the about text as configured in config.lua. |
| `ping.lua` | /ping | The simplest plugin ever! |
| `echo.lua` | /echo text | Repeats a string of text. |
| `bing.lua` | /bing query | Returns Bing web results. | /g |
| `gImages.lua` | /images query | Returns a Google image result. | /i |
| `gMaps.lua` | /location query | Returns location data from Google Maps. | /loc |
| `youtube.lua` | /youtube query | Returns the top video result from YouTube. | /yt |
| `wikipedia.lua` | /wikipedia query | Returns the summary of a Wikipedia article. | /w |
| `lastfm.lua` | /np [username] | Returns the song you are currently listening to. |
| `lastfm.lua` | /fmset [username] | Sets your username for /np. /fmset -- will delete it. |
| `hackernews.lua` | /hackernews | Returns the latest posts from Hacker News. | /hn |
| `imdb.lua` | /imdb query | Returns film information from IMDb. |
| `hearthstone.lua` | /hearthstone query | Returns data for Hearthstone cards matching the query. | /hs |
| `calc.lua` | /calc expression | Returns conversions and solutions to math expressions. |
| `bible.lua` | /bible reference | Returns a Bible verse. | /b |
| `urbandictionary.lua` | /urban query | Returns the top definition from Urban Dictionary. | /ud |
| `time.lua` | /time query | Returns the time, date, and a timezone for a location. |
| `weather.lua` | /weather query | Returns current weather conditions for a given location. |
| `nick.lua` | /nick nickname | Set your nickname. /nick - will delete it. |
| `whoami.lua` | /whoami | Returns user and chat info for you or the replied-to user. | /who |
| `eightball.lua` | /8ball | Returns an answer from a magic 8-ball. |
| `dice.lua` | /roll nDr | Returns RNG dice rolls. Uses D&D notation. |
| `reddit.lua` | /reddit [r/subreddit ¦ query] | Returns the top results from a subreddit, query, or r/all. | /r |
| `xkcd.lua` | /xkcd [query] | Returns an xkcd strip and its alt text. |
| `slap.lua` | /slap target | Gives someone a slap (or worse). |
| `commit.lua` | /commit | Returns a commit message from whatthecommit.com. |
| `fortune.lua` | /fortune | Returns a UNIX fortune. |
| `pun.lua` | /pun | Returns a pun. |
| `pokedex.lua` | /pokedex query | Returns a Pokedex entry. | /dex |
| `currency.lua` | /cash [amount] cur to cur | Converts one currency to another. |
| `cats.lua` | /cat | Returns a cat picture. |
| `reactions.lua` | /reactions | Returns a list of emoticons which can be posted by the bot. |
| `apod.lua` | /apod [date] | Returns the NASA Astronomy Picture of the Day. |
| `dilbert.lua` | /dilbert [date] | Returns a Dilbert strip. |
| `patterns.lua` | /s/from/to/ | Search-and-replace using Lua patterns. |
| `me.lua` | /me | Returns user-specific data stored by the bot. |
| `remind.lua` | /remind <duration> <message> | Reminds a user of something after a duration of minutes. |
* * *

36
bot.lua
View File

@ -6,18 +6,16 @@ local utilities -- Load miscellaneous and cross-plugin functions.
bot.version = '3.8'
function bot:init() -- The function run when the bot is started or reloaded.
function bot:init(config) -- The function run when the bot is started or reloaded.
bindings = require('bindings')
utilities = require('utilities')
self.config = require('config') -- Load configuration file.
assert(
self.config.bot_api_key and self.config.bot_api_key ~= '',
'You did not set your bot token in config.lua!'
config.bot_api_key and config.bot_api_key ~= '',
'You did not set your bot token in the config!'
)
self.BASE_URL = 'https://api.telegram.org/bot' .. self.config.bot_api_key .. '/'
self.BASE_URL = 'https://api.telegram.org/bot' .. config.bot_api_key .. '/'
-- Fetch bot information. Try until it succeeds.
repeat
@ -35,10 +33,10 @@ function bot:init() -- The function run when the bot is started or reloaded.
self.database.users[tostring(self.info.id)] = self.info
self.plugins = {} -- Load plugins.
for _,v in ipairs(self.config.plugins) do
for _,v in ipairs(config.plugins) do
local p = require('plugins.'..v)
table.insert(self.plugins, p)
if p.init then p.init(self) end
if p.init then p.init(self, config) end
end
print('@' .. self.info.username .. ', AKA ' .. self.info.first_name ..' ('..self.info.id..')')
@ -49,7 +47,7 @@ function bot:init() -- The function run when the bot is started or reloaded.
end
function bot:on_msg_receive(msg) -- The fn run whenever a message is received.
function bot:on_msg_receive(msg, config) -- The fn run whenever a message is received.
-- Cache user info for those involved.
utilities.create_user_entry(self, msg.from)
@ -63,20 +61,20 @@ function bot:on_msg_receive(msg) -- The fn run whenever a message is received.
msg = utilities.enrich_message(msg)
if msg.text:match('^/start .+') then
msg.text = '/' .. utilities.input(msg.text)
if msg.text:match('^'..config.cmd_pat..'start .+') then
msg.text = config.cmd_pat .. utilities.input(msg.text)
msg.text_lower = msg.text:lower()
end
for _,v in ipairs(self.plugins) do
for _,w in pairs(v.triggers) do
if string.match(msg.text:lower(), w) then
if string.match(msg.text_lower, w) then
local success, result = pcall(function()
return v.action(self, msg)
return v.action(self, msg, config)
end)
if not success then
utilities.send_reply(self, msg, 'Sorry, an unexpected error occurred.')
utilities.handle_exception(self, result, msg.from.id .. ': ' .. msg.text)
utilities.handle_exception(self, result, msg.from.id .. ': ' .. msg.text, config)
return
end
-- If the action returns a table, make that table the new msg.
@ -92,8 +90,8 @@ function bot:on_msg_receive(msg) -- The fn run whenever a message is received.
end
function bot:run()
bot.init(self) -- Actually start the script. Run the bot_init function.
function bot:run(config)
bot.init(self, config) -- Actually start the script.
while self.is_started do -- Start a loop while the bot should be running.
@ -102,7 +100,7 @@ function bot:run()
for _,v in ipairs(res.result) do -- Go through every new message.
self.last_update = v.update_id
if v.message then
bot.on_msg_receive(self, v.message)
bot.on_msg_receive(self, v.message, config)
end
end
else
@ -114,9 +112,9 @@ function bot:run()
utilities.save_data(self.info.username..'.db', self.database) -- Save the database.
for i,v in ipairs(self.plugins) do
if v.cron then -- Call each plugin's cron function, if it has one.
local result, err = pcall(function() v.cron(self) end)
local result, err = pcall(function() v.cron(self, config) end)
if not result then
utilities.handle_exception(self, err, 'CRON: ' .. i)
utilities.handle_exception(self, err, 'CRON: ' .. i, config)
end
end
end

View File

@ -18,6 +18,8 @@ I am otouto, the plugin-wielding, multipurpose Telegram bot.
Send /help to get started.
]],
-- The symbol that starts a command. Usually noted as '/' in documentation.
cmd_pat = '/',
-- https://datamarket.azure.com/dataset/bing/search
bing_api_key = '',

View File

@ -1,5 +1,6 @@
local bot = require('bot')
local instance = {}
local config = require('config')
return bot.run(instance)
return bot.run(instance, config)

View File

@ -10,18 +10,18 @@ about.triggers = {
''
}
function about:action(msg)
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 = self.config.about_text .. '\nBased on otouto v'..bot.version..' by topkecleon.'
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('^/about')
or msg.text_lower:match('^/about@'..self.info.username:lower())
or msg.text_lower:match('^/start') then
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

View File

@ -48,7 +48,7 @@ local utilities = require('utilities')
local administration = {}
function administration:init()
function administration:init(config)
-- Build the administration db if nonexistent.
if not self.database.administration then
self.database.administration = {
@ -64,19 +64,22 @@ function administration:init()
flood = {}
}
drua.PORT = self.config.cli_port or 4567
drua.PORT = config.cli_port or 4567
administration.init_command(self)
administration.init_flags(config.cmd_pat)
administration.init_command(self, config)
administration.doc = '`Returns a list of administrated groups.\nUse '..config.cmd_pat..'ahelp for more administrative commands.`'
end
administration.flags = {
function administration.init_flags(cmd_pat) return {
[1] = {
name = 'unlisted',
desc = 'Removes this group from the group listing.',
short = 'This group is unlisted.',
enabled = 'This group is no longer listed in /groups.',
disabled = 'This group is now listed in /groups.'
enabled = 'This group is no longer listed in '..cmd_pat..'groups.',
disabled = 'This group is now listed in '..cmd_pat..'groups.'
},
[2] = {
name = 'antisquig',
@ -105,7 +108,7 @@ administration.flags = {
name = 'antiflood',
desc = 'Prevents flooding by rate-limiting messages per user.',
short = 'This group automatically removes users who flood.',
enabled = 'Users will now be removed automatically for excessive messages. Use /antiflood to configure limits.',
enabled = 'Users will now be removed automatically for excessive messages. Use '..cmd_pat..'antiflood to configure limits.',
disabled = 'Users will no longer be removed automatically for excessive messages.',
kicked = 'You were automatically kicked from GROUPNAME for flooding.'
},
@ -116,7 +119,7 @@ administration.flags = {
enabled = 'This group will no longer remove users for being globally banned.',
disabled = 'This group will now remove users for being globally banned.'
}
}
} end
administration.antiflood = {
text = 10,
@ -139,13 +142,13 @@ administration.ranks = {
[5] = 'Owner'
}
function administration:get_rank(target, chat)
function administration:get_rank(target, chat, config)
target = tostring(target)
chat = tostring(chat)
-- Return 5 if the target is the bot or its owner.
if tonumber(target) == self.config.admin or tonumber(target) == self.info.id then
if tonumber(target) == config.admin or tonumber(target) == self.info.id then
return 5
end
@ -180,10 +183,10 @@ function administration:get_rank(target, chat)
end
function administration:get_target(msg)
function administration:get_target(msg, config)
local target = utilities.user_from_message(self, msg)
if target.id then
target.rank = administration.get_rank(self, target.id_str, msg.chat.id)
target.rank = administration.get_rank(self, target.id_str, msg.chat.id, config)
end
return target
end
@ -197,7 +200,7 @@ function administration:mod_format(id)
return output
end
function administration:get_desc(chat_id)
function administration:get_desc(chat_id, config)
local group = self.database.administration.groups[tostring(chat_id)]
local t = {}
@ -237,12 +240,12 @@ function administration:get_desc(chat_id)
if modstring ~= '' then
table.insert(t, '*Moderators:*\n' .. utilities.trim(modstring))
end
table.insert(t, 'Run /ahelp@' .. self.info.username .. ' for a list of commands.')
table.insert(t, 'Run '..config..'ahelp@' .. self.info.username .. ' for a list of commands.')
return table.concat(t, '\n\n')
end
function administration:update_desc(chat)
function administration:update_desc(chat, config)
local group = self.database.administration.groups[tostring(chat)]
local desc = 'Welcome to ' .. group.name .. '!\n'
if group.motd then desc = desc .. group.motd .. '\n' end
@ -250,12 +253,12 @@ function administration:update_desc(chat)
local gov = self.database.users[tostring(group.governor)]
desc = desc .. '\nGovernor: ' .. utilities.build_name(gov.first_name, gov.last_name) .. ' [' .. gov.id .. ']\n'
end
local s = '\n/desc@' .. self.info.username .. ' for more information.'
local s = '\n'..config.cmd_pat..'desc@' .. self.info.username .. ' for more information.'
desc = desc:sub(1, 250-s:len()) .. s
drua.channel_set_about(chat, desc)
end
function administration:kick_user(chat, target, reason)
function administration:kick_user(chat, target, reason, config)
drua.kick_user(chat, target)
local victim = target
if self.database.users[tostring(target)] then
@ -265,10 +268,10 @@ function administration:kick_user(chat, target, reason)
)
end
local group = self.database.administration.groups[tostring(chat)].name
utilities.handle_exception(self, victim..' kicked from '..group, reason)
utilities.handle_exception(self, victim..' kicked from '..group, reason, config)
end
function administration.init_command(self_)
function administration.init_command(self_, config)
administration.commands = {
{ -- generic, mostly autokicks
@ -277,9 +280,10 @@ function administration.init_command(self_)
privilege = 0,
interior = true,
action = function(self, msg, group)
action = function(self, msg, group, config)
local rank = administration.get_rank(self, msg.from.id, msg.chat.id)
local rank = administration.get_rank(self, msg.from.id, msg.chat.id, config)
local user = {}
if rank < 2 then
@ -360,7 +364,7 @@ function administration.init_command(self_)
-- the original guy.
if msg.new_chat_participant.id ~= msg.from.id then
new_user = {}
new_rank = administration.get_rank(self,noob.id, msg.chat.id)
new_rank = administration.get_rank(self,noob.id, msg.chat.id, config)
end
if new_rank == 0 then
@ -399,7 +403,7 @@ function administration.init_command(self_)
else
group.name = msg.new_chat_title
if group.grouptype == 'supergroup' then
administration.update_desc(self, msg.chat.id)
administration.update_desc(self, msg.chat.id, config)
end
end
elseif msg.new_chat_photo then
@ -425,7 +429,7 @@ function administration.init_command(self_)
end
if new_user ~= user and new_user.do_kick then
administration.kick_user(self, msg.chat.id, msg.new_chat_participant.id, new_user.reason)
administration.kick_user(self, msg.chat.id, msg.new_chat_participant.id, new_user.reason, config)
if new_user.output then
utilities.send_message(self, msg.new_chat_participant.id, new_user.output)
end
@ -450,7 +454,7 @@ function administration.init_command(self_)
end
if user.do_kick then
administration.kick_user(self, msg.chat.id, msg.from.id, user.reason)
administration.kick_user(self, msg.chat.id, msg.from.id, user.reason, config)
if user.output then
utilities.send_message(self, msg.from.id, user.output)
end
@ -460,7 +464,7 @@ function administration.init_command(self_)
end
if msg.new_chat_participant and not new_user.do_kick then
local output = administration.get_desc(self, msg.chat.id)
local output = administration.get_desc(self, msg.chat.id, config)
utilities.send_message(self, msg.new_chat_participant.id, output, true, nil, true)
end
@ -480,14 +484,14 @@ function administration.init_command(self_)
},
{ -- /groups
triggers = utilities.triggers(self_.info.username):t('groups').table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('groups').table,
command = 'groups',
privilege = 1,
interior = false,
doc = 'Returns a list of administrated groups.',
action = function(self, msg)
action = function(self, msg, group, config)
local output = ''
for _,v in ipairs(self.database.administration.activity) do
local group = self.database.administration.groups[v]
@ -509,22 +513,22 @@ function administration.init_command(self_)
},
{ -- /ahelp
triggers = utilities.triggers(self_.info.username):t('ahelp', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('ahelp', true).table,
command = 'ahelp \\[command]',
privilege = 1,
interior = false,
doc = 'Returns a list of realm-related commands for your rank (in a private message), or command-specific help.',
action = function(self, msg)
local rank = administration.get_rank(self, msg.from.id, msg.chat.id)
action = function(self, msg, group, config)
local rank = administration.get_rank(self, msg.from.id, msg.chat.id, config)
local input = utilities.get_word(msg.text_lower, 2)
if input then
input = input:gsub('^/', '')
input = input:gsub('^'..config.cmd_pat..'', '')
local doc
for _,action in ipairs(administration.commands) do
if action.keyword == input then
doc = '/' .. action.command:gsub('\\','') .. '\n' .. action.doc
doc = ''..config.cmd_pat..'' .. action.command:gsub('\\','') .. '\n' .. action.doc
break
end
end
@ -532,14 +536,14 @@ function administration.init_command(self_)
local output = '*Help for* _' .. input .. '_ :\n```\n' .. doc .. '\n```'
utilities.send_message(self, msg.chat.id, output, true, nil, true)
else
local output = 'Sorry, there is no help for that command.\n/ahelp@'..self.info.username
local output = 'Sorry, there is no help for that command.\n'..config.cmd_pat..'ahelp@'..self.info.username
utilities.send_reply(self, msg, output)
end
else
local output = '*Commands for ' .. administration.ranks[rank] .. ':*\n'
for i = 1, rank do
for _, val in ipairs(self.admin_temp.help[i]) do
output = output .. '/' .. val .. '\n'
output = output .. '' .. config.cmd_pat .. val .. '\n'
end
end
output = output .. 'Arguments: <required> \\[optional]'
@ -555,14 +559,14 @@ function administration.init_command(self_)
},
{ -- /ops
triggers = utilities.triggers(self_.info.username):t('ops'):t('oplist').table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('ops'):t('oplist').table,
command = 'ops',
privilege = 1,
interior = true,
doc = 'Returns a list of moderators and the governor for the group.',
action = function(self, msg, group)
action = function(self, msg, group, config)
local modstring = ''
for k,_ in pairs(group.mods) do
modstring = modstring .. administration.mod_format(self, k)
@ -585,15 +589,15 @@ function administration.init_command(self_)
},
{ -- /desc
triggers = utilities.triggers(self_.info.username):t('desc'):t('description').table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('desc'):t('description').table,
command = 'description',
privilege = 1,
interior = true,
doc = 'Returns a description of the group (in a private message), including its motd, rules, flags, governor, and moderators.',
action = function(self, msg)
local output = administration.get_desc(self, msg.chat.id)
action = function(self, msg, group, config)
local output = administration.get_desc(self, msg.chat.id, config)
if utilities.send_message(self, msg.from.id, output, true, nil, true) then
if msg.from.id ~= msg.chat.id then
utilities.send_reply(self, msg, 'I have sent you the requested information in a private message.')
@ -605,14 +609,14 @@ function administration.init_command(self_)
},
{ -- /rules
triggers = utilities.triggers(self_.info.username):t('rules?', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('rules?', true).table,
command = 'rules \\[i]',
privilege = 1,
interior = true,
doc = 'Returns the group\'s list of rules, or a specific rule.',
action = function(self, msg, group)
action = function(self, msg, group, config)
local output
local input = utilities.get_word(msg.text_lower, 2)
input = tonumber(input)
@ -633,14 +637,14 @@ function administration.init_command(self_)
},
{ -- /motd
triggers = utilities.triggers(self_.info.username):t('motd').table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('motd').table,
command = 'motd',
privilege = 1,
interior = true,
doc = 'Returns the group\'s message of the day.',
action = function(self, msg, group)
action = function(self, msg, group, config)
local output = 'No MOTD has been set for ' .. msg.chat.title .. '.'
if group.motd then
output = '*MOTD for ' .. msg.chat.title .. ':*\n' .. group.motd
@ -650,14 +654,14 @@ function administration.init_command(self_)
},
{ -- /link
triggers = utilities.triggers(self_.info.username):t('link').table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('link').table,
command = 'link',
privilege = 1,
interior = true,
doc = 'Returns the group\'s link.',
action = function(self, msg, group)
action = function(self, msg, group, config)
local output = 'No link has been set for ' .. msg.chat.title .. '.'
if group.link then
output = '[' .. msg.chat.title .. '](' .. group.link .. ')'
@ -667,18 +671,18 @@ function administration.init_command(self_)
},
{ -- /kickme
triggers = utilities.triggers(self_.info.username):t('leave'):t('kickme').table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('leave'):t('kickme').table,
command = 'kickme',
privilege = 1,
interior = true,
doc = 'Removes the user from the group.',
action = function(self, msg)
if administration.get_rank(self, msg.from.id) == 5 then
action = function(self, msg, group, config)
if administration.get_rank(self, msg.from.id, nil, config) == 5 then
utilities.send_reply(self, msg, 'I can\'t let you do that, '..msg.from.name..'.')
else
administration.kick_user(self, msg.chat.id, msg.from.id, 'kickme')
administration.kick_user(self, msg.chat.id, msg.from.id, 'kickme', config)
utilities.send_message(self, msg.chat.id, 'Goodbye, ' .. msg.from.name .. '!', true)
if msg.chat.type == 'supergroup' then
bindings.unbanChatMember(self, { chat_id = msg.chat.id, user_id = msg.from.id } )
@ -688,21 +692,21 @@ function administration.init_command(self_)
},
{ -- /kick
triggers = utilities.triggers(self_.info.username):t('kick', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('kick', true).table,
command = 'kick <user>',
privilege = 2,
interior = true,
doc = 'Removes a user from the group. The target may be specified via reply, username, or ID.',
action = function(self, msg)
local target = administration.get_target(self, msg)
action = function(self, msg, group, config)
local target = administration.get_target(self, msg, config)
if target.err then
utilities.send_reply(self, msg, target.err)
elseif target.rank > 1 then
utilities.send_reply(self, msg, target.name .. ' is too privileged to be kicked.')
else
administration.kick_user(self, msg.chat.id, target.id, 'kicked by ' .. msg.from.name)
administration.kick_user(self, msg.chat.id, target.id, 'kicked by ' .. msg.from.name, config)
utilities.send_message(self, msg.chat.id, target.name .. ' has been kicked.')
if msg.chat.type == 'supergroup' then
bindings.unbanChatMember(self, { chat_id = msg.chat.id, user_id = target.id } )
@ -712,15 +716,15 @@ function administration.init_command(self_)
},
{ -- /ban
triggers = utilities.triggers(self_.info.username):t('ban', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('ban', true).table,
command = 'ban <user>',
privilege = 2,
interior = true,
doc = 'Bans a user from the group. The target may be specified via reply, username, or ID.',
action = function(self, msg, group)
local target = administration.get_target(self, msg)
action = function(self, msg, group, config)
local target = administration.get_target(self, msg, config)
if target.err then
utilities.send_reply(self, msg, target.err)
elseif target.rank > 1 then
@ -728,7 +732,7 @@ function administration.init_command(self_)
elseif group.bans[target.id_str] then
utilities.send_reply(self, msg, target.name .. ' is already banned.')
else
administration.kick_user(self, msg.chat.id, target.id, 'banned by '..msg.from.name)
administration.kick_user(self, msg.chat.id, target.id, 'banned by '..msg.from.name, config)
utilities.send_reply(self, msg, target.name .. ' has been banned.')
group.bans[target.id_str] = true
end
@ -736,15 +740,15 @@ function administration.init_command(self_)
},
{ -- /unban
triggers = utilities.triggers(self_.info.username):t('unban', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('unban', true).table,
command = 'unban <user>',
privilege = 2,
interior = true,
doc = 'Unbans a user from the group. The target may be specified via reply, username, or ID.',
action = function(self, msg, group)
local target = administration.get_target(self, msg)
action = function(self, msg, group, config)
local target = administration.get_target(self, msg, config)
if target.err then
utilities.send_reply(self, msg, target.err)
else
@ -762,15 +766,15 @@ function administration.init_command(self_)
},
{ -- /setrules
triggers = utilities.triggers(self_.info.username):t('setrules', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('setrules', true).table,
command = 'setrules <rules>',
privilege = 3,
interior = true,
doc = 'Sets the group\'s rules. Rules will be automatically numbered. Separate rules with a new line. Markdown is supported. Pass "--" to delete the rules.',
action = function(self, msg, group)
local input = msg.text:match('^/setrules[@'..self.info.username..']*(.+)')
action = function(self, msg, group, config)
local input = msg.text:match('^'..config.cmd_pat..'setrules[@'..self.info.username..']*(.+)')
if input == ' --' or input == ' ' .. utilities.char.em_dash then
group.rules = {}
utilities.send_reply(self, msg, 'The rules have been cleared.')
@ -792,16 +796,16 @@ function administration.init_command(self_)
},
{ -- /changerule
triggers = utilities.triggers(self_.info.username):t('changerule', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('changerule', true).table,
command = 'changerule <i> <rule>',
privilege = 3,
interior = true,
doc = 'Changes a single rule. Pass "--" to delete the rule. If i is a number for which there is no rule, adds a rule by the next incremented number.',
action = function(self, msg, group)
action = function(self, msg, group, config)
local input = utilities.input(msg.text)
local output = 'usage: `/changerule <i> <newrule>`'
local output = 'usage: `'..config.cmd_pat..'changerule <i> <newrule>`'
if input then
local rule_num = tonumber(input:match('^%d+'))
local new_rule = utilities.input(input)
@ -829,14 +833,14 @@ function administration.init_command(self_)
},
{ -- /setmotd
triggers = utilities.triggers(self_.info.username):t('setmotd', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('setmotd', true).table,
command = 'setmotd <motd>',
privilege = 2,
interior = true,
doc = 'Sets the group\'s message of the day. Markdown is supported. Pass "--" to delete the message.',
action = function(self, msg, group)
action = function(self, msg, group, config)
local input = utilities.input(msg.text)
if not input and msg.reply_to_message and msg.reply_to_message.text:len() > 0 then
input = msg.reply_to_message.text
@ -852,7 +856,7 @@ function administration.init_command(self_)
utilities.send_message(self, msg.chat.id, output, true, nil, true)
end
if group.grouptype == 'supergroup' then
administration.update_desc(self, msg.chat.id)
administration.update_desc(self, msg.chat.id, config)
end
else
utilities.send_reply(self, msg, 'Please specify the new message of the day.')
@ -861,14 +865,14 @@ function administration.init_command(self_)
},
{ -- /setlink
triggers = utilities.triggers(self_.info.username):t('setlink', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('setlink', true).table,
command = 'setlink <link>',
privilege = 3,
interior = true,
doc = 'Sets the group\'s join link. Pass "--" to regenerate the link.',
action = function(self, msg, group)
action = function(self, msg, group, config)
local input = utilities.input(msg.text)
if input == '--' or input == utilities.char.em_dash then
group.link = drua.export_link(msg.chat.id)
@ -884,16 +888,16 @@ function administration.init_command(self_)
},
{ -- /alist
triggers = utilities.triggers(self_.info.username):t('alist').table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('alist').table,
command = 'alist',
privilege = 3,
interior = true,
doc = 'Returns a list of administrators. Owner is denoted with a star character.',
action = function(self, msg)
action = function(self, msg, config)
local output = '*Administrators:*\n'
output = output .. administration.mod_format(self, self.config.admin):gsub('\n', '\n')
output = output .. administration.mod_format(self, config.admin):gsub('\n', '\n')
for id,_ in pairs(self.database.administration.admins) do
output = output .. administration.mod_format(self, id)
end
@ -902,14 +906,14 @@ function administration.init_command(self_)
},
{ -- /flags
triggers = utilities.triggers(self_.info.username):t('flags?', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('flags?', true).table,
command = 'flag \\[i]',
privilege = 3,
interior = true,
doc = 'Returns a list of flags or toggles the specified flag.',
action = function(self, msg, group)
action = function(self, msg, group, config)
local input = utilities.input(msg.text)
if input then
input = utilities.get_word(input, 1)
@ -934,16 +938,16 @@ function administration.init_command(self_)
},
{ -- /antiflood
triggers = utilities.triggers(self_.info.username):t('antiflood', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('antiflood', true).table,
command = 'antiflood \\[<type> <i>]',
privilege = 3,
interior = true,
doc = 'Returns a list of antiflood values or sets one.',
action = function(self, msg, group)
action = function(self, msg, group, config)
if not group.flags[5] then
utilities.send_message(self, msg.chat.id, 'antiflood is not enabled. Use `/flag 5` to enable it.', true, nil, true)
utilities.send_message(self, msg.chat.id, 'antiflood is not enabled. Use `'..config.cmd_pat..'flag 5` to enable it.', true, nil, true)
else
if not group.antiflood then
group.antiflood = JSON.decode(JSON.encode(administration.antiflood))
@ -962,7 +966,7 @@ function administration.init_command(self_)
output = '*' .. key:gsub('^%l', string.upper) .. '* messages are now worth *' .. val .. '* points.'
end
else
output = 'usage: `/antiflood <type> <i>`\nexample: `/antiflood text 5`\nUse this command to configure the point values for each message type. When a user reaches 100 points, he is kicked. The points are reset each minute. The current values are:\n'
output = 'usage: `'..config.cmd_pat..'antiflood <type> <i>`\nexample: `'..config.cmd_pat..'antiflood text 5`\nUse this command to configure the point values for each message type. When a user reaches 100 points, he is kicked. The points are reset each minute. The current values are:\n'
for k,v in pairs(group.antiflood) do
output = output .. '*'..k..':* `'..v..'`\n'
end
@ -974,15 +978,15 @@ function administration.init_command(self_)
},
{ -- /mod
triggers = utilities.triggers(self_.info.username):t('mod', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('mod', true).table,
command = 'mod <user>',
privilege = 3,
interior = true,
doc = 'Promotes a user to a moderator. The target may be specified via reply, username, or ID.',
action = function(self, msg, group)
local target = administration.get_target(self, msg)
action = function(self, msg, group, config)
local target = administration.get_target(self, msg, config)
if target.err then
utilities.send_reply(self, msg, target.err)
else
@ -1001,15 +1005,15 @@ function administration.init_command(self_)
},
{ -- /demod
triggers = utilities.triggers(self_.info.username):t('demod', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('demod', true).table,
command = 'demod <user>',
privilege = 3,
interior = true,
doc = 'Demotes a moderator to a user. The target may be specified via reply, username, or ID.',
action = function(self, msg, group)
local target = administration.get_target(self, msg)
action = function(self, msg, group, config)
local target = administration.get_target(self, msg, config)
if target.err then
utilities.send_reply(self, msg, target.err)
else
@ -1027,15 +1031,15 @@ function administration.init_command(self_)
},
{ -- /gov
triggers = utilities.triggers(self_.info.username):t('gov', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('gov', true).table,
command = 'gov <user>',
privilege = 4,
interior = true,
doc = 'Promotes a user to the governor. The current governor will be replaced. The target may be specified via reply, username, or ID.',
action = function(self, msg, group)
local target = administration.get_target(self, msg)
action = function(self, msg, group, config)
local target = administration.get_target(self, msg, config)
if target.err then
utilities.send_reply(self, msg, target.err)
else
@ -1049,22 +1053,22 @@ function administration.init_command(self_)
end
if group.grouptype == 'supergroup' then
drua.channel_set_admin(msg.chat.id, target.id, 2)
administration.update_desc(self, msg.chat.id)
administration.update_desc(self, msg.chat.id, config)
end
end
end
},
{ -- /degov
triggers = utilities.triggers(self_.info.username):t('degov', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('degov', true).table,
command = 'degov <user>',
privilege = 4,
interior = true,
doc = 'Demotes the governor to a user. The administrator will become the new governor. The target may be specified via reply, username, or ID.',
action = function(self, msg, group)
local target = administration.get_target(self, msg)
action = function(self, msg, group, config)
local target = administration.get_target(self, msg, config)
if target.err then
utilities.send_reply(self, msg, target.err)
else
@ -1076,22 +1080,22 @@ function administration.init_command(self_)
end
if group.grouptype == 'supergroup' then
drua.channel_set_admin(msg.chat.id, target.id, 0)
administration.update_desc(self, msg.chat.id)
administration.update_desc(self, msg.chat.id, config)
end
end
end
},
{ -- /hammer
triggers = utilities.triggers(self_.info.username):t('hammer', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('hammer', true).table,
command = 'hammer <user>',
privilege = 4,
interior = false,
doc = 'Bans a user from all groups. The target may be specified via reply, username, or ID.',
action = function(self, msg, group)
local target = administration.get_target(self, msg)
action = function(self, msg, group, config)
local target = administration.get_target(self, msg, config)
if target.err then
utilities.send_reply(self, msg, target.err)
elseif target.rank > 3 then
@ -1099,7 +1103,7 @@ function administration.init_command(self_)
elseif self.database.blacklist[target.id_str] then
utilities.send_reply(self, msg, target.name .. ' is already globally banned.')
else
administration.kick_user(self, msg.chat.id, target.id, 'hammered by '..msg.from.name)
administration.kick_user(self, msg.chat.id, target.id, 'hammered by '..msg.from.name, config)
self.database.blacklist[target.id_str] = true
for k,v in pairs(self.database.administration.groups) do
if not v.flags[6] then
@ -1119,15 +1123,15 @@ function administration.init_command(self_)
},
{ -- /unhammer
triggers = utilities.triggers(self_.info.username):t('unhammer', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('unhammer', true).table,
command = 'unhammer <user>',
privilege = 4,
interior = false,
doc = 'Removes a global ban. The target may be specified via reply, username, or ID.',
action = function(self, msg)
local target = administration.get_target(self, msg)
action = function(self, msg, group, config)
local target = administration.get_target(self, msg, config)
if target.err then
utilities.send_reply(self, msg, target.err)
elseif not self.database.blacklist[target.id_str] then
@ -1143,15 +1147,15 @@ function administration.init_command(self_)
},
{ -- /admin
triggers = utilities.triggers(self_.info.username):t('admin', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('admin', true).table,
command = 'admin <user>',
privilege = 5,
interior = false,
doc = 'Promotes a user to an administrator. The target may be specified via reply, username, or ID.',
action = function(self, msg, group)
local target = administration.get_target(self, msg)
action = function(self, msg, group, config)
local target = administration.get_target(self, msg, config)
if target.err then
utilities.send_reply(self, msg, target.err)
elseif target.rank >= 4 then
@ -1170,15 +1174,15 @@ function administration.init_command(self_)
},
{ -- /deadmin
triggers = utilities.triggers(self_.info.username):t('deadmin', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('deadmin', true).table,
command = 'deadmin <user>',
privilege = 5,
interior = false,
doc = 'Demotes an administrator to a user. The target may be specified via reply, username, or ID.',
action = function(self, msg)
local target = administration.get_target(self, msg)
action = function(self, msg, group, config)
local target = administration.get_target(self, msg, config)
if target.err then
utilities.send_reply(self, msg, target.err)
else
@ -1198,14 +1202,14 @@ function administration.init_command(self_)
},
{ -- /gadd
triggers = utilities.triggers(self_.info.username):t('gadd', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('gadd', true).table,
command = 'gadd [i] ...',
privilege = 5,
interior = false,
doc = 'Adds a group to the administration system. Pass numbers as arguments to enable those flags immediately. For example, this would add the group and enable the unlisted flag, antibot, and antiflood:\n/gadd 1 4 5',
action = function(self, msg)
action = function(self, msg, group, config)
if self.database.administration.groups[msg.chat.id_str] then
utilities.send_reply(self, msg, 'I am already administrating this group.')
else
@ -1237,7 +1241,7 @@ function administration.init_command(self_)
autokicks = {},
autoban = 3
}
administration.update_desc(self, msg.chat.id)
administration.update_desc(self, msg.chat.id, config)
table.insert(self.database.administration.activity, msg.chat.id_str)
utilities.send_reply(self, msg, 'I am now administrating this group.')
drua.channel_set_admin(msg.chat.id, self.info.id, 2)
@ -1246,14 +1250,14 @@ function administration.init_command(self_)
},
{ -- /grem
triggers = utilities.triggers(self_.info.username):t('grem', true):t('gremove', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('grem', true):t('gremove', true).table,
command = 'gremove \\[chat]',
privilege = 5,
interior = false,
doc = 'Removes a group from the administration system.',
action = function(self, msg)
action = function(self, msg, group, config)
local input = utilities.input(msg.text) or msg.chat.id_str
local output
if self.database.administration.groups[input] then
@ -1277,14 +1281,14 @@ function administration.init_command(self_)
},
{ -- /glist
triggers = utilities.triggers(self_.info.username):t('glist', false).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('glist', false).table,
command = 'glist',
privilege = 5,
interior = false,
doc = 'Returns a list (in a private message) of all administrated groups with their governors and links.',
action = function(self, msg)
action = function(self, msg, group, config)
local output = ''
if utilities.table_size(self.database.administration.groups) > 0 then
for k,v in pairs(self.database.administration.groups) do
@ -1306,14 +1310,14 @@ function administration.init_command(self_)
},
{ -- /broadcast
triggers = utilities.triggers(self_.info.username):t('broadcast', true).table,
triggers = utilities.triggers(self_.info.username, config.cmd_pat):t('broadcast', true).table,
command = 'broadcast <message>',
privilege = 5,
interior = false,
doc = 'Broadcasts a message to all administrated groups.',
action = function(self, msg)
action = function(self, msg, group, config)
local input = utilities.input(msg.text)
if not input then
utilities.send_reply(self, msg, 'Give me something to broadcast.')
@ -1357,17 +1361,17 @@ function administration.init_command(self_)
end
end
function administration:action(msg)
function administration:action(msg, config)
for _,command in ipairs(administration.commands) do
for _,trigger in pairs(command.triggers) do
if msg.text_lower:match(trigger) then
if command.interior and not self.database.administration.groups[msg.chat.id_str] then
break
end
if administration.get_rank(self, msg.from.id, msg.chat.id) < command.privilege then
if administration.get_rank(self, msg.from.id, msg.chat.id, config) < command.privilege then
break
end
local res = command.action(self, msg, self.database.administration.groups[msg.chat.id_str])
local res = command.action(self, msg, self.database.administration.groups[msg.chat.id_str], config)
if res ~= true then
return res
end
@ -1388,6 +1392,5 @@ function administration:cron()
end
administration.command = 'groups'
administration.doc = '`Returns a list of administrated groups.\nUse /ahelp for more administrative commands.`'
return administration

View File

@ -8,33 +8,33 @@ local URL = require('socket.url')
local utilities = require('utilities')
apod.command = 'apod [date]'
apod.doc = [[```
/apod [query]
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.
/apodhd [query]
]]..config.cmd_pat..[[apodhd [query]
Returns the image in HD, if available.
/apodtext [query]
]]..config.cmd_pat..[[apodtext [query]
Returns the explanation of the APOD.
Source: nasa.gov
```]]
function apod:init()
apod.triggers = utilities.triggers(self.info.username)
:t('apod', true):t('apodhd', true):t('apodtext', true).table
end
function apod:action(msg)
function apod:action(msg, config)
if not self.config.nasa_api_key then
self.config.nasa_api_key = 'DEMO_KEY'
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=' .. self.config.nasa_api_key
local url = 'https://api.nasa.gov/planetary/apod?api_key=' .. config.nasa_api_key
if input then
if input:match('(%d+)%-(%d+)%-(%d+)$') then
@ -52,26 +52,26 @@ function apod:action(msg)
local jstr, res = HTTPS.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)
if jdat.error then
utilities.send_reply(msg, self.config.errors.results)
utilities.send_reply(self, msg, config.errors.results)
return
end
local img_url = jdat.url
if string.match(msg.text, '^/apodhd*') then
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, '^/apodtext*') then
if string.match(msg.text, '^'..config.cmd_pat..'apodtext*') then
output = output .. '\n' .. jdat.explanation
disable_page_preview = true
end

View File

@ -3,13 +3,13 @@ local bandersnatch = {}
local utilities = require('utilities')
bandersnatch.command = 'bandersnatch'
bandersnatch.doc = [[```
Shun the frumious Bandersnatch.
Alias: /bc
```]]
function bandersnatch:init()
bandersnatch.triggers = utilities.triggers(self.info.username):t('bandersnatch'):t('bc').table
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" }

View File

@ -4,24 +4,24 @@ local HTTP = require('socket.http')
local URL = require('socket.url')
local utilities = require('utilities')
function bible:init()
if not self.config.biblia_api_key then
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):t('bible', true):t('b', true).table
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>'
bible.doc = [[```
/bible <reference>
Returns a verse from the American Standard Version of the Bible, or an apocryphal verse from the King James Version. Results from biblia.com.
Alias: /b
```]]
function bible:action(msg)
function bible:action(msg, config)
local input = utilities.input(msg.text)
if not input then
@ -29,17 +29,17 @@ function bible:action(msg)
return
end
local url = 'http://api.biblia.com/v1/bible/content/ASV.txt?key=' .. self.config.biblia_api_key .. '&passage=' .. URL.escape(input)
local url = 'http://api.biblia.com/v1/bible/content/ASV.txt?key=' .. config.biblia_api_key .. '&passage=' .. URL.escape(input)
local 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=' .. self.config.biblia_api_key .. '&passage=' .. URL.escape(input)
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 = self.config.errors.results
output = config.errors.results
end
if output:len() > 4000 then

View File

@ -15,12 +15,12 @@ blacklist.triggers = {
''
}
function blacklist:action(msg)
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('^/blacklist') then return true end
if msg.from.id ~= self.config.admin 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

View File

@ -5,16 +5,16 @@ local HTTPS = require('ssl.https')
local utilities = require('utilities')
calc.command = 'calc <expression>'
calc.doc = [[```
/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.
```]]
function calc:init()
calc.triggers = utilities.triggers(self.info.username):t('calc', true).table
end
function calc:action(msg)
function calc:action(msg, config)
local input = utilities.input(msg.text)
if not input then
@ -30,7 +30,7 @@ function calc:action(msg)
local output = HTTPS.request(url)
if not output then
utilities.send_reply(self, msg, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end

View File

@ -3,28 +3,28 @@ local cats = {}
local HTTP = require('socket.http')
local utilities = require('utilities')
function cats:init()
if not self.config.thecatapi_key then
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):t('cat').table
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)
function cats:action(msg, config)
local url = 'http://thecatapi.com/api/images/get?format=html&type=jpg'
if self.config.thecatapi_key then
url = url .. '&api_key=' .. self.config.thecatapi_key
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(msg, self.config.errors.connection)
utilities.send_reply(self, msg, onfig.errors.connection)
return
end

View File

@ -6,10 +6,9 @@ local HTTP = require('socket.http')
local URL = require('socket.url')
local JSON = require('dkjson')
local bindings = require('bindings')
local utilities = require('utilities')
function chatter:init()
if not self.config.simsimi_key then
function chatter:init(config)
if not config.simsimi_key then
print('Missing config value: simsimi_key.')
print('chatter.lua will not be enabled.')
return
@ -22,7 +21,7 @@ end
chatter.base_url = 'http://%sapi.simsimi.com/request.p?key=%s&lc=%s&ft=1.0&text=%s'
function chatter:action(msg)
function chatter:action(msg, config)
if msg.text == '' then return true end
@ -34,7 +33,7 @@ function chatter:action(msg)
--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('^/')
or msg.text:match('^'..config.CMD_PAT)
or msg.text == ''
) then
return true
@ -47,17 +46,17 @@ function chatter:action(msg)
local sandbox = self.config.simsimi_trial and 'sandbox.' or ''
local url = chatter.base_url:format(sandbox, self.config.simsimi_key, self.config.lang, URL.escape(input))
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, self.config.errors.chatter_connection)
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, self.config.errors.chatter_response)
utilities.send_message(self, msg.chat.id, config.errors.chatter_response)
return
end
local output = jdat.response

View File

@ -7,8 +7,8 @@ local utilities = require('utilities')
commit.command = 'commit'
commit.doc = '`Returns a commit message from whatthecommit.com.`'
function commit:init()
commit.triggers = utilities.triggers(self.info.username):t('commit').table
function commit:init(config)
commit.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('commit').table
end
local commits = {

View File

@ -3,37 +3,43 @@ local control = {}
local bot = require('bot')
local utilities = require('utilities')
function control:init()
control.triggers = utilities.triggers(self.info.username):t('reload'):t('halt').table
table.insert(control.triggers, '^/script')
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)
function control:action(msg, config)
if msg.from.id ~= self.config.admin then
if msg.from.id ~= config.admin then
return
end
if msg.date < os.time() - 1 then return end
if msg.text:match('^'..utilities.INVOCATION_PATTERN..'reload') then
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
package.loaded['bindings'] = nil
package.loaded['utilities'] = nil
package.loaded['config'] = nil
end
bot.init(self)
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:match('^'..utilities.INVOCATION_PATTERN..'halt') then
elseif msg.text_lower:match('^'..cmd_pat..'halt') then
self.is_started = false
utilities.send_reply(self, msg, 'Stopping bot!')
elseif msg.text:match('^'..utilities.INVOCATION_PATTERN..'script') then
local input = msg.text:match('^'..utilities.INVOCATION_PATTERN..'script\n(.+)')
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/script\n/command <arg>\n...\n```', true)
utilities.send_reply(self, msg, 'usage: ```\n'..cmd_pat..'script\n'..cmd_pat..'command <arg>\n...\n```', true)
return
end
input = input .. '\n'

View File

@ -4,18 +4,18 @@ local HTTPS = require('ssl.https')
local utilities = require('utilities')
currency.command = 'cash [amount] <from> to <to>'
currency.doc = [[```
/cash [amount] <from> to <to>
Example: /cash 5 USD to EUR
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.
```]]
function currency:init()
currency.triggers = utilities.triggers(self.info.username):t('cash', true).table
end
function currency:action(msg)
function currency:action(msg, config)
local input = msg.text:upper()
if not input:match('%a%a%a TO %a%a%a') then
@ -36,13 +36,13 @@ function currency:action(msg)
url = url .. '?from=' .. from .. '&to=' .. to .. '&a=' .. amount
local str, res = HTTPS.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, self.config.errors.connection)
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, self.config.errors.results)
utilities.send_reply(self, msg, config.errors.results)
return
end

View File

@ -3,13 +3,13 @@ local dice = {}
local utilities = require('utilities')
dice.command = 'roll <nDr>'
dice.doc = [[```
/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.
```]]
function dice:init()
dice.triggers = utilities.triggers(self.info.username):t('roll', true).table
end
function dice:action(msg)

View File

@ -6,18 +6,18 @@ local bindings = require('bindings')
local utilities = require('utilities')
dilbert.command = 'dilbert [date]'
dilbert.doc = [[```
/dilbert [YYYY-MM-DD]
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
```]]
function dilbert:init()
dilbert.triggers = utilities.triggers(self.info.username):t('dilbert', true).table
end
function dilbert:action(msg)
function dilbert:action(msg, config)
bindings.sendChatAction(self, { chat_id = msg.chat.id, action = 'upload_photo' } )
@ -28,7 +28,7 @@ function dilbert:action(msg)
local url = 'http://dilbert.com/strip/' .. URL.escape(input)
local str, res = HTTP.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end

View File

@ -3,13 +3,13 @@ local echo = {}
local utilities = require('utilities')
echo.command = 'echo <text>'
echo.doc = [[```
/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.
```]]
function echo:init()
echo.triggers = utilities.triggers(self.info.username):t('echo', true).table
end
function echo:action(msg)

View File

@ -5,8 +5,9 @@ local utilities = require('utilities')
eightball.command = '8ball'
eightball.doc = '`Returns an answer from a magic 8-ball!`'
function eightball:init()
eightball.triggers = utilities.triggers(self.info.username, {'[Yy]/[Nn]%p*$'}):t('8ball', true).table
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 = {

View File

@ -4,7 +4,7 @@ local fortune = {}
local utilities = require('utilities')
function fortune:init()
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.')
@ -12,7 +12,7 @@ function fortune:init()
return
end
fortune.triggers = utilities.triggers(self.info.username):t('fortune').table
fortune.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('fortune').table
end
fortune.command = 'fortune'

View File

@ -8,28 +8,28 @@ local URL = require('socket.url')
local JSON = require('dkjson')
local utilities = require('utilities')
function gImages:init()
if not self.config.google_api_key then
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 self.config.google_cse_key then
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):t('image', true):t('i', true):t('insfw', true).table
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>'
gImages.doc = [[```
/image <query>
Returns a randomized top result from Google Images. Safe search is enabled by default; use "/insfw" to disable it. NSFW results will not display an image preview.
Alias: /i
```]]
function gImages:action(msg)
function gImages:action(msg, config)
local input = utilities.input(msg.text)
if not input then
@ -41,9 +41,9 @@ function gImages:action(msg)
end
end
local url = 'https://www.googleapis.com/customsearch/v1?&searchType=image&imgSize=xlarge&alt=json&num=8&start=1&key=' .. self.config.google_api_key .. '&cx=' .. self.config.google_cse_key
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, '^/i[mage]*nsfw') then
if not string.match(msg.text, '^'..config.cmd_pat..'i[mage]*nsfw') then
url = url .. '&safe=high'
end
@ -51,13 +51,13 @@ function gImages:action(msg)
local jstr, res = HTTPS.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, self.config.errors.connection)
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, self.config.errors.results)
utilities.send_reply(self, msg, config.errors.results)
return
end

View File

@ -4,17 +4,17 @@ local bindings = require('bindings')
local utilities = require('utilities')
gMaps.command = 'location <query>'
gMaps.doc = [[```
/location <query>
Returns a location from Google Maps.
Alias: /loc
```]]
function gMaps:init()
gMaps.triggers = utilities.triggers(self.info.username):t('location', true):t('loc', true).table
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)
function gMaps:action(msg, config)
local input = utilities.input(msg.text)
if not input then
@ -26,7 +26,7 @@ function gMaps:action(msg)
end
end
local coords = utilities.get_coords(self, input)
local coords = utilities.get_coords(input, config)
if type(coords) == 'string' then
utilities.send_reply(self, msg, coords)
return

View File

@ -6,17 +6,17 @@ local JSON = require('dkjson')
local utilities = require('utilities')
gSearch.command = 'google <query>'
gSearch.doc = [[```
/google <query>
Returns four (if group) or eight (if private message) results from Google. Safe search is enabled by default, use "/gnsfw" to disable it.
Alias: /g
```]]
function gSearch:init()
gSearch.triggers = utilities.triggers(self.info.username):t('g', true):t('google', true):t('gnsfw', true).table
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)
function gSearch:action(msg, config)
local input = utilities.input(msg.text)
if not input then
@ -36,7 +36,7 @@ function gSearch:action(msg)
url = url .. '&rsz=4'
end
if not string.match(msg.text, '^/g[oogle]*nsfw') then
if not string.match(msg.text, '^'..config.cmd_pat..'g[oogle]*nsfw') then
url = url .. '&safe=active'
end
@ -44,17 +44,17 @@ function gSearch:action(msg)
local jstr, res = HTTPS.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, self.config.errors.connection)
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, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end
if not jdat.responseData.results[1] then
utilities.send_reply(self, msg, self.config.errors.results)
utilities.send_reply(self, msg, config.errors.results)
return
end

View File

@ -6,46 +6,44 @@ local greetings = {}
local utilities = require('utilities')
function greetings:init()
if not self.config.greetings then
self.config.greetings = {
['Hello, #NAME.'] = {
'hello',
'hey',
'sup',
'hi',
'good morning',
'good day',
'good afternoon',
'good evening'
},
['Goodbye, #NAME.'] = {
'bye',
'later',
'see ya',
'good night'
},
['Welcome back, #NAME.'] = {
'i\'m home',
'i\'m back'
},
['You\'re welcome, #NAME.'] = {
'thanks',
'thank you'
}
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'
}
end
}
greetings.triggers = {
self.info.first_name:lower() .. '%p*$'
}
end
function greetings:action(msg)
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(self.config.greetings) do
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)))

View File

@ -6,22 +6,22 @@ local bindings = require('bindings')
local utilities = require('utilities')
hackernews.command = 'hackernews'
hackernews.doc = [[```
Returns four (if group) or eight (if private message) top stories from Hacker News.
Alias: /hn
```]]
function hackernews:init()
hackernews.triggers = utilities.triggers(self.info.username):t('hackernews', true):t('hn', true).table
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)
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, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end
@ -37,7 +37,7 @@ function hackernews:action(msg)
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, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end
local res_jdat = JSON.decode(jstr)
@ -47,7 +47,7 @@ function hackernews:action(msg)
end
local url = res_jdat.url
if not url then
utilities.send_reply(self, msg, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end
if url:find('%(') then

View File

@ -6,7 +6,7 @@ local hearthstone = {}
local JSON = require('dkjson')
local utilities = require('utilities')
function hearthstone:init()
function hearthstone:init(config)
if not self.database.hearthstone or os.time() > self.database.hearthstone.expiration then
print('Downloading Hearthstone database...')
@ -36,15 +36,15 @@ function hearthstone:init()
end
hearthstone.triggers = utilities.triggers(self.info.username):t('hearthstone', true):t('hs').table
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>'
hearthstone.doc = [[```
/hearthstone <query>
Returns Hearthstone card info.
Alias: /hs
```]]
local function format_card(card)
@ -102,7 +102,7 @@ local function format_card(card)
end
function hearthstone:action(msg)
function hearthstone:action(msg, config)
local input = utilities.input(msg.text_lower)
if not input then
@ -119,7 +119,7 @@ function hearthstone:action(msg)
output = utilities.trim(output)
if output:len() == 0 then
utilities.send_reply(self, msg, self.config.errors.results)
utilities.send_reply(self, msg, config.errors.results)
return
end

View File

@ -7,26 +7,26 @@ local utilities = require('utilities')
local help_text
function help:init()
function help:init(config)
local commandlist = {}
help_text = '*Available commands:*\n/'
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• /' .. plugin.command:gsub('%[', '\\[')
--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/') .. '\nArguments: <required> [optional]'
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):t('help', true):t('h', true).table
help.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('help', true):t('h', true).table
end

View File

@ -6,16 +6,16 @@ local JSON = require('dkjson')
local utilities = require('utilities')
imdb.command = 'imdb <query>'
imdb.doc = [[```
/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.
```]]
function imdb:init()
imdb.triggers = utilities.triggers(self.info.username):t('imdb', true).table
end
function imdb:action(msg)
function imdb:action(msg, config)
local input = utilities.input(msg.text)
if not input then
@ -31,14 +31,14 @@ function imdb:action(msg)
local jstr, res = HTTP.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, self.config.errors.connection)
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, self.config.errors.results)
utilities.send_reply(self, msg, config.errors.results)
return
end

View File

@ -8,33 +8,33 @@ local URL = require('socket.url')
local JSON = require('dkjson')
local utilities = require('utilities')
function lastfm:init()
if not self.config.lastfm_api_key then
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):t('lastfm', true):t('np', true):t('fmset', true).table
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'
lastfm.doc = [[```
/np [username]
Returns what you are or were last listening to. If you specify a username, info will be returned for that username.
/fmset <username>
Sets your last.fm username. Otherwise, /np will use your Telegram username. Use "/fmset --" to delete it.
```]]
function lastfm:action(msg)
function lastfm:action(msg, config)
local input = utilities.input(msg.text)
if string.match(msg.text, '^/lastfm') then
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, '^/fmset') then
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
@ -47,7 +47,7 @@ function lastfm:action(msg)
return
end
local url = 'http://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&format=json&limit=1&api_key=' .. self.config.lastfm_api_key .. '&user='
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 = ''
@ -57,10 +57,10 @@ function lastfm:action(msg)
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 /fmset <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 /fmset.')
utilities.send_reply(self, msg, 'Please specify your last.fm username or set it with '..config.cmd_pat..'fmset.')
return
end
@ -72,13 +72,13 @@ function lastfm:action(msg)
jstr, res = HTTP.request(url)
end)
if res ~= 200 then
utilities.send_reply(self, msg, self.config.errors.connection)
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 /fmset.')
utilities.send_reply(self, msg, 'Please specify your last.fm username or set it with '..config.cmd_pat..'fmset.')
return
end

View File

@ -4,13 +4,13 @@ local utilities = require('utilities')
local URL = require('socket.url')
local JSON = require('dkjson')
function luarun:init()
luarun.triggers = utilities.triggers(self.info.username):t('lua', true):t('return', true).table
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)
function luarun:action(msg, config)
if msg.from.id ~= self.config.admin then
if msg.from.id ~= config.admin then
return true
end
@ -20,7 +20,7 @@ function luarun:action(msg)
return
end
if msg.text_lower:match('^/return') then
if msg.text_lower:match('^'..config.cmd_pat..'return') then
input = 'return ' .. input
end
@ -32,8 +32,8 @@ function luarun:action(msg)
local URL = require('socket.url')
local HTTP = require('socket.http')
local HTTPS = require('ssl.https')
return function (self, msg) ]] .. input .. [[ end
]] )()(self, msg)
return function (self, msg, config) ]] .. input .. [[ end
]] )()(self, msg, config)
if output == nil then
output = 'Done!'
else

View File

@ -2,15 +2,15 @@ local me = {}
local utilities = require('utilities')
function me:init()
me.triggers = utilities.triggers(self.info.username):t('me', true).table
function me:init(config)
me.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('me', true).table
end
function me:action(msg)
function me:action(msg, config)
local target = self.database.users[msg.from.id_str]
if msg.from.id == self.config.admin and (msg.reply_to_message or utilities.input(msg.text)) then
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)

View File

@ -3,20 +3,20 @@ local nick = {}
local utilities = require('utilities')
nick.command = 'nick <nickname>'
nick.doc = [[```
/nick <nickname>
Set your nickname. Use "/nick --" to delete it.
```]]
function nick:init()
nick.triggers = utilities.triggers(self.info.username):t('nick', true).table
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)
function nick:action(msg, config)
local target = msg.from
if msg.from.id == self.config.admin and msg.reply_to_message then
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

View File

@ -4,12 +4,12 @@ local ping = {}
local utilities = require('utilities')
function ping:init()
ping.triggers = utilities.triggers(self.info.username):t('ping'):t('annyong').table
function ping:init(config)
ping.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('ping'):t('annyong').table
end
function ping:action(msg)
local output = msg.text_lower:match('^/ping') and 'Pong!' or 'Annyong.'
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

View File

@ -6,17 +6,17 @@ local bindings = require('bindings')
local utilities = require('utilities')
pokedex.command = 'pokedex <query>'
pokedex.doc = [[```
/pokedex <query>
Returns a Pokedex entry from pokeapi.co.
Alias: /dex
```]]
function pokedex:init()
pokedex.triggers = utilities.triggers(self.info.username):t('pokedex', true):t('dex', true).table
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)
function pokedex:action(msg, config)
bindings.sendChatAction(self, { chat_id = msg.chat.id, action = 'typing' } )
@ -35,7 +35,7 @@ function pokedex:action(msg)
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, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end
@ -44,7 +44,7 @@ function pokedex:action(msg)
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, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end

View File

@ -4,13 +4,13 @@ local HTTP = require('socket.http')
local utilities = require('utilities')
preview.command = 'preview <link>'
preview.doc = [[```
/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.
```]]
function preview:init()
preview.triggers = utilities.triggers(self.info.username):t('preview', true).table
end
function preview:action(msg)

View File

@ -5,8 +5,8 @@ local utilities = require('utilities')
pun.command = 'pun'
pun.doc = '`Returns a pun.`'
function pun:init()
pun.triggers = utilities.triggers(self.info.username):t('pun').table
function pun:init(config)
pun.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('pun').table
end
local puns = {

View File

@ -25,24 +25,24 @@ local mapping = {
local help
function reactions:init()
function reactions:init(config)
-- Generate a "help" message triggered by "/reactions".
help = 'Reactions:\n'
reactions.triggers = utilities.triggers(self.info.username):t('reactions').table
reactions.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('reactions').table
for trigger,reaction in pairs(mapping) do
help = help .. '' .. utilities.INVOCATION_PATTERN .. trigger:gsub('.%?', '') .. ': ' .. reaction .. '\n'
table.insert(reactions.triggers, utilities.INVOCATION_PATTERN..trigger)
table.insert(reactions.triggers, utilities.INVOCATION_PATTERN..trigger..'@'..self.info.username:lower())
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)
if string.match(msg.text_lower, utilities.INVOCATION_PATTERN..'reactions') then
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, utilities.INVOCATION_PATTERN..trigger) then
if string.match(msg.text_lower, config.cmd_pat..trigger) then
utilities.send_message(self, msg.chat.id, reaction)
return
end

View File

@ -6,14 +6,14 @@ local JSON = require('dkjson')
local utilities = require('utilities')
reddit.command = 'reddit [r/subreddit | query]'
reddit.doc = [[```
/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: /r, /r/subreddit
```]]
function reddit:init()
reddit.triggers = utilities.triggers(self.info.username, {'^/r/'}):t('reddit', true):t('r', true):t('r/', true).table
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)
@ -39,7 +39,7 @@ 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)
function reddit:action(msg, config)
-- Eight results in PM, four results elsewhere.
local limit = 4
if msg.chat.type == 'private' then
@ -48,7 +48,7 @@ function reddit:action(msg)
local text = msg.text_lower
if text:match('^/r/.') then
-- Normalize input so this hack works easily.
text = msg.text_lower:gsub('^/r/', '/r r/')
text = msg.text_lower:gsub('^/r/', config.cmd_pat..'r r/')
end
local input = utilities.input(text)
local source, url
@ -69,11 +69,11 @@ function reddit:action(msg)
end
local jstr, res = HTTP.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, self.config.errors.connection)
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, self.config.errors.results)
utilities.send_reply(self, msg, config.errors.results)
else
local output = format_results(jdat.data.children)
output = source .. output

View File

@ -3,15 +3,15 @@ local remind = {}
local utilities = require('utilities')
remind.command = 'remind <duration> <message>'
remind.doc = [[```
/remind <duration> <message>
Repeats a message after a duration of time, in minutes.
```]]
function remind:init()
function remind:init(config)
self.database.reminders = self.database.reminders or {}
remind.triggers = utilities.triggers(self.info.username):t('remind', true).table
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)

View File

@ -2,26 +2,25 @@ local setandget = {}
local utilities = require('utilities')
function setandget:init()
function setandget:init(config)
self.database.setandget = self.database.setandget or {}
setandget.triggers = utilities.triggers(self.info.username):t('set', true):t('get', true).table
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>'
setandget.doc = [[```
/set <name> <value>
Stores a value with the given name. Use "/set <name> --" to delete the stored value.
/get [name]
Returns the stored value or a list of stored values.
```]]
function setandget:action(msg)
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('^/set') then
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)
@ -41,7 +40,7 @@ function setandget:action(msg)
utilities.send_message(self, msg.chat.id, '"' .. name .. '" has been set to "' .. value .. '".', true)
end
elseif msg.text_lower:match('^/get') then
elseif msg.text_lower:match('^'..config.cmd_pat..'get') then
if not input then
local output

View File

@ -2,13 +2,13 @@ local shell = {}
local utilities = require('utilities')
function shell:init()
shell.triggers = utilities.triggers(self.info.username):t('run', true).table
function shell:init(config)
shell.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('run', true).table
end
function shell:action(msg)
function shell:action(msg, config)
if msg.from.id ~= self.config.admin then
if msg.from.id ~= config.admin then
return
end

View File

@ -3,13 +3,13 @@ local shout = {}
local utilities = require('utilities')
shout.command = 'shout <text>'
shout.doc = [[```
/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.
```]]
function shout:init()
shout.triggers = utilities.triggers(self.info.username):t('shout', true).table
end
function shout:action(msg)

View File

@ -3,13 +3,13 @@ local slap = {}
local utilities = require('utilities')
slap.command = 'slap [target]'
slap.doc = [[```
/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.
```]]
function slap:init()
slap.triggers = utilities.triggers(self.info.username):t('slap', true).table
end
local slaps = {

View File

@ -5,16 +5,16 @@ local JSON = require('dkjson')
local utilities = require('utilities')
time.command = 'time <location>'
time.doc = [[```
/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.
```]]
function time:init()
time.triggers = utilities.triggers(self.info.username):t('time', true).table
end
function time:action(msg)
function time:action(msg, config)
local input = utilities.input(msg.text)
if not input then
@ -26,7 +26,7 @@ function time:action(msg)
end
end
local coords = utilities.get_coords(self, input)
local coords = utilities.get_coords(input, config)
if type(coords) == 'string' then
utilities.send_reply(self, msg, coords)
return
@ -39,7 +39,7 @@ function time:action(msg)
local jstr, res = HTTPS.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end

View File

@ -6,16 +6,16 @@ local JSON = require('dkjson')
local utilities = require('utilities')
translate.command = 'translate [text]'
translate.doc = [[```
/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.
```]]
function translate:init()
translate.triggers = utilities.triggers(self.info.username):t('translate', true):t('tl', true).table
end
function translate:action(msg)
function translate:action(msg, config)
local input = utilities.input(msg.text)
if not input then
@ -27,17 +27,17 @@ function translate:action(msg)
end
end
local url = 'https://translate.yandex.net/api/v1.5/tr.json/translate?key=' .. self.config.yandex_key .. '&lang=' .. self.config.lang .. '&text=' .. URL.escape(input)
local 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, self.config.errors.connection)
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, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end

View File

@ -6,17 +6,18 @@ local JSON = require('dkjson')
local utilities = require('utilities')
urbandictionary.command = 'urbandictionary <query>'
urbandictionary.doc = [[```
/urbandictionary <query>
Returns a definition from Urban Dictionary.
Aliases: /ud, /urban
```]]
function urbandictionary:init()
urbandictionary.triggers = utilities.triggers(self.info.username):t('urbandictionary', true):t('ud', true):t('urban', true).table
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)
function urbandictionary:action(msg, config)
local input = utilities.input(msg.text)
if not input then
@ -32,13 +33,13 @@ function urbandictionary:action(msg)
local jstr, res = HTTP.request(url)
if res ~= 200 then
utilities.send_reply(self, msg, self.config.errors.connection)
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, self.config.errors.results)
utilities.send_reply(self, msg, config.errors.results)
return
end

View File

@ -4,23 +4,23 @@ local HTTP = require('socket.http')
local JSON = require('dkjson')
local utilities = require('utilities')
function weather:init()
if not self.config.owm_api_key then
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):t('weather', true).table
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>'
weather.doc = [[```
/weather <location>
Returns the current weather conditions for a given location.
```]]
function weather:action(msg)
function weather:action(msg, config)
local input = utilities.input(msg.text)
if not input then
@ -32,17 +32,17 @@ function weather:action(msg)
end
end
local coords = utilities.get_coords(self, input)
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=' .. self.config.owm_api_key .. '&lat=' .. coords.lat .. '&lon=' .. coords.lon
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, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end

View File

@ -3,13 +3,13 @@ local whoami = {}
local utilities = require('utilities')
whoami.command = 'whoami'
whoami.doc = [[```
Returns user and chat info for you or the replied-to message.
Alias: /who
```]]
function whoami:init()
whoami.triggers = utilities.triggers(self.info.username):t('who', true):t('whoami').table
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)

View File

@ -6,14 +6,14 @@ local JSON = require('dkjson')
local utilities = require('utilities')
wikipedia.command = 'wikipedia <query>'
wikipedia.doc = [[```
/wikipedia <query>
Returns an article from Wikipedia.
Aliases: /w, /wiki
```]]
function wikipedia:init()
wikipedia.triggers = utilities.triggers(self.info.username):t('wikipedia', true):t('wiki', true):t('w', true).table
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)
@ -25,7 +25,7 @@ local get_title = function(search)
return false
end
function wikipedia:action(msg)
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.
@ -50,19 +50,19 @@ function wikipedia:action(msg)
jstr, res = HTTPS.request(search_url .. URL.escape(input))
if res ~= 200 then
utilities.send_reply(self, msg, self.config.errors.connection)
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, self.config.errors.results)
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, self.config.errors.results)
utilities.send_reply(self, msg, config.errors.results)
return
end
@ -70,7 +70,7 @@ function wikipedia:action(msg)
jstr, res = HTTPS.request(res_url .. URL.escape(title))
if res ~= 200 then
utilities.send_reply(self, msg, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end
@ -78,7 +78,7 @@ function wikipedia:action(msg)
local text = JSON.decode(jstr).query.pages
_, text = next(text)
if not text then
utilities.send_reply(self, msg, self.config.errors.results)
utilities.send_reply(self, msg, config.errors.results)
return
else
text = text.extract

View File

@ -5,20 +5,20 @@ local JSON = require('dkjson')
local utilities = require('utilities')
xkcd.command = 'xkcd [i]'
xkcd.doc = [[```
/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.
```]]
function xkcd:init()
xkcd.triggers = utilities.triggers(self.info.username):t('xkcd', true).table
end
function xkcd:action(msg)
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, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end
local latest = JSON.decode(jstr).num
@ -44,7 +44,7 @@ function xkcd:action(msg)
jstr, res = HTTP.request(res_url)
if res ~= 200 then
utilities.send_reply(self, msg, self.config.errors.connection)
utilities.send_reply(self, msg, config.errors.connection)
return
end
local jdat = JSON.decode(jstr)

View File

@ -7,24 +7,24 @@ local URL = require('socket.url')
local JSON = require('dkjson')
local utilities = require('utilities')
function youtube:init()
if not self.config.google_api_key then
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):t('youtube', true):t('yt', true).table
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>'
youtube.doc = [[```
/youtube <query>
Returns the top result from YouTube.
Alias: /yt
```]]
function youtube:action(msg)
function youtube:action(msg, config)
local input = utilities.input(msg.text)
if not input then
@ -36,17 +36,17 @@ function youtube:action(msg)
end
end
local url = 'https://www.googleapis.com/youtube/v3/search?key=' .. self.config.google_api_key .. '&type=video&part=snippet&maxResults=4&q=' .. URL.escape(input)
local 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, self.config.errors.connection)
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, self.config.errors.results)
utilities.send_reply(self, msg, config.errors.results)
return
end

View File

@ -137,18 +137,18 @@ function utilities.save_data(filename, data)
end
-- Gets coordinates for a location. Used by gMaps.lua, time.lua, weather.lua.
function utilities:get_coords(input)
function utilities.get_coords(input, config)
local url = 'http://maps.googleapis.com/maps/api/geocode/json?address=' .. URL.escape(input)
local jstr, res = HTTP.request(url)
if res ~= 200 then
return self.config.errors.connection
return config.errors.connection
end
local jdat = JSON.decode(jstr)
if jdat.status == 'ZERO_RESULTS' then
return self.config.errors.results
return config.errors.results
end
return {
@ -231,15 +231,15 @@ function utilities:user_from_message(msg, no_extra)
end
function utilities:handle_exception(err, message)
function utilities:handle_exception(err, message, config)
if not err then err = '' end
local output = '\n[' .. os.date('%F %T', os.time()) .. ']\n' .. self.info.username .. ': ' .. err .. '\n' .. message .. '\n'
if self.config.log_chat then
if config.log_chat then
output = '```' .. output .. '```'
utilities.send_message(self, self.config.log_chat, output, true, nil, true)
utilities.send_message(self, config.log_chat, output, true, nil, true)
else
print(output)
end
@ -281,24 +281,23 @@ end
utilities.md_escape = utilities.markdown_escape
utilities.INVOCATION_PATTERN = '/'
utilities.triggers_meta = {}
utilities.triggers_meta.__index = utilities.triggers_meta
function utilities.triggers_meta:t(pattern, has_args)
local username = self.username:lower()
table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'$')
table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'@'..username..'$')
table.insert(self.table, '^'..self.cmd_pat..pattern..'$')
table.insert(self.table, '^'..self.cmd_pat..pattern..'@'..username..'$')
if has_args then
table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'%s+[^%s]*')
table.insert(self.table, '^'..utilities.INVOCATION_PATTERN..pattern..'@'..username..'%s+[^%s]*')
table.insert(self.table, '^'..self.cmd_pat..pattern..'%s+[^%s]*')
table.insert(self.table, '^'..self.cmd_pat..pattern..'@'..username..'%s+[^%s]*')
end
return self
end
function utilities.triggers(username, trigger_table)
function utilities.triggers(username, cmd_pat, trigger_table)
local self = setmetatable({}, utilities.triggers_meta)
self.username = username
self.cmd_pat = cmd_pat
self.table = trigger_table or {}
return self
end