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 |
| /setlink | Sets a group's link. | 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 |
| /demod | Demotes a moderator to a user. | 3 | 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. |
| 3 | antisquig Strict | Automatically removes users whose names contain Arabic script or RTL characters. |
| 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
admin_temp = {
help = {},
flood = {}
}
-- Migration code: Remove this in v1.7.
-- Group data is now stored in a "groups" array.
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.'
},
[3] = {
name = 'antisquig Strict',
name = 'antisquig++',
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.',
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.',
enabled = 'Non-moderators will no longer 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 = {
[0] = 'Banned',
[1] = 'Users',
@ -182,7 +207,7 @@ local get_desc = function(chat_id)
local flaglist = ''
for i = 1, #flags do
if group.flags[i] then
output = output .. '' .. flags[i].short .. '\n'
flaglist = flaglist .. '' .. flags[i].short .. '\n'
end
end
if flaglist ~= '' then
@ -260,6 +285,45 @@ local commands = {
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
if msg.new_chat_participant then
@ -350,7 +414,8 @@ local commands = {
{ -- groups
triggers = {
'^/groups[@'..bot.username..']*$'
'^/groups$',
'^/groups@'..bot.username
},
command = 'groups',
@ -380,7 +445,8 @@ local commands = {
{ -- ahelp
triggers = {
'^/ahelp[@'..bot.username..']*$'
'^/ahelp$',
'^/ahelp@'..bot.username
},
command = 'ahelp',
@ -391,7 +457,7 @@ local commands = {
local rank = get_rank(msg.from.id, msg.chat.id)
local output = '*Commands for ' .. ranks[rank] .. ':*\n'
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'
end
end
@ -405,9 +471,10 @@ local commands = {
{ -- alist
triggers = {
'^/alist[@'..bot.username..']*$',
'^/ops[@'..bot.username..']*$',
'^/oplist[@'..bot.username..']*$'
'^/ops$',
'^/ops@'..bot.username,
'^/oplist$',
'^/oplist@'..bot.username
},
command = 'ops',
@ -440,8 +507,8 @@ local commands = {
{ -- desc
triggers = {
'^/desc[@'..bot.username..']*$',
'^/description[@'..bot.username..']*$'
'^/desc[ription]*$',
'^/desc[ription]*@'..bot.username
},
command = 'description',
@ -460,7 +527,8 @@ local commands = {
{ -- rules
triggers = {
'^/rules[@'..bot.username..']*$'
'^/rules$',
'^/rules@'..bot.username
},
command = 'rules',
@ -481,7 +549,8 @@ local commands = {
{ -- motd
triggers = {
'^/motd[@'..bot.username..']*'
'^/motd$',
'^/motd@'..bot.username
},
command = 'motd',
@ -499,7 +568,8 @@ local commands = {
{ -- link
triggers = {
'^/link[@'..bot.username..']*'
'^/link$',
'^/link@'..bot.username
},
command = 'link',
@ -598,7 +668,7 @@ local commands = {
'^/changerule@' .. bot.username
},
command = 'changerule <i> <newrule>',
command = 'changerule <i> <rule>',
privilege = 3,
interior = true,
@ -650,16 +720,16 @@ local commands = {
'^/setrules[@'..bot.username..']*'
},
command = 'setrules\\n<rule1>\\n\\[rule2]\\n...',
command = 'setrules <rules>',
privilege = 3,
interior = true,
action = function(msg, group)
local input = msg.text:match('^/setrules[@'..bot.username..']* (.+)')
local input = msg.text:match('^/setrules[@'..bot.username..']*(.+)')
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
elseif input == '--' or input == '' then
elseif input == ' --' or input == ' ' then
group.rules = {}
sendReply(msg, 'The rules have been cleared.')
return
@ -689,8 +759,12 @@ local commands = {
action = function(msg, group)
local input = msg.text:input()
if not input then
sendReply(msg, 'Please specify the new message of the day.')
return
if msg.reply_to_message and msg.reply_to_message.text then
input = msg.reply_to_message.text
else
sendReply(msg, 'Please specify the new message of the day.')
return
end
elseif input == '--' or input == '' then
group.motd = nil
sendReply(msg, 'The MOTD has been cleared.')
@ -764,6 +838,44 @@ local commands = {
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
triggers = {
'^/mod',
@ -792,7 +904,7 @@ local commands = {
return
end
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
group.mods[target.id_str] = true
sendReply(msg, target.name .. ' is now a moderator.')
@ -827,7 +939,7 @@ local commands = {
group.mods[target.id_str] = nil
end
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
group.govs[target.id_str] = true
sendReply(msg, target.name .. ' is now a governor.')
@ -993,11 +1105,11 @@ end
database.administration.help = {}
for i,v in ipairs(ranks) do
database.administration.help[i] = {}
admin_temp.help[i] = {}
end
for i,v in ipairs(commands) do
if v.command then
table.insert(database.administration.help[v.privilege], v.command)
table.insert(admin_temp.help[v.privilege], v.command)
end
end
@ -1021,12 +1133,17 @@ local action = function(msg)
return true
end
local cron = function()
admin_temp.flood = {}
end
local command = 'groups'
local doc = '`Returns a list of administrated groups.\nUse /ahelp for more administrative commands.`'
return {
action = action,
triggers = triggers,
cron = cron,
doc = doc,
command = command
}

View File

@ -29,12 +29,12 @@ local action = function(msg)
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)
message, res = HTTP.request(url)
end
if res ~= 200 then
if not message or res ~= 200 or message:len() == 0 then
message = config.errors.results
end

View File

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

View File

@ -19,6 +19,16 @@ get_word = function(s, i)
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
-- Returns the string after the first space.