administration.lua: 1.10: Added /ahelp $command support. No

migration required. All actions have been reworked to be more
 elegant. Style has been slightly changed (no more weak-looking,
 italic group names). Added some (but not many) comments.

drua-tg.lua: Slightly changed send function with error catching
 for failed TCP connections.

reddit.lua: Rewritten, no more brokenness. Yay.
This commit is contained in:
topkecleon 2016-05-25 09:01:54 -04:00
parent 85c9785099
commit 684cca287f
7 changed files with 453 additions and 319 deletions

View File

@ -89,6 +89,8 @@ Some plugins are designed to be used by the bot's owner. Here are some examples,
## administration.lua ## administration.lua
The administration plugin enables self-hosted, single-realm group administration, supporting both normal groups and supergroups. This works by sending TCP commands to an instance of tg running on the owner's account. The administration plugin enables self-hosted, single-realm group administration, supporting both normal groups and supergroups. This works by sending TCP commands to an instance of tg running on the owner's account.
**For best results, make your bot an administrator of any group it administrates.**
To get started, run `./tg-install.sh`. Note that this script is written for Ubuntu/Debian. If you're running Arch (the only acceptable alternative), you'll have to do it yourself. If that is the case, note that otouto uses the "test" branch of tg, and the AUR package `telegram-cli-git` will not be sufficient, as it does not have support for supergroups yet. To get started, run `./tg-install.sh`. Note that this script is written for Ubuntu/Debian. If you're running Arch (the only acceptable alternative), you'll have to do it yourself. If that is the case, note that otouto uses the "test" branch of tg, and the AUR package `telegram-cli-git` will not be sufficient, as it does not have support for supergroups yet.
Once the installation is finished, enable `administration.lua` in your config file. **The administration plugin must be loaded before about.lua and blacklist.lua.** 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. Once the installation is finished, enable `administration.lua` in your config file. **The administration plugin must be loaded before about.lua and blacklist.lua.** 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.
@ -223,6 +225,7 @@ The bot will accept these commands from both Liberbot and the configured adminis
## Style ## Style
Bot output from every plugin should follow a consistent style. This style is easily observed interacting with the bot. Bot output from every plugin should follow a consistent style. This style is easily observed interacting with the bot.
Titles should be either **bold** (along with their colons) or a [link](http://otou.to) (with plaintext colons) to the content's source. Names should be _italic_. Numbered lists should use bold numbers followed by a bold period followed by a space. Unnumbered lists should use the • bullet point followed by a space. Descriptions and information should be in plaintext, although "flavor" text should be italic. Technical information should be `monospace`. Links should be named. Titles should be either **bold** (along with their colons) or a [link](http://otou.to) (with plaintext colons) to the content's source. Names should be _italic_. Numbered lists should use bold numbers followed by a bold period followed by a space. Unnumbered lists should use the • bullet point followed by a space. Descriptions and information should be in plaintext, although "flavor" text should be italic. Technical information should be `monospace`. Links should be named.
The standard count for plugins which return multiple results is eight results in a private message, and four results elsewhere. This is a trivial number, but consistency is noticeable and desirable.
## Contributors ## Contributors
Everybody is free to contribute to otouto. If you are interested, you are invited to fork the [repo](http://github.com/topkecleon/otouto) and start making pull requests. If you have an idea and you are not sure how to implement it, open an issue or bring it up in the Bot Development group. Everybody is free to contribute to otouto. If you are interested, you are invited to fork the [repo](http://github.com/topkecleon/otouto) and start making pull requests. If you have an idea and you are not sure how to implement it, open an issue or bring it up in the Bot Development group.

View File

@ -50,17 +50,16 @@ local drua = {
} }
drua.send = function(command, do_receive) drua.send = function(command, do_receive)
command = command .. '\n' local s = SOCKET.connect(drua.IP, drua.PORT)
local s = SOCKET.connect('localhost', 4567) assert(s, '\nUnable to connect to tg session.')
s:send(command) s:send(command..'\n')
local output
if do_receive then if do_receive then
-- Get the size of the output, and get the output. output = string.match(s:receive('*l'), 'ANSWER (%d+)')
-- Thanks Juan for making this so easy to read. :^) output = s:receive(tonumber(n)):gsub('\n$', '')
local output = s:receive(tonumber(string.match(s:receive("*l"), "ANSWER (%d+)")))
s:close()
return output:gsub('\n$', '')
end end
s:close() s:close()
return output
end end
drua.message = function(target, text) drua.message = function(target, text)

View File

@ -1,13 +1,13 @@
--[[ --[[
administration.lua administration.lua
Version 1.9 Version 1.10
Part of the otouto project. Part of the otouto project.
© 2016 topkecleon <drew@otou.to> © 2016 topkecleon <drew@otou.to>
GNU General Public License, version 2 GNU General Public License, version 2
This plugin provides self-hosted, single-realm group administration. This plugin provides self-hosted, single-realm group administration.
It requires tg (http://github.com/vysheng/tg) with supergroup support. It requires tg (http://github.com/vysheng/tg) with supergroup support.
For more documentation, view the readme or the manual (otou.to/rtfm). For more documentation, read the the manual (otou.to/rtfm).
Remember to load this before blacklist.lua. Remember to load this before blacklist.lua.
@ -24,6 +24,11 @@
groups[*].autoban = 3 groups[*].autoban = 3
groups[*].autokicks = {} groups[*].autokicks = {}
1.9.1 - Returned to non-toggled promotions/bans (too many complaints!).
1.10 - Added /ahelp $command support. No migration required. All actions
have been reworked to be more elegant. Style has been slightly changed (no
more weak-looking, italic group names). Added some (but not many) comments.
]]-- ]]--
@ -130,47 +135,48 @@ function administration:get_rank(target, chat)
target = tostring(target) target = tostring(target)
chat = tostring(chat) 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) == self.config.admin or tonumber(target) == self.info.id then
return 5 return 5
end end
-- Return 4 if the target is an administrator.
if self.database.administration.admins[target] then if self.database.administration.admins[target] then
return 4 return 4
end end
if chat and self.database.administration.groups[chat] then if chat and self.database.administration.groups[chat] then
-- Return 3 if the target is the governor of the chat.
if self.database.administration.groups[chat].governor == tonumber(target) then if self.database.administration.groups[chat].governor == tonumber(target) then
return 3 return 3
-- Return 2 if the target is a moderator of the chat.
elseif self.database.administration.groups[chat].mods[target] then elseif self.database.administration.groups[chat].mods[target] then
return 2 return 2
-- Return 0 if the target is banned from the chat.
elseif self.database.administration.groups[chat].bans[target] then elseif self.database.administration.groups[chat].bans[target] then
return 0 return 0
-- Return 1 if antihammer is enabled.
elseif self.database.administration.groups[chat].flags[6] then
return 1
end end
end end
-- I wrote a more succint statement, but I want to be able to make sense of -- Return 0 if the target is blacklisted (and antihammer is not enabled).
-- it. Basically, blacklisted users get 0, except when the group has flag 6
-- enabled.
if self.database.blacklist[target] then if self.database.blacklist[target] then
if chat and self.database.administration.groups[chat] and self.database.administration.groups[chat].flags[6] then
return 1
else
return 0 return 0
end end
end
-- Return 1 if the target is a regular user.
return 1 return 1
end end
function administration:get_target(msg) function administration:get_target(msg)
local target = utilities.user_from_message(self, msg) local target = utilities.user_from_message(self, msg)
if target.id then if target.id then
target.rank = administration.get_rank(self, target.id, msg.chat.id) target.rank = administration.get_rank(self, target.id_str, msg.chat.id)
end end
return target return target
end end
function administration:mod_format(id) function administration:mod_format(id)
@ -189,15 +195,15 @@ function administration:get_desc(chat_id)
if group.link then if group.link then
table.insert(t, '*Welcome to* [' .. group.name .. '](' .. group.link .. ')*!*') table.insert(t, '*Welcome to* [' .. group.name .. '](' .. group.link .. ')*!*')
else else
table.insert(t, '*Welcome to* _' .. group.name .. '_*!*') table.insert(t, '*Welcome to ' .. group.name .. '!*')
end end
if group.motd then if group.motd then
table.insert(t, '*Message of the Day:*\n' .. group.motd) table.insert(t, '*Message of the Day:*\n' .. group.motd)
end end
if #group.rules > 0 then if #group.rules > 0 then
local rulelist = '*Rules:*\n' local rulelist = '*Rules:*\n'
for i,v in ipairs(group.rules) do for i = 1, #group.rules do
rulelist = rulelist .. '*' .. i .. '.* ' .. v .. '\n' rulelist = rulelist .. '*' .. i .. '.* ' .. group.rules[i] .. '\n'
end end
table.insert(t, utilities.trim(rulelist)) table.insert(t, utilities.trim(rulelist))
end end
@ -462,6 +468,7 @@ function administration.init_command(self_)
command = 'groups', command = 'groups',
privilege = 1, privilege = 1,
interior = false, interior = false,
doc = 'Returns a list of administrated groups.',
action = function(self, msg) action = function(self, msg)
local output = '' local output = ''
@ -485,20 +492,40 @@ function administration.init_command(self_)
}, },
{ -- /ahelp { -- /ahelp
triggers = utilities.triggers(self_.info.username):t('ahelp').table, triggers = utilities.triggers(self_.info.username):t('ahelp', true).table,
command = 'ahelp', command = 'ahelp \\[command]',
privilege = 1, privilege = 1,
interior = false, 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) action = function(self, msg)
local rank = administration.get_rank(self, msg.from.id, msg.chat.id) local rank = administration.get_rank(self, msg.from.id, msg.chat.id)
local input = utilities.get_word(msg.text_lower, 2)
if input then
input = input:gsub('^/', '')
local doc
for _,action in ipairs(administration.commands) do
if action.keyword == input then
doc = '/' .. action.command:gsub('\\','') .. '\n' .. action.doc
break
end
end
if doc then
local output = '*Help for* _' .. input .. '_ :\n```\n' .. doc .. '\n```'
bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
else
local output = 'Sorry, there is no help for that command.\n/ahelp@'..self.info.username
bindings.sendReply(self, msg, output)
end
else
local output = '*Commands for ' .. administration.ranks[rank] .. ':*\n' local output = '*Commands for ' .. administration.ranks[rank] .. ':*\n'
for i = 1, rank do for i = 1, rank do
for _, val in ipairs(self.admin_temp.help[i]) do for _, val in ipairs(self.admin_temp.help[i]) do
output = output .. '• /' .. val .. '\n' output = output .. '• /' .. val .. '\n'
end end
end end
output = output .. 'Arguments: <required> \\[optional]'
if bindings.sendMessage(self, msg.from.id, output, true, nil, true) then if bindings.sendMessage(self, msg.from.id, output, true, nil, true) then
if msg.from.id ~= msg.chat.id then if msg.from.id ~= msg.chat.id then
bindings.sendReply(self, msg, 'I have sent you the requested information in a private message.') bindings.sendReply(self, msg, 'I have sent you the requested information in a private message.')
@ -507,14 +534,16 @@ function administration.init_command(self_)
bindings.sendMessage(self, msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end end
end end
end
}, },
{ -- /alist { -- /ops
triggers = utilities.triggers(self_.info.username):t('ops'):t('oplist').table, triggers = utilities.triggers(self_.info.username):t('ops'):t('oplist').table,
command = 'ops', command = 'ops',
privilege = 1, privilege = 1,
interior = true, interior = true,
doc = 'Returns a list of moderators and the governor for the group.',
action = function(self, msg, group) action = function(self, msg, group)
local modstring = '' local modstring = ''
@ -522,7 +551,7 @@ function administration.init_command(self_)
modstring = modstring .. administration.mod_format(self, k) modstring = modstring .. administration.mod_format(self, k)
end end
if modstring ~= '' then if modstring ~= '' then
modstring = '*Moderators for* _' .. msg.chat.title .. '_ *:*\n' .. modstring modstring = '*Moderators for ' .. msg.chat.title .. ':*\n' .. modstring
end end
local govstring = '' local govstring = ''
if group.governor then if group.governor then
@ -544,6 +573,7 @@ function administration.init_command(self_)
command = 'description', command = 'description',
privilege = 1, privilege = 1,
interior = true, 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) action = function(self, msg)
local output = administration.get_desc(self, msg.chat.id) local output = administration.get_desc(self, msg.chat.id)
@ -560,9 +590,10 @@ function administration.init_command(self_)
{ -- /rules { -- /rules
triggers = utilities.triggers(self_.info.username):t('rules?', true).table, triggers = utilities.triggers(self_.info.username):t('rules?', true).table,
command = 'rules', command = 'rules \\[i]',
privilege = 1, privilege = 1,
interior = true, interior = true,
doc = 'Returns the group\'s list of rules, or a specific rule.',
action = function(self, msg, group) action = function(self, msg, group)
local output local output
@ -572,7 +603,7 @@ function administration.init_command(self_)
if input and group.rules[input] then if input and group.rules[input] then
output = '*' .. input .. '.* ' .. group.rules[input] output = '*' .. input .. '.* ' .. group.rules[input]
else else
output = '*Rules for* _' .. msg.chat.title .. '_ *:*\n' output = '*Rules for ' .. msg.chat.title .. ':*\n'
for i,v in ipairs(group.rules) do for i,v in ipairs(group.rules) do
output = output .. '*' .. i .. '.* ' .. v .. '\n' output = output .. '*' .. i .. '.* ' .. v .. '\n'
end end
@ -590,11 +621,12 @@ function administration.init_command(self_)
command = 'motd', command = 'motd',
privilege = 1, privilege = 1,
interior = true, interior = true,
doc = 'Returns the group\'s message of the day.',
action = function(self, msg, group) action = function(self, msg, group)
local output = 'No MOTD has been set for ' .. msg.chat.title .. '.' local output = 'No MOTD has been set for ' .. msg.chat.title .. '.'
if group.motd then if group.motd then
output = '*MOTD for* _' .. msg.chat.title .. '_ *:*\n' .. group.motd output = '*MOTD for ' .. msg.chat.title .. ':*\n' .. group.motd
end end
bindings.sendMessage(self, msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end end
@ -606,6 +638,7 @@ function administration.init_command(self_)
command = 'link', command = 'link',
privilege = 1, privilege = 1,
interior = true, interior = true,
doc = 'Returns the group\'s link.',
action = function(self, msg, group) action = function(self, msg, group)
local output = 'No link has been set for ' .. msg.chat.title .. '.' local output = 'No link has been set for ' .. msg.chat.title .. '.'
@ -622,17 +655,18 @@ function administration.init_command(self_)
command = 'kickme', command = 'kickme',
privilege = 1, privilege = 1,
interior = true, interior = true,
doc = 'Removes the user from the group.',
action = function(self, msg) action = function(self, msg)
if administration.get_rank(self, msg.from.id) == 5 then if administration.get_rank(self, msg.from.id) == 5 then
bindings.sendReply(self, msg, 'I can\'t let you do that, '..msg.from.name..'.') bindings.sendReply(self, msg, 'I can\'t let you do that, '..msg.from.name..'.')
return else
end
administration.kick_user(self, msg.chat.id, msg.from.id, 'kickme') administration.kick_user(self, msg.chat.id, msg.from.id, 'kickme')
if msg.chat.type == 'supergroup' then if msg.chat.type == 'supergroup' then
bindings.unbanChatMember(self, msg.chat.id, msg.from.id) bindings.unbanChatMember(self, msg.chat.id, msg.from.id)
end end
end end
end
}, },
{ -- /kick { -- /kick
@ -641,51 +675,100 @@ function administration.init_command(self_)
command = 'kick <user>', command = 'kick <user>',
privilege = 2, privilege = 2,
interior = true, interior = true,
doc = 'Removes a user from the group. The target may be specified via reply, username, or ID.',
action = function(self, msg) action = function(self, msg)
local target = administration.get_target(self, msg) local target = administration.get_target(self, msg)
if target.err then if target.err then
bindings.sendReply(self, msg, target.err) bindings.sendReply(self, msg, target.err)
return
elseif target.rank > 1 then elseif target.rank > 1 then
bindings.sendReply(self, msg, target.name .. ' is too privileged to be kicked.') bindings.sendReply(self, msg, target.name .. ' is too privileged to be kicked.')
return else
end
administration.kick_user(self, msg.chat.id, target.id, 'kicked by ' .. msg.from.id) administration.kick_user(self, msg.chat.id, target.id, 'kicked by ' .. msg.from.id)
bindings.sendMessage(self, msg.chat.id, target.name .. ' has been kicked.')
if msg.chat.type == 'supergroup' then if msg.chat.type == 'supergroup' then
bindings.unbanChatMember(self, msg.chat.id, target.id) bindings.unbanChatMember(self, msg.chat.id, target.id)
end end
bindings.sendMessage(self, msg.chat.id, target.name .. ' has been kicked.') end
end end
}, },
{ -- /ban { -- /ban
triggers = utilities.triggers(self_.info.username):t('ban', true):t('unban', true).table, triggers = utilities.triggers(self_.info.username):t('ban', true).table,
command = 'ban <user>', command = 'ban <user>',
privilege = 2, privilege = 2,
interior = true, interior = true,
doc = 'Bans a user from the group. The target may be specified via reply, username, or ID.',
action = function(self, msg, group) action = function(self, msg, group)
local target = administration.get_target(self, msg) local target = administration.get_target(self, msg)
if target.err then if target.err then
bindings.sendReply(self, msg, target.err) bindings.sendReply(self, msg, target.err)
return elseif target.rank > 1 then
end
if target.rank > 1 then
bindings.sendReply(self, msg, target.name .. ' is too privileged to be banned.') bindings.sendReply(self, msg, target.name .. ' is too privileged to be banned.')
return elseif group.bans[target.id_str] then
bindings.sendReply(self, msg, target.name .. ' is already banned.')
else
administration.kick_user(self, msg.chat.id, target.id, ' banned by '..msg.from.id)
bindings.sendReply(self, msg, target.name .. ' has been banned.')
group.bans[target.id_str] = true
end end
if group.bans[target.id_str] then end
},
{ -- /unban
triggers = utilities.triggers(self_.info.username):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)
if target.err then
bindings.sendReply(self, msg, target.err)
else
if not group.bans[target.id_str] then
bindings.sendReply(self, msg, target.name .. ' is not banned.')
else
group.bans[target.id_str] = nil group.bans[target.id_str] = nil
bindings.sendReply(self, msg, target.name .. ' has been unbanned.')
end
if msg.chat.type == 'supergroup' then if msg.chat.type == 'supergroup' then
bindings.unbanChatMember(self, msg.chat.id, target.id) bindings.unbanChatMember(self, msg.chat.id, target.id)
end end
bindings.sendReply(self, msg, target.name .. ' has been unbanned.') end
end
},
{ -- /setrules
triggers = utilities.triggers(self_.info.username):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..']*(.+)')
if input == ' --' or input == ' ' .. utilities.char.em_dash then
group.rules = {}
bindings.sendReply(self, msg, 'The rules have been cleared.')
elseif input then
group.rules = {}
input = utilities.trim(input) .. '\n'
local output = '*Rules for ' .. msg.chat.title .. ':*\n'
local i = 1
for l in input:gmatch('(.-)\n') do
output = output .. '*' .. i .. '.* ' .. l .. '\n'
i = i + 1
table.insert(group.rules, utilities.trim(l))
end
bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
else else
group.bans[target.id_str] = true bindings.sendReply(self, msg, 'Please specify the new rules.')
administration.kick_user(self, msg.chat.id, target.id, ' banned by '..msg.from.id)
bindings.sendReply(self, msg, target.name .. ' has been banned.')
end end
end end
}, },
@ -696,77 +779,34 @@ function administration.init_command(self_)
command = 'changerule <i> <rule>', command = 'changerule <i> <rule>',
privilege = 3, privilege = 3,
interior = true, interior = true,
doc = 'Changes a single rule. Pass "--" to delete the rule.',
action = function(self, msg, group) action = function(self, msg, group)
local usage = 'usage: `/changerule <i> <newrule>`\n`/changerule <i> -- `deletes.'
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then local output = 'usage: `/changerule <i> <newrule>`'
bindings.sendMessage(self, msg.chat.id, usage, true, msg.message_id, true) if input then
return local rule_num = tonumber(input:match('^%d+'))
end local new_rule = utilities.input(input)
local rule_num = input:match('^%d+')
if not rule_num then if not rule_num then
local output = 'Please specify which rule you want to change.\n' .. usage output = 'Please specify which rule you want to change.'
bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true) elseif not new_rule then
return output = 'Please specify the new rule.'
end elseif new_rule == '--' or new_rule == utilities.char.em_dash then
rule_num = tonumber(rule_num) if group.rules[rule_num] then
local rule_new = utilities.input(input) table.remove(group.rules, rule_num)
if not rule_new then output = 'That rule has been deleted.'
local output = 'Please specify the new rule.\n' .. usage else
bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true) output = 'There is no rule with that number.'
return
end
if not group.rules then
local output = 'Sorry, there are no rules to change. Please use /setrules.\n' .. usage
bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true)
return
end end
else
if not group.rules[rule_num] then if not group.rules[rule_num] then
rule_num = #group.rules + 1 rule_num = #group.rules + 1
end end
if rule_new == '--' or rule_new == '' then group.rules[rule_num] = new_rule
if group.rules[rule_num] then output = '*' .. rule_num .. '*. ' .. new_rule
table.remove(group.rules, rule_num)
bindings.sendReply(self, msg, 'That rule has been deleted.')
else
bindings.sendReply(self, msg, 'There is no rule with that number.')
end end
return
end end
group.rules[rule_num] = rule_new bindings.sendReply(self, msg, output, true)
local output = '*' .. rule_num .. '*. ' .. rule_new
bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end
},
{ -- /setrules
triggers = utilities.triggers(self_.info.username):t('setrules', true).table,
command = 'setrules <rules>',
privilege = 3,
interior = true,
action = function(self, msg, group)
local input = msg.text:match('^/setrules[@'..self.info.username..']*(.+)')
if not input then
bindings.sendMessage(self, msg.chat.id, '```\n/setrules [rule]\n<rule>\n[rule]\n...\n```', true, msg.message_id, true)
return
elseif input == ' --' or input == '' then
group.rules = {}
bindings.sendReply(self, msg, 'The rules have been cleared.')
return
end
group.rules = {}
input = utilities.trim(input) .. '\n'
local output = '*Rules for* _' .. msg.chat.title .. '_ *:*\n'
local i = 1
for l in input:gmatch('(.-)\n') do
output = output .. '*' .. i .. '.* ' .. l .. '\n'
i = i + 1
table.insert(group.rules, utilities.trim(l))
end
bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end end
}, },
@ -776,29 +816,29 @@ function administration.init_command(self_)
command = 'setmotd <motd>', command = 'setmotd <motd>',
privilege = 3, privilege = 3,
interior = true, 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)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if not input and msg.reply_to_message and msg.reply_to_message.text:len() > 0 then
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text input = msg.reply_to_message.text
else
bindings.sendReply(self, msg, 'Please specify the new message of the day.')
return
end end
end if input then
if input == '--' or input == '' then if input == '--' or input == utilities.char.em_dash then
group.motd = nil group.motd = nil
bindings.sendReply(self, msg, 'The MOTD has been cleared.') bindings.sendReply(self, msg, 'The MOTD has been cleared.')
else else
input = utilities.trim(input) input = utilities.trim(input)
group.motd = input group.motd = input
local output = '*MOTD for* _' .. msg.chat.title .. '_ *:*\n' .. input local output = '*MOTD for ' .. msg.chat.title .. ':*\n' .. input
bindings.sendMessage(self, msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
end end
if group.grouptype == 'supergroup' then if group.grouptype == 'supergroup' then
administration.update_desc(self, msg.chat.id) administration.update_desc(self, msg.chat.id)
end end
else
bindings.sendReply(self, msg, 'Please specify the new message of the day.')
end
end end
}, },
@ -808,20 +848,20 @@ function administration.init_command(self_)
command = 'setlink <link>', command = 'setlink <link>',
privilege = 3, privilege = 3,
interior = true, interior = true,
doc = 'Sets the group\'s join link. Pass "--" to regenerate the link.',
action = function(self, msg, group) action = function(self, msg, group)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if input == '--' or input == utilities.chat.em_dash then
bindings.sendReply(self, msg, 'Please specify the new link.')
return
elseif input == '--' or input == '' then
group.link = drua.export_link(msg.chat.id) group.link = drua.export_link(msg.chat.id)
bindings.sendReply(self, msg, 'The link has been regenerated.') bindings.sendReply(self, msg, 'The link has been regenerated.')
return elseif input then
end
group.link = input group.link = input
local output = '[' .. msg.chat.title .. '](' .. input .. ')' local output = '[' .. msg.chat.title .. '](' .. input .. ')'
bindings.sendMessage(self, msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
else
bindings.sendReply(self, msg, 'Please specify the new link.')
end
end end
}, },
@ -831,6 +871,7 @@ function administration.init_command(self_)
command = 'alist', command = 'alist',
privilege = 3, privilege = 3,
interior = true, interior = true,
doc = 'Returns a list of administrators. Owner is denoted with a star character.',
action = function(self, msg) action = function(self, msg)
local output = '*Administrators:*\n' local output = '*Administrators:*\n'
@ -845,9 +886,10 @@ function administration.init_command(self_)
{ -- /flags { -- /flags
triggers = utilities.triggers(self_.info.username):t('flags?', true).table, triggers = utilities.triggers(self_.info.username):t('flags?', true).table,
command = 'flag <i>', command = 'flag \\[i]',
privilege = 3, privilege = 3,
interior = true, interior = true,
doc = 'Returns a list of flags or toggles the specified flag.',
action = function(self, msg, group) action = function(self, msg, group)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
@ -857,15 +899,13 @@ function administration.init_command(self_)
if not input or not administration.flags[input] then input = false end if not input or not administration.flags[input] then input = false end
end end
if not input then if not input then
local output = '*Flags for* _' .. msg.chat.title .. '_ *:*\n' local output = '*Flags for ' .. msg.chat.title .. ':*\n'
for i,v in ipairs(administration.flags) do for i,v in ipairs(administration.flags) do
local status = group.flags[i] or false local status = group.flags[i] or false
output = output .. '`[' .. i .. ']` *' .. v.name .. '*` = ' .. tostring(status) .. '`\n' .. v.desc .. '\n' output = output .. '`[' .. i .. ']` *' .. v.name .. '*` = ' .. tostring(status) .. '`\n' .. v.desc .. '\n'
end end
bindings.sendMessage(self, msg.chat.id, output, true, nil, true) bindings.sendMessage(self, msg.chat.id, output, true, nil, true)
return elseif group.flags[input] == true then
end
if group.flags[input] == true then
group.flags[input] = false group.flags[input] = false
bindings.sendReply(self, msg, administration.flags[input].disabled) bindings.sendReply(self, msg, administration.flags[input].disabled)
else else
@ -878,15 +918,15 @@ function administration.init_command(self_)
{ -- /antiflood { -- /antiflood
triggers = utilities.triggers(self_.info.username):t('antiflood', true).table, triggers = utilities.triggers(self_.info.username):t('antiflood', true).table,
command = 'antiflood <type> <i>', command = 'antiflood \\[<type> <i>]',
privilege = 3, privilege = 3,
interior = true, interior = true,
doc = 'Returns a list of antiflood values or sets one.',
action = function(self, msg, group) action = function(self, msg, group)
if not group.flags[5] then if not group.flags[5] then
bindings.sendMessage(self, msg.chat.id, 'antiflood is not enabled. Use `/flag 5` to enable it.', true, nil, true) bindings.sendMessage(self, msg.chat.id, 'antiflood is not enabled. Use `/flag 5` to enable it.', true, nil, true)
return else
end
if not group.antiflood then if not group.antiflood then
group.antiflood = JSON.decode(JSON.encode(administration.antiflood)) group.antiflood = JSON.decode(JSON.encode(administration.antiflood))
end end
@ -912,109 +952,146 @@ function administration.init_command(self_)
end end
bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true) bindings.sendMessage(self, msg.chat.id, output, true, msg.message_id, true)
end end
end
}, },
{ -- /mod { -- /mod
triggers = utilities.triggers(self_.info.username):t('mod', true):t('demod', true).table, triggers = utilities.triggers(self_.info.username):t('mod', true).table,
command = 'mod <user>', command = 'mod <user>',
privilege = 3, privilege = 3,
interior = true, interior = true,
doc = 'Promotes a user to a moderator. The target may be specified via reply, username, or ID.',
action = function(self, msg, group) action = function(self, msg, group)
local target = administration.get_target(self, msg) local target = administration.get_target(self, msg)
if target.err then if target.err then
bindings.sendReply(self, msg, target.err) bindings.sendReply(self, msg, target.err)
return
end
if group.mods[target.id_str] then
if group.grouptype == 'supergroup' then
drua.channel_set_admin(msg.chat.id, target.id, 0)
end
group.mods[target.id_str] = nil
bindings.sendReply(self, msg, target.name .. ' is no longer a moderator.')
else else
if target.rank > 2 then if target.rank > 1 then
bindings.sendReply(self, msg, target.name .. ' is greater than a moderator.') bindings.sendReply(self, msg, target.name .. ' is already a moderator or greater.')
return else
group.bans[target.id_str] = nil
group.mods[target.id_str] = true
bindings.sendReply(self, msg, target.name .. ' is now a moderator.')
end end
if group.grouptype == 'supergroup' then if group.grouptype == 'supergroup' then
drua.channel_set_admin(msg.chat.id, target.id, 2) drua.channel_set_admin(msg.chat.id, target.id, 2)
end end
group.mods[target.id_str] = true end
bindings.sendReply(self, msg, target.name .. ' is now a moderator.') end
},
{ -- /demod
triggers = utilities.triggers(self_.info.username):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)
if target.err then
bindings.sendReply(self, msg, target.err)
else
if not group.mods[target.id_str] then
bindings.sendReply(self, msg, target.name .. ' is not a moderator.')
else
group.mods[target.id_str] = nil
bindings.sendReply(self, msg, target.name .. ' is no longer a moderator.')
end
if group.grouptype == 'supergroup' then
drua.channel_set_admin(msg.chat.id, target.id, 0)
end
end end
end end
}, },
{ -- /gov { -- /gov
triggers = utilities.triggers(self_.info.username):t('gov', true):t('degov', true).table, triggers = utilities.triggers(self_.info.username):t('gov', true).table,
command = 'gov <user>', command = 'gov <user>',
privilege = 4, privilege = 4,
interior = true, 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) action = function(self, msg, group)
local target = administration.get_target(self, msg) local target = administration.get_target(self, msg)
if target.err then if target.err then
bindings.sendReply(self, msg, target.err) bindings.sendReply(self, msg, target.err)
return
end
if group.governor and group.governor == target.id then
if group.grouptype == 'supergroup' then
drua.channel_set_admin(msg.chat.id, target.id, 0)
end
group.governor = self.config.admin
bindings.sendReply(self, msg, target.name .. ' is no longer the governor.')
else else
if group.grouptype == 'supergroup' then if group.governor == target.id then
if group.governor then bindings.sendReply(self, msg, target.name .. ' is already the governor.')
drua.channel_set_admin(msg.chat.id, group.governor, 0) else
end group.bans[target.id_str] = nil
drua.channel_set_admin(msg.chat.id, target.id, 2)
end
if target.rank == 2 then
group.mods[target.id_str] = nil group.mods[target.id_str] = nil
end
group.governor = target.id group.governor = target.id
bindings.sendReply(self, msg, target.name .. ' is the new governor.') bindings.sendReply(self, msg, target.name .. ' is the new governor.')
end end
if group.grouptype == 'supergroup' then 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)
end end
end end
end
},
{ -- /degov
triggers = utilities.triggers(self_.info.username):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)
if target.err then
bindings.sendReply(self, msg, target.err)
else
if group.governor ~= target.id then
bindings.sendReply(self, msg, target.name .. ' is not the governor.')
else
group.governor = msg.from.id
bindings.sendReply(self, msg, target.name .. ' is no longer the governor.')
end
if group.grouptype == 'supergroup' then
drua.channel_set_admin(msg.chat.id, target.id, 0)
administration.update_desc(self, msg.chat.id)
end
end
end
}, },
{ -- /hammer { -- /hammer
triggers = utilities.triggers(self_.info.username):t('hammer', true):t('unhammer', true).table, triggers = utilities.triggers(self_.info.username):t('hammer', true).table,
command = 'hammer <user>', command = 'hammer <user>',
privilege = 4, privilege = 4,
interior = false, interior = false,
doc = 'Bans a user from all groups. The target may be specified via reply, username, or ID.',
action = function(self, msg, group) action = function(self, msg, group)
local target = administration.get_target(self, msg) local target = administration.get_target(self, msg)
if target.err then if target.err then
bindings.sendReply(self, msg, target.err) bindings.sendReply(self, msg, target.err)
return elseif target.rank > 3 then
end
if target.rank > 3 then
bindings.sendReply(self, msg, target.name .. ' is too privileged to be globally banned.') bindings.sendReply(self, msg, target.name .. ' is too privileged to be globally banned.')
return elseif self.database.blacklist[target.id_str] then
end bindings.sendReply(self, msg, target.name .. ' is already globally banned.')
if self.database.blacklist[target.id_str] then
self.database.blacklist[target.id_str] = nil
bindings.sendReply(self, msg, target.name .. ' has been globally unbanned.')
else else
administration.kick_user(self, msg.chat.id, target.id, 'hammered by '..msg.from.id) administration.kick_user(self, msg.chat.id, target.id, 'hammered by '..msg.from.id)
self.database.blacklist[target.id_str] = true self.database.blacklist[target.id_str] = true
for k,v in pairs(self.database.administration.groups) do for k,v in pairs(self.database.administration.groups) do
if not v.flags[6] then if not v.flags[6] then
v.mods[target.id_str] = nil
drua.kick_user(k, target.id) drua.kick_user(k, target.id)
end end
end end
local output = target.name .. ' has been globally banned.' local output = target.name .. ' has been globally banned.'
if group.flags[6] == true then if group.flags[6] == true then
group.mods[target.id_str] = nil
group.bans[target.id_str] = true group.bans[target.id_str] = true
output = target.name .. ' has been globally and locally banned.' output = target.name .. ' has been globally and locally banned.'
end end
@ -1023,33 +1100,72 @@ function administration.init_command(self_)
end end
}, },
{ -- /unhammer
triggers = utilities.triggers(self_.info.username):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, group)
local target = administration.get_target(self, msg)
if target.err then
bindings.sendReply(self, msg, target.err)
elseif not self.database.blacklist[target.id_str] then
bindings.sendReply(self, msg, target.name .. ' is not globally banned.')
else
self.database.blacklist[target.id_str] = nil
bindings.sendReply(self, msg, target.name .. ' has been globally unbanned.')
end
end
},
{ -- /admin { -- /admin
triggers = utilities.triggers(self_.info.username):t('admin', true):t('deadmin', true).table, triggers = utilities.triggers(self_.info.username):t('admin', true).table,
command = 'admin <user>', command = 'admin <user>',
privilege = 5, privilege = 5,
interior = false, interior = false,
doc = 'Promotes a user to an administrator. The target may be specified via reply, username, or ID.',
action = function(self, msg) action = function(self, msg)
local target = administration.get_target(self, msg) local target = administration.get_target(self, msg)
if target.err then if target.err then
bindings.sendReply(self, msg, target.err) bindings.sendReply(self, msg, target.err)
return elseif target.rank >= 4 then
end bindings.sendReply(self, msg, target.name .. ' is already an administrator or greater.')
if self.database.administration.admins[target.id_str] then
self.database.administration.admins[target.id_str] = nil
bindings.sendReply(self, msg, target.name .. ' is no longer an administrator.')
else else
if target.rank == 5 then
bindings.sendReply(self, msg, target.name .. ' is greater than an administrator.')
return
end
for _,group in pairs(self.database.administration.groups) do for _,group in pairs(self.database.administration.groups) do
group.mods[target.id_str] = nil group.mods[target.id_str] = nil
end end
self.database.administration.admins[target.id_str] = true self.database.administration.admins[target.id_str] = true
bindings.sendReply(self, msg, target.name .. ' is now an administrator.') bindings.sendReply(self, msg, target.name .. ' is now an administrator.')
end end
if group.grouptype == 'supergroup' then
drua.channel_set_admin(msg.chat.id, target.id, 2)
end
end
},
{ -- /deadmin
triggers = utilities.triggers(self_.info.username):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)
if target.err then
bindings.sendReply(self, msg, target.err)
elseif target.rank ~= 4 then
bindings.sendReply(self, msg, target.name .. ' is not an administrator.')
else
self.database.administration.admins[target.id_str] = nil
bindings.sendReply(self, msg, target.name .. ' is no longer an administrator.')
end
end end
}, },
@ -1059,12 +1175,12 @@ function administration.init_command(self_)
command = 'gadd', command = 'gadd',
privilege = 5, privilege = 5,
interior = false, interior = false,
doc = 'Adds a group to the administration system.',
action = function(self, msg) action = function(self, msg)
if self.database.administration.groups[msg.chat.id_str] then if self.database.administration.groups[msg.chat.id_str] then
bindings.sendReply(self, msg, 'I am already administrating this group.') bindings.sendReply(self, msg, 'I am already administrating this group.')
return else
end
self.database.administration.groups[msg.chat.id_str] = { self.database.administration.groups[msg.chat.id_str] = {
mods = {}, mods = {},
governor = msg.from.id, governor = msg.from.id,
@ -1087,6 +1203,7 @@ function administration.init_command(self_)
bindings.sendReply(self, msg, 'I am now administrating this group.') bindings.sendReply(self, msg, 'I am now administrating this group.')
drua.channel_set_admin(msg.chat.id, self.info.id, 2) drua.channel_set_admin(msg.chat.id, self.info.id, 2)
end end
end
}, },
{ -- /grem { -- /grem
@ -1095,6 +1212,7 @@ function administration.init_command(self_)
command = 'gremove \\[chat]', command = 'gremove \\[chat]',
privilege = 5, privilege = 5,
interior = false, interior = false,
doc = 'Removes a group from the administration system.',
action = function(self, msg) action = function(self, msg)
local input = utilities.input(msg.text) or msg.chat.id_str local input = utilities.input(msg.text) or msg.chat.id_str
@ -1125,6 +1243,7 @@ function administration.init_command(self_)
command = 'glist', command = 'glist',
privilege = 5, privilege = 5,
interior = false, 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)
local output = '' local output = ''
@ -1153,22 +1272,25 @@ function administration.init_command(self_)
command = 'broadcast <message>', command = 'broadcast <message>',
privilege = 5, privilege = 5,
interior = false, interior = false,
doc = 'Broadcasts a message to all administrated groups.',
action = function(self, msg) action = function(self, msg)
local input = utilities.input(msg.text) local input = utilities.input(msg.text)
if not input then if not input then
bindings.sendReply(self, msg, 'Give me something to broadcast.') bindings.sendReply(self, msg, 'Give me something to broadcast.')
return else
end
input = '*Admin Broadcast:*\n' .. input input = '*Admin Broadcast:*\n' .. input
for id,_ in pairs(self.database.administration.groups) do for id,_ in pairs(self.database.administration.groups) do
bindings.sendMessage(self, id, input, true, nil, true) bindings.sendMessage(self, id, input, true, nil, true)
end end
end end
end
} }
} }
-- These could be merged, but load time doesn't matter.
-- Generate trigger table. -- Generate trigger table.
administration.triggers = {} administration.triggers = {}
for _, command in ipairs(administration.commands) do for _, command in ipairs(administration.commands) do
@ -1177,6 +1299,7 @@ function administration.init_command(self_)
end end
end end
-- Generate help messages.
self_.database.administration.help = {} self_.database.administration.help = {}
for i,_ in ipairs(administration.ranks) do for i,_ in ipairs(administration.ranks) do
self_.admin_temp.help[i] = {} self_.admin_temp.help[i] = {}
@ -1186,6 +1309,13 @@ function administration.init_command(self_)
table.insert(self_.admin_temp.help[v.privilege], v.command) table.insert(self_.admin_temp.help[v.privilege], v.command)
end end
end end
-- Generate ahelp keywords.
for _,v in ipairs(administration.commands) do
if v.command and v.doc then
v.keyword = utilities.get_word(v.command, 1)
end
end
end end
function administration:action(msg) function administration:action(msg)

View File

@ -35,7 +35,7 @@ function lastfm:action(msg)
elseif string.match(msg.text, '^/fmset') then elseif string.match(msg.text, '^/fmset') then
if not input then if not input then
bindings.sendMessage(self, msg.chat.id, lastfm.doc, true, msg.message_id, true) bindings.sendMessage(self, msg.chat.id, lastfm.doc, true, msg.message_id, true)
elseif input == '--' or input == '' then elseif input == '--' or input == utilities.char.em_dash then
self.database.users[msg.from.id_str].lastfm = nil self.database.users[msg.from.id_str].lastfm = nil
bindings.sendReply(self, msg, 'Your last.fm username has been forgotten.') bindings.sendReply(self, msg, 'Your last.fm username has been forgotten.')
else else

View File

@ -36,7 +36,7 @@ function nick:action(msg)
end end
elseif string.len(input) > 32 then elseif string.len(input) > 32 then
output = 'The character limit for nicknames is 32.' output = 'The character limit for nicknames is 32.'
elseif input == '--' or input == '' then elseif input == '--' or input == utilities.char.em_dash then
self.database.users[target.id_str].nickname = nil self.database.users[target.id_str].nickname = nil
output = target.name .. '\'s nickname has been deleted.' output = target.name .. '\'s nickname has been deleted.'
else else

View File

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

View File

@ -336,7 +336,8 @@ utilities.char = {
zwnj = '', zwnj = '',
arabic = '[\216-\219][\128-\191]', arabic = '[\216-\219][\128-\191]',
rtl_override = '', rtl_override = '',
rtl_mark = '' rtl_mark = '',
em_dash = ''
} }
return utilities return utilities