administration.lua: Added antiflood flag.

bible.lua: Some better error handling.
hearthstone.lua: Corrected help message.
utilities.lua: Added string:index() to succeed get_word().
This commit is contained in:
topkecleon 2016-03-31 07:53:12 -04:00
parent 3063df56c9
commit b643154df8
5 changed files with 174 additions and 29 deletions

View File

@ -106,6 +106,7 @@ While tg is running, you may start/reload otouto with administration.lua enabled
| /setmotd | Sets a group's "Message of the Day". | 3 | Y | | /setmotd | Sets a group's "Message of the Day". | 3 | Y |
| /setlink | Sets a group's link. | 3 | Y | | /setlink | Sets a group's link. | 3 | Y |
| /flag | Returns a list of available flags and their settings, or toggles a flag. | 3 | Y | | /flag | Returns a list of available flags and their settings, or toggles a flag. | 3 | Y |
| /antiflood | Configures antiflood (flag 5) settings. | 3 | Y |
| /mod | Promotes a user to a moderator. | 3 | Y | | /mod | Promotes a user to a moderator. | 3 | Y |
| /demod | Demotes a moderator to a user. | 3 | Y | | /demod | Demotes a moderator to a user. | 3 | Y |
| /gov | Promotes a user to a governor. | 4 | Y | | /gov | Promotes a user to a governor. | 4 | Y |
@ -141,6 +142,23 @@ Obviously, each greater rank inherits the privileges of the lower, positive rank
| 2 | antisquig | Automatically removes users for posting Arabic script or RTL characters. | | 2 | antisquig | Automatically removes users for posting Arabic script or RTL characters. |
| 3 | antisquig Strict | Automatically removes users whose names contain Arabic script or RTL characters. | | 3 | antisquig Strict | Automatically removes users whose names contain Arabic script or RTL characters. |
| 4 | antibot | Prevents bots from being added by non-moderators. | | 4 | antibot | Prevents bots from being added by non-moderators. |
| 5 | antiflood | Prevents flooding by rate-limiting messages per user. |
#### antiflood
antiflood (flag 5) provides a system of automatic flood protection by removing users who post too much. It is entirely configurable by a group's governor, an administrator, or the bot owner. For each message to a particular group, a user is awarded a certain number of "points". The number of points is different for each message type. When the user reaches 100 points, he is removed. Points are reset each minute. In this way, if a user posts twenty messages within one minute, he is removed.
**Default antiflood values:**
| Type | Points |
| text | 5 |
| contact | 5 |
| audio | 5 |
| voice | 5 |
| photo | 10 |
| document | 10 |
| location | 10 |
| video | 10 |
| sticker | 20 |
* * * * * *

View File

@ -30,6 +30,11 @@ if not database.administration then
} }
end end
admin_temp = {
help = {},
flood = {}
}
-- Migration code: Remove this in v1.7. -- Migration code: Remove this in v1.7.
-- Group data is now stored in a "groups" array. -- Group data is now stored in a "groups" array.
if not database.administration.groups then if not database.administration.groups then
@ -82,7 +87,7 @@ local flags = {
kicked = 'You were automatically kicked from GROUPNAME for posting Arabic script and/or RTL characters.' kicked = 'You were automatically kicked from GROUPNAME for posting Arabic script and/or RTL characters.'
}, },
[3] = { [3] = {
name = 'antisquig Strict', name = 'antisquig++',
desc = 'Automatically removes users whose names contain Arabic script or RTL characters.', desc = 'Automatically removes users whose names contain Arabic script or RTL characters.',
short = 'This group does not allow users whose names contain Arabic script or RTL characters.', short = 'This group does not allow users whose names contain Arabic script or RTL characters.',
enabled = 'Users whose names contain Arabic script and/or RTL characters will now be removed automatically.', enabled = 'Users whose names contain Arabic script and/or RTL characters will now be removed automatically.',
@ -95,9 +100,29 @@ local flags = {
short = 'This group does not allow users to add bots.', short = 'This group does not allow users to add bots.',
enabled = 'Non-moderators will no longer be able to add bots.', enabled = 'Non-moderators will no longer be able to add bots.',
disabled = 'Non-moderators will now be able to add bots.' disabled = 'Non-moderators will now be able to add bots.'
},
[5] = {
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.',
disabled = 'Users will no longer be removed automatically for excessive messages.',
kicked = 'You were automatically kicked from GROUPNAME for flooding.'
} }
} }
local antiflood = {
text = 5,
voice = 5,
audio = 5,
contact = 5,
photo = 10,
video = 10,
location = 10,
document = 10,
sticker = 20
}
local ranks = { local ranks = {
[0] = 'Banned', [0] = 'Banned',
[1] = 'Users', [1] = 'Users',
@ -182,7 +207,7 @@ local get_desc = function(chat_id)
local flaglist = '' local flaglist = ''
for i = 1, #flags do for i = 1, #flags do
if group.flags[i] then if group.flags[i] then
output = output .. '' .. flags[i].short .. '\n' flaglist = flaglist .. '' .. flags[i].short .. '\n'
end end
end end
if flaglist ~= '' then if flaglist ~= '' then
@ -260,6 +285,45 @@ local commands = {
end end
end end
-- antiflood
if group.flags[5] == true then
if not group.antiflood then
group.antiflood = JSON.decode(JSON.encode(antiflood))
end
if not admin_temp.flood[msg.chat.id_str] then
admin_temp.flood[msg.chat.id_str] = {}
end
if not admin_temp.flood[msg.chat.id_str][msg.from.id_str] then
admin_temp.flood[msg.chat.id_str][msg.from.id_str] = 0
end
if msg.sticker then -- Thanks Brazil for discarding switches.
admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.sticker
elseif msg.photo then
admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.photo
elseif msg.document then
admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.document
elseif msg.audio then
admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.audio
elseif msg.contact then
admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.contact
elseif msg.video then
admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.video
elseif msg.location then
admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.location
elseif msg.voice then
admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.voice
else
admin_temp.flood[msg.chat.id_str][msg.from.id_str] = admin_temp.flood[msg.chat.id_str][msg.from.id_str] + group.antiflood.text
end
if admin_temp.flood[msg.chat.id_str][msg.from.id_str] > 99 then
drua.kick_user(msg.chat.id, msg.from.id)
local output = flags[5].kicked:gsub('GROUPNAME', msg.chat.title)
sendMessage(msg.from.id, output)
admin_temp.flood[msg.chat.id_str][msg.from.id_str] = nil
return
end
end
end end
if msg.new_chat_participant then if msg.new_chat_participant then
@ -350,7 +414,8 @@ local commands = {
{ -- groups { -- groups
triggers = { triggers = {
'^/groups[@'..bot.username..']*$' '^/groups$',
'^/groups@'..bot.username
}, },
command = 'groups', command = 'groups',
@ -380,7 +445,8 @@ local commands = {
{ -- ahelp { -- ahelp
triggers = { triggers = {
'^/ahelp[@'..bot.username..']*$' '^/ahelp$',
'^/ahelp@'..bot.username
}, },
command = 'ahelp', command = 'ahelp',
@ -391,7 +457,7 @@ local commands = {
local rank = get_rank(msg.from.id, msg.chat.id) local rank = get_rank(msg.from.id, msg.chat.id)
local output = '*Commands for ' .. ranks[rank] .. ':*\n' local output = '*Commands for ' .. ranks[rank] .. ':*\n'
for i = 1, rank do for i = 1, rank do
for ind, val in ipairs(database.administration.help[i]) do for ind, val in ipairs(admin_temp.help[i]) do
output = output .. '• /' .. val .. '\n' output = output .. '• /' .. val .. '\n'
end end
end end
@ -405,9 +471,10 @@ local commands = {
{ -- alist { -- alist
triggers = { triggers = {
'^/alist[@'..bot.username..']*$', '^/ops$',
'^/ops[@'..bot.username..']*$', '^/ops@'..bot.username,
'^/oplist[@'..bot.username..']*$' '^/oplist$',
'^/oplist@'..bot.username
}, },
command = 'ops', command = 'ops',
@ -440,8 +507,8 @@ local commands = {
{ -- desc { -- desc
triggers = { triggers = {
'^/desc[@'..bot.username..']*$', '^/desc[ription]*$',
'^/description[@'..bot.username..']*$' '^/desc[ription]*@'..bot.username
}, },
command = 'description', command = 'description',
@ -460,7 +527,8 @@ local commands = {
{ -- rules { -- rules
triggers = { triggers = {
'^/rules[@'..bot.username..']*$' '^/rules$',
'^/rules@'..bot.username
}, },
command = 'rules', command = 'rules',
@ -481,7 +549,8 @@ local commands = {
{ -- motd { -- motd
triggers = { triggers = {
'^/motd[@'..bot.username..']*' '^/motd$',
'^/motd@'..bot.username
}, },
command = 'motd', command = 'motd',
@ -499,7 +568,8 @@ local commands = {
{ -- link { -- link
triggers = { triggers = {
'^/link[@'..bot.username..']*' '^/link$',
'^/link@'..bot.username
}, },
command = 'link', command = 'link',
@ -598,7 +668,7 @@ local commands = {
'^/changerule@' .. bot.username '^/changerule@' .. bot.username
}, },
command = 'changerule <i> <newrule>', command = 'changerule <i> <rule>',
privilege = 3, privilege = 3,
interior = true, interior = true,
@ -650,16 +720,16 @@ local commands = {
'^/setrules[@'..bot.username..']*' '^/setrules[@'..bot.username..']*'
}, },
command = 'setrules\\n<rule1>\\n\\[rule2]\\n...', command = 'setrules <rules>',
privilege = 3, privilege = 3,
interior = true, interior = true,
action = function(msg, group) action = function(msg, group)
local input = msg.text:match('^/setrules[@'..bot.username..']* (.+)') local input = msg.text:match('^/setrules[@'..bot.username..']*(.+)')
if not input then if not input then
sendMessage(msg.chat.id, '```\n/setrules\n<rule1>\n[rule2]\n...\n```', true, msg.message_id, true) sendMessage(msg.chat.id, '```\n/setrules [rule]\n<rule>\n[rule]\n...\n```', true, msg.message_id, true)
return return
elseif input == '--' or input == '' then elseif input == ' --' or input == ' ' then
group.rules = {} group.rules = {}
sendReply(msg, 'The rules have been cleared.') sendReply(msg, 'The rules have been cleared.')
return return
@ -689,8 +759,12 @@ local commands = {
action = function(msg, group) action = function(msg, group)
local input = msg.text:input() local input = msg.text:input()
if not input then if not input then
sendReply(msg, 'Please specify the new message of the day.') if msg.reply_to_message and msg.reply_to_message.text then
return input = msg.reply_to_message.text
else
sendReply(msg, 'Please specify the new message of the day.')
return
end
elseif input == '--' or input == '' then elseif input == '--' or input == '' then
group.motd = nil group.motd = nil
sendReply(msg, 'The MOTD has been cleared.') sendReply(msg, 'The MOTD has been cleared.')
@ -764,6 +838,44 @@ local commands = {
end end
}, },
{ -- antiflood
triggers = {
'^/antiflood',
'^/antiflood@'..bot.username
},
command = 'antiflood <type> <i>',
privilege = 3,
interior = true,
action = function(msg, group)
if not group.flags[5] then
sendMessage(msg.chat.id, 'antiflood is not enabled. Use `/flag 5` to enable it.', true, nil, true)
return
end
if not group.antiflood then
group.antiflood = JSON.decode(JSON.encode(antiflood))
end
local input = msg.text_lower:input()
local output
if input then
local key, val = input:match('(%a+) (%d+)')
if not group.antiflood[key] or not tonumber(val) then
output = 'Not a valid message type or number.'
else
group.antiflood[key] = val
output = 'A *' .. key .. '* message is 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'
for k,v in pairs(group.antiflood) do
output = output .. '*'..k..':* `'..v..'`\n'
end
end
sendMessage(msg.chat.id, output, true, msg.message_id, true)
end
},
{ -- mod { -- mod
triggers = { triggers = {
'^/mod', '^/mod',
@ -792,7 +904,7 @@ local commands = {
return return
end end
if group.grouptype == 'supergroup' then if group.grouptype == 'supergroup' then
drua.channel_set_admin(msg.chat.id, target.id, 1) drua.channel_set_admin(msg.chat.id, target.id, 2)
end end
group.mods[target.id_str] = true group.mods[target.id_str] = true
sendReply(msg, target.name .. ' is now a moderator.') sendReply(msg, target.name .. ' is now a moderator.')
@ -827,7 +939,7 @@ local commands = {
group.mods[target.id_str] = nil group.mods[target.id_str] = nil
end end
if group.grouptype == 'supergroup' then if group.grouptype == 'supergroup' then
drua.channel_set_admin(msg.chat.id, target.id, 1) drua.channel_set_admin(msg.chat.id, target.id, 2)
end end
group.govs[target.id_str] = true group.govs[target.id_str] = true
sendReply(msg, target.name .. ' is now a governor.') sendReply(msg, target.name .. ' is now a governor.')
@ -993,11 +1105,11 @@ end
database.administration.help = {} database.administration.help = {}
for i,v in ipairs(ranks) do for i,v in ipairs(ranks) do
database.administration.help[i] = {} admin_temp.help[i] = {}
end end
for i,v in ipairs(commands) do for i,v in ipairs(commands) do
if v.command then if v.command then
table.insert(database.administration.help[v.privilege], v.command) table.insert(admin_temp.help[v.privilege], v.command)
end end
end end
@ -1021,12 +1133,17 @@ local action = function(msg)
return true return true
end end
local cron = function()
admin_temp.flood = {}
end
local command = 'groups' local command = 'groups'
local doc = '`Returns a list of administrated groups.\nUse /ahelp for more administrative commands.`' local doc = '`Returns a list of administrated groups.\nUse /ahelp for more administrative commands.`'
return { return {
action = action, action = action,
triggers = triggers, triggers = triggers,
cron = cron,
doc = doc, doc = doc,
command = command command = command
} }

View File

@ -29,12 +29,12 @@ local action = function(msg)
local message, res = HTTP.request(url) local message, res = HTTP.request(url)
if message:len() == 0 then if not message or res ~= 200 or message:len() == 0 then
url = 'http://api.biblia.com/v1/bible/content/KJVAPOC.txt?key=' .. 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)
message, res = HTTP.request(url) message, res = HTTP.request(url)
end end
if res ~= 200 then if not message or res ~= 200 or message:len() == 0 then
message = config.errors.results message = config.errors.results
end end

View File

@ -4,7 +4,9 @@ if not database.hearthstone or os.time() > database.hearthstone.expiration then
print('Downloading Hearthstone database...') print('Downloading Hearthstone database...')
database.hearthstone = {} database.hearthstone = {
expiration = os.time() + 600000
}
local jstr, res = HTTPS.request('http://hearthstonejson.com/json/AllSets.json') local jstr, res = HTTPS.request('http://hearthstonejson.com/json/AllSets.json')
if res ~= 200 then if res ~= 200 then
@ -20,8 +22,6 @@ if not database.hearthstone or os.time() > database.hearthstone.expiration then
end end
end end
database.hearthstone.expiration = os.time() + 600000
print('Download complete! It will be stored for a week.') print('Download complete! It will be stored for a week.')
end end

View File

@ -19,6 +19,16 @@ get_word = function(s, i)
return t[i] or false return t[i] or false
end
-- Like get_word(), but better.
-- Returns the actual index.
function string:index()
local t = {}
for w in s:gmatch('%g+') do
table.insert(t, w)
end
return t
end end
-- Returns the string after the first space. -- Returns the string after the first space.