diff --git a/lua/groupbutler/config.lua b/lua/groupbutler/config.lua
index 3257b7d50..b21d78688 100644
--- a/lua/groupbutler/config.lua
+++ b/lua/groupbutler/config.lua
@@ -247,7 +247,8 @@ local _M =
},
chat_hashes = {'extra', 'info', 'links', 'warns', 'mediawarn', 'spamwarns', 'blocked', 'report', 'defpermissions',
'defpermduration'},
- chat_sets = {'whitelist'},
+ chat_sets = {'whitelist', 'blacklist'},--, 'mods'},
+
bot_keys = {
d3 = {'bot:general', 'bot:usernames', 'bot:chat:latsmsg'},
d2 = {'bot:groupsid', 'bot:groupsid:removed', 'tempbanned', 'bot:blocked', 'remolden_chats'} --remolden_chats: chat removed with $remold command
diff --git a/lua/groupbutler/plugins/help.lua b/lua/groupbutler/plugins/help.lua
index e7429d37e..cceb8569c 100644
--- a/lua/groupbutler/plugins/help.lua
+++ b/lua/groupbutler/plugins/help.lua
@@ -144,8 +144,28 @@ If users send a whitelisted link, they won't be warned or kicked.
When the group link is saved with `/setlink`, it gets automatically added to the whitelist.
*Why links are saved without* _https://_ *and* _www_*?*
+The bot auto-removes _https://, http:// and www_ from every link to reduce the possibility of having the same link saved twice.
+]])
+ elseif key == 'blacklist' then
+ return _([[*Blacklist settings*
+
+If an user sends a blacklisted link, it will be deleted.
+
+`/blacklist [link(s)]` or `/bl [link(s)]`: add one or more links to the blacklist.
+`/unblacklist [link(s)]` or `/unbl [link(s)]`: remove one or more links from the blacklist.
+`/blacklist` or `/bl`: get the blacklist.
+`/blacklistl -` or `/bl -`: empty the blacklist.
+
+*Why links are saved without* _https://_ *and* _www_*?*
+The bot auto-removes _https://, http:// and www_ from every link to reduce the possibility of having the same link saved twice.
+]])
+ elseif key == 'extra' then
+ return i18n([[
+*Extra commands*
+
The bot auto-removes _https://, http:// and www_ from every link to reduce the possibility of having the same link saved twice.]]), -- luacheck: ignore 631
extra = i18n([[*Extra commands*
+
#extra commands are a smart way to save your own custom commands.
ā¢ `/extra [#trigger] [reply]`: set a reply to be sent when someone writes the trigger.
@@ -254,9 +274,12 @@ local function dk_admins(self)
[i18n("Extra commands")] = 'extra',
[i18n("Warns")] = 'warns'
},
- {
- [i18n("Welcome settings")] = 'welcome',
+ {
[i18n("Links whitelist")] = 'whitelist',
+ [i18n("Links blacklist")] = 'blacklist',
+ },
+ {
+ [i18n("Welcome settings")] = 'welcome',
}
}
for _, line in pairs(list) do
diff --git a/lua/plugins/antispam.lua b/lua/plugins/antispam.lua
new file mode 100644
index 000000000..ddf82d54e
--- /dev/null
+++ b/lua/plugins/antispam.lua
@@ -0,0 +1,514 @@
+local config = require 'config'
+local u = require 'utilities'
+local api = require 'methods'
+local db = require 'database'
+local locale = require 'languages'
+local i18n = locale.translate
+
+local plugin = {}
+
+local function is_whitelisted(chat_id, text)
+ local set = ('chat:%d:whitelist'):format(chat_id)
+ local links = db:smembers(set)
+ if links and next(links) then
+ for i=1, #links do
+ if text:find(links[i]:lower():gsub('%-', '%%-')) then
+ return true
+ end
+ end
+ end
+end
+
+local function getAntispamWarns(chat_id, user_id)
+ local max_allowed = (db:hget('chat:'..chat_id..':antispam', 'warns')) or config.chat_settings['antispam']['warns']
+ max_allowed = tonumber(max_allowed)
+ local warns_received = (db:hincrby('chat:'..chat_id..':spamwarns', user_id, 1))
+ warns_received = tonumber(warns_received)
+
+ return warns_received, max_allowed
+end
+
+local humanizations = {
+ ['ban'] = i18n('banned'),
+ ['kick'] = i18n('kicked'),
+ ['mute'] = i18n('muted'),
+ ['links'] = i18n('telegram.me links'),
+ ['forwards'] = i18n('Channels messages')
+}
+
+function plugin.onEveryMessage(msg)
+ if not msg.inline and msg.spam and msg.chat.id < 0 and not msg.cb and not msg.from.admin then
+ local status = db:hget('chat:'..msg.chat.id..':antispam', msg.spam)
+ if status and status ~= 'alwd' then
+ local whitelisted
+ if msg.spam == 'links' then
+ whitelisted = is_whitelisted(msg.chat.id, msg.text:lower())
+ --[[elseif msg.forward_from_chat then
+ if msg.forward_from_chat.type == 'channel' then
+ whitelisted = is_whitelisted_channel(msg.chat.id, msg.forward_from_chat.id)
+ end]]
+ end
+
+ if not whitelisted then
+ local hammer_text = nil
+ local name = u.getname_final(msg.from)
+ local warns_received, max_allowed = getAntispamWarns(msg.chat.id, msg.from.id) --also increases the warns counter
+
+ if warns_received >= max_allowed then
+ if status == 'del' then
+ api.deleteMessage(msg.chat.id, msg.message_id)
+ end
+
+ local action = (db:hget('chat:'..msg.chat.id..':antispam', 'action')) or config.chat_settings['antispam']['action']
+
+ local res
+ if action == 'ban' then
+ res = api.banUser(msg.chat.id, msg.from.id)
+ elseif action == 'kick' then
+ res = api.kickUser(msg.chat.id, msg.from.id)
+ elseif action == 'mute' then
+ res = api.muteUser(msg.chat.id, msg.from.id)
+ end
+ if res then
+ db:hdel('chat:'..msg.chat.id..':spamwarns', msg.from.id) --remove spam warns
+ api.sendMessage(msg.chat.id,
+ i18n('%s %s for spam! (%d/%d)'):format(name, humanizations[action], warns_received, max_allowed), 'html')
+ end
+ else
+ if status == 'del' and warns_received == max_allowed - 1 then
+ api.deleteMessage(msg.chat.id, msg.message_id)
+ api.sendReply(msg, i18n('%s, spam is not allowed here. The next time you will be restricted'):format(name),
+ 'html')
+ elseif status == 'del' then
+ --just delete
+ api.deleteMessage(msg.chat.id, msg.message_id)
+ elseif status ~= 'del' then
+ api.sendReply(msg, i18n('%s, this kind of spam is not allowed in this chat (%d/%d)')
+ :format(name, warns_received, max_allowed), 'html')
+ end
+ end
+ local name_pretty = {links = i18n("telegram.me link"), forwards = i18n("message from a channel")}
+ u.logEvent('spamwarn', msg,
+ {hammered = hammer_text, warns = warns_received, warnmax = max_allowed, spam_type = name_pretty[msg.spam]})
+ end
+ end
+ end
+
+ if msg.edited then return false end
+ return true
+end
+
+local function toggleAntispamSetting(chat_id, key)
+ local hash = 'chat:'..chat_id..':antispam'
+ local current = db:hget(hash, key) or config.chat_settings['antispam'][key]
+
+ local next_state = { ['alwd'] = 'warn', ['warn'] = 'del', ['del'] = 'alwd' }
+ local new = next_state[current] or 'alwd'
+ db:hset(hash, key, new)
+
+ if key == 'forwards' then
+ if new == 'alwd' then
+ return i18n("forwards are allowed")
+ elseif new == 'warn' then
+ return i18n("warn for forwards")
+ elseif new == 'del' then
+ return i18n("forwards will be deleted")
+ end
+ elseif key == 'links' then
+ if new == 'alwd' then
+ return i18n("links are allowed")
+ elseif new == 'warn' then
+ return i18n("warn for links")
+ elseif new == 'del' then
+ return i18n("links will be deleted")
+ end
+ end
+end
+
+local function changeWarnsNumber(chat_id, action)
+ local hash = 'chat:'..chat_id..':antispam'
+ local key = 'warns'
+ local current = (db:hget(hash, key)) or config.chat_settings['antispam'][key]
+ current = tonumber(current)
+ if current < 1 then
+ current = 1
+ db:hset(hash, key, 1)
+ end
+
+ if current == 1 and action == 'dim' then
+ return i18n("You can't go lower")
+ elseif current == 7 and action == 'raise' then
+ return i18n("You can't go higher")
+ else
+ local new
+ if action == 'dim' then
+ new = db:hincrby(hash, key, -1)
+ elseif action == 'raise' then
+ new = db:hincrby(hash, key, 1)
+ end
+ return i18n("New value: %d"):format(new)
+ end
+end
+
+local function changeAction(chat_id)
+ local hash = 'chat:'..chat_id..':antispam'
+ local key = 'action'
+ local current = (db:hget(hash, key)) or config.chat_settings['antispam'][key]
+ local new_action
+
+ if current == 'ban' then new_action = 'kick'
+ elseif current == 'kick' then new_action = 'mute'
+ elseif current == 'mute' then new_action = 'ban' end
+
+ db:hset(hash, key, new_action)
+
+ return 'ā
'
+end
+
+local function get_alert_text(key)
+ if key == 'links' then
+ return i18n("Allow/forbid telegram.me links")
+ elseif key == 'forwards' then
+ return i18n("Allow/forbid forwarded messages from channels")
+ elseif key == 'warns' then
+ return i18n("Set how many times the bot should warn the user before kick/ban him")
+ else
+ return i18n("Description not available")
+ end
+end
+
+local function doKeyboard_antispam(chat_id)
+ local keyboard = {inline_keyboard = {}}
+
+ for field, _ in pairs(config.chat_settings['antispam']) do
+ if field == 'links' or field == 'forwards' then
+ local icon = 'ā
'
+ local status = (db:hget('chat:'..chat_id..':antispam', field)) or config.chat_settings['antispam'][field]
+ if status == 'warn' then
+ icon = 'ā'
+ elseif status == 'del' then icon = 'š' end
+ local line = {
+ {text = i18n(humanizations[field] or field), callback_data = 'antispam:alert:'..field..':'..locale.language},
+ {text = icon, callback_data = 'antispam:toggle:'..field..':'..chat_id}
+ }
+ table.insert(keyboard.inline_keyboard, line)
+ end
+ end
+
+ local warns = (db:hget('chat:'..chat_id..':antispam', 'warns')) or config.chat_settings['antispam']['warns']
+ local action = (db:hget('chat:'..chat_id..':antispam', 'action')) or config.chat_settings['antispam']['action']
+
+ if action == 'kick' then
+ action = i18n("Kick š")
+ elseif action == 'ban' then
+ action = i18n("Ban šØ")
+ elseif action == 'mute' then
+ action = i18n("Mute š")
+ end
+
+ local line = {
+ {text = 'Warns: '..warns, callback_data = 'antispam:alert:warns:'..locale.language},
+ {text = 'ā', callback_data = 'antispam:toggle:dim:'..chat_id},
+ {text = 'ā', callback_data = 'antispam:toggle:raise:'..chat_id},
+ {text = action, callback_data = 'antispam:toggle:action:'..chat_id}
+ }
+
+ table.insert(keyboard.inline_keyboard, line)
+
+ --back button
+ table.insert(keyboard.inline_keyboard, {{text = 'š', callback_data = 'config:back:'..chat_id}})
+
+ return keyboard
+end
+
+local function get_url(text, entity)
+ return text:sub(entity.offset + 1, entity.offset + entity.length)
+end
+
+local function urls_table(entities, text)
+ local links = {}
+ for _, entity in pairs(entities) do
+ if entity.type == 'url' then
+ local url = get_url(text, entity):gsub(' ', ''):gsub('https?://', ''):gsub('www.', '')
+ table.insert(links, url)
+ end
+ end
+
+ return links
+end
+
+function plugin.onCallbackQuery(msg, blocks)
+
+ if blocks[1] == 'alert' then
+ if config.available_languages[blocks[3]] then
+ locale.language = blocks[3]
+ end
+ local text = get_alert_text(blocks[2])
+ api.answerCallbackQuery(msg.cb_id, text, true, config.bot_settings.cache_time.alert_help)
+ else
+
+ local chat_id = msg.target_id
+ if not u.is_allowed('config', chat_id, msg.from) then
+ api.answerCallbackQuery(msg.cb_id, i18n("You're no longer an admin"))
+ else
+ local antispam_first = i18n([[*Anti-spam settings*
+Choose which kind of spam you want to forbid
+ā¢ ā
= *Allowed*
+ā¢ ā = *Not allowed*
+ā¢ š = *Delete*
+When set on `delete`, the bot doesn't warn users until they are about to be kicked/banned/muted (at the second-to-last warning)
+]])
+
+ local keyboard, text
+
+ if blocks[1] == 'toggle' then
+ if blocks[2] == 'forwards' or blocks[2] == 'links' then
+ text = toggleAntispamSetting(chat_id, blocks[2])
+ else
+ if blocks[2] == 'raise' or blocks[2] == 'dim' then
+ text = changeWarnsNumber(chat_id, blocks[2])
+ elseif blocks[2] == 'action' then
+ text = changeAction(chat_id, blocks[2])
+ end
+ end
+ end
+
+ keyboard = doKeyboard_antispam(chat_id)
+ api.editMessageText(msg.chat.id, msg.message_id, antispam_first, true, keyboard)
+ if text then api.answerCallbackQuery(msg.cb_id, text) end
+ end
+ end
+end
+
+local function edit_channels_whitelist(chat_id, list, action)
+
+ local channels = {valid = {}, not_valid ={}}
+ local for_entered
+ local set = ('chat:%d:chanwhitelist'):format(chat_id)
+ local res
+ for channel_id in list:gmatch('-%d+') do
+ if action == 'add' then
+ res = db:sadd(set, channel_id)
+ elseif action == 'rem' then
+ res = db:srem(set, channel_id)
+ end
+
+ if res == 1 then
+ table.insert(channels.valid, channel_id)
+ elseif res == 0 then
+ table.insert(channels.not_valid, channel_id)
+ end
+
+ for_entered = true
+ end
+
+ return for_entered, channels
+end
+
+function plugin.onTextMessage(msg, blocks)
+ if u.is_allowed('texts', msg.chat.id, msg.from) then
+ if (blocks[1] == 'wl' or blocks[1] == 'whitelist') and blocks[2] then
+ if blocks[2] == '-' then
+ local set = ('chat:%d:whitelist'):format(msg.chat.id)
+ local n = db:scard(set) or 0
+ local text
+ if n == 0 then
+ text = i18n("_The whitelist was already empty_")
+ else
+ db:del(set)
+ text = i18n("*Whitelist cleaned*\n%d links have been removed"):format(n)
+ end
+ api.sendReply(msg, text, true)
+ else
+ local text
+ if msg.entities then
+ local links = urls_table(msg.entities, msg.text)
+ if not next(links) then
+ text = i18n("_I can't find any url in this message_")
+ else
+ local new = db:sadd(('chat:%d:whitelist'):format(msg.chat.id), unpack(links))
+ text = i18n("%d link(s) will be whitelisted"):format(#links - (#links - new))
+ if new ~= #links then
+ text = text..i18n("\n%d links were already in the list"):format(#links - new)
+ end
+ end
+ else
+ text = i18n("_I can't find any url in this message_")
+ end
+ api.sendReply(msg, text, true)
+ end
+ end
+ if (blocks[1] == 'wl' or blocks[1] == 'whitelist') and not blocks[2] then
+ local links = db:smembers(('chat:%d:whitelist'):format(msg.chat.id))
+ if not next(links) then
+ api.sendReply(msg, i18n("_The whitelist is empty_.\nUse `/wl [links]` to add some links to the whitelist"), true)
+ else
+ local text = i18n("Whitelisted links:\n\n")
+ for i=1, #links do
+ text = text..'ā¢ '..links[i]..'\n'
+ end
+ api.sendReply(msg, text)
+ end
+ end
+ if blocks[1] == 'unwl' or blocks[1] == 'unwhitelist' then
+ local text
+ if msg.entities then
+ local links = urls_table(msg.entities, msg.text)
+ if not next(links) then
+ text = i18n("_I can't find any url in this message_")
+ else
+ local removed = db:srem(('chat:%d:whitelist'):format(msg.chat.id), unpack(links))
+ text = i18n("%d link(s) removed from the whitelist"):format(removed)
+ if removed ~= #links then
+ text = text..i18n("\n%d links were already in the list"):format(#links - removed)
+ end
+ end
+ else
+ text = i18n("_I can't find any url in this message_")
+ end
+ api.sendReply(msg, text, true)
+ end
+ if blocks[1] == 'funwl' then --force the unwhitelist of a link
+ db:srem(('chat:%d:whitelist'):format(msg.chat.id), blocks[2])
+ api.sendReply(msg, 'Done')
+ end
+
+ if (blocks[1] == 'bl' or blocks[1] == 'blacklist') and blocks[2] then
+ if blocks[2] == '-' then
+ local set = ('chat:%d:blacklist'):format(msg.chat.id)
+ local n = db:scard(set) or 0
+ local text
+ if n == 0 then
+ text = i18n("_The blacklist was already empty_")
+ else
+ db:del(set)
+ text = i18n("*Blacklist cleaned*\n%d links have been removed"):format(n)
+ end
+ api.sendReply(msg, text, true)
+ else
+ local text
+ if msg.entities then
+ local links = urls_table(msg.entities, msg.text)
+ if not next(links) then
+ text = i18n("_I can't find any url in this message_")
+ else
+ local new = db:sadd(('chat:%d:blacklist'):format(msg.chat.id), unpack(links))
+ text = i18n("%d link(s) will be blacklisted"):format(#links - (#links - new))
+ if new ~= #links then
+ text = text..i18n("\n%d links were already in the list"):format(#links - new)
+ end
+ end
+ else
+ text = i18n("_I can't find any url in this message_")
+ end
+ api.sendReply(msg, text, true)
+ end
+ end
+ if (blocks[1] == 'bl' or blocks[1] == 'blacklist') and not blocks[2] then
+ local links = db:smembers(('chat:%d:blacklist'):format(msg.chat.id))
+ if not next(links) then
+ api.sendReply(msg, i18n("_The blacklist is empty_.\nUse `/bl [links]` to add some links to the blacklist"), true)
+ else
+ local text = i18n("Blacklisted links:\n\n")
+ for i=1, #links do
+ text = text..'ā¢ '..links[i]..'\n'
+ end
+ api.sendReply(msg, text)
+ end
+ end
+ if blocks[1] == 'unbl' or blocks[1] == 'unblacklist' then
+ local text
+ if msg.entities then
+ local links = urls_table(msg.entities, msg.text)
+ if not next(links) then
+ text = i18n("_I can't find any url in this message_")
+ else
+ local removed = db:srem(('chat:%d:blacklist'):format(msg.chat.id), unpack(links))
+ text = i18n("%d link(s) removed from the blacklist"):format(removed)
+ if removed ~= #links then
+ text = text..i18n("\n%d links were already in the list"):format(#links - removed)
+ end
+ end
+ else
+ text = i18n("_I can't find any url in this message_")
+ end
+ api.sendReply(msg, text, true)
+ end
+ if blocks[1] == 'funbl' then --force the unblacklist of a link
+ db:srem(('chat:%d:blacklist'):format(msg.chat.id), blocks[2])
+ api.sendReply(msg, 'Done')
+ end
+
+ if blocks[1] == 'wlchan' and not blocks[2] then
+ local channels = db:smembers(('chat:%d:chanwhitelist'):format(msg.chat.id))
+ if not next(channels) then
+ api.sendReply(msg, i18n("_Whitelist of channels empty_"), true)
+ else
+ api.sendReply(msg, i18n("*Whitelisted channels:*\n%s"):format(table.concat(channels, '\n')), true)
+ end
+ end
+ if blocks[1] == 'wlchan' and blocks[2] then
+ local for_entered, channels = edit_channels_whitelist(msg.chat.id, blocks[2], 'add')
+
+ if not for_entered then
+ api.sendReply(msg, i18n("_I can't find a channel ID in your message_"), true)
+ else
+ local text = ''
+ if next(channels.valid) then
+ text = text..("*Channels whitelisted*: `%s`\n"):format(table.concat(channels.valid, ', '))
+ end
+ if next(channels.not_valid) then
+ text = text..("*Channels already whitelisted*: `%s`\n"):format(table.concat(channels.not_valid, ', '))
+ end
+
+ api.sendReply(msg, text, true)
+ end
+ end
+ if blocks[1] == 'unwlchan' then
+ local for_entered, channels = edit_channels_whitelist(msg.chat.id, blocks[2], 'rem')
+
+ if not for_entered then
+ api.sendReply(msg, i18n("_I can't find a channel ID in your message_"), true)
+ else
+ local text = ''
+ if next(channels.valid) then
+ text = text..("*Channels unwhitelisted*: `%s`\n"):format(table.concat(channels.valid, ', '))
+ end
+ if next(channels.not_valid) then
+ text = text..("*Channels not whitelisted*: `%s`\n"):format(table.concat(channels.not_valid, ', '))
+ end
+
+ api.sendReply(msg, text, true)
+ end
+ end
+ end
+end
+
+plugin.triggers = {
+ onCallbackQuery = {
+ '^###cb:antispam:(toggle):(%w+):(-?%d+)$',
+ '^###cb:antispam:(alert):(%w+):([%w_]+)$',
+ '^###cb:(config):antispam:(-?%d+)$'
+ },
+ onTextMessage = {
+ config.cmd..'(wl) (.+)$',
+ config.cmd..'(whitelist) (.+)$',
+ --config.cmd..'(wlchan) (.+)$',
+ config.cmd..'(unwl) (.+)$',
+ config.cmd..'(unwhitelist) (.+)$',
+ --config.cmd..'(unwlchan) (.+)$',
+ config.cmd..'(wl)$',
+ config.cmd..'(whitelist)$',
+ --config.cmd..'(wlchan)$',
+ config.cmd..'(funwl) (.+)',
+ config.cmd..'(bl) (.+)$',
+ config.cmd..'(blacklist) (.+)$',
+ config.cmd..'(bl)$',
+ config.cmd..'(blacklist)$',
+ config.cmd..'(unbl) (.+)$',
+ config.cmd..'(unblacklist) (.+)$',
+ config.cmd..'(funbl) (.+)'
+ }
+}
+
+return plugin
diff --git a/lua/plugins/onmessage.lua b/lua/plugins/onmessage.lua
new file mode 100644
index 000000000..ee6893f0e
--- /dev/null
+++ b/lua/plugins/onmessage.lua
@@ -0,0 +1,258 @@
+local config = require 'config'
+local u = require 'utilities'
+local api = require 'methods'
+local db = require 'database'
+local locale = require 'languages'
+local i18n = locale.translate
+
+local plugin = {}
+
+local function max_reached(chat_id, user_id)
+ local max = tonumber(db:hget('chat:'..chat_id..':warnsettings', 'mediamax'))
+ or config.chat_settings.warnsettings.mediamax
+ local n = tonumber(db:hincrby('chat:'..chat_id..':mediawarn', user_id, 1))
+ if n >= max then
+ return true, n, max
+ else
+ return false, n, max
+ end
+end
+
+local function is_ignored(chat_id, msg_type)
+ local hash = 'chat:'..chat_id..':floodexceptions'
+ local status = (db:hget(hash, msg_type)) or 'no'
+ if status == 'yes' then
+ return true
+ elseif status == 'no' then
+ return false
+ end
+end
+
+local function is_flooding_funct(msg)
+ local spamhash = 'spam:'..msg.chat.id..':'..msg.from.id
+
+ local msgs = tonumber(db:get(spamhash)) or 1
+
+ local max_msgs = tonumber(db:hget('chat:'..msg.chat.id..':flood', 'MaxFlood')) or 5
+ if msg.cb then max_msgs = 15 end
+
+ local max_time = 5
+ db:setex(spamhash, max_time, msgs+1)
+
+ if msgs > max_msgs then
+ return true, msgs, max_msgs
+ else
+ return false
+ end
+end
+
+local function is_blocked(id)
+ if db:sismember('bot:blocked', id) then
+ return true
+ else
+ return false
+ end
+end
+
+local function is_whitelisted(chat_id, text)
+ local set = ('chat:%d:whitelist'):format(chat_id)
+ local links = db:smembers(set)
+ if links and next(links) then
+ for i=1, #links do
+ if text:match(links[i]:gsub('%-', '%%-')) then
+ --print('Whitelist:', links[i])
+ return true
+ end
+ end
+ end
+end
+
+local function is_blacklisted(chat_id, text)
+ local set = ('chat:%d:blacklist'):format(chat_id)
+ local links = db:smembers(set)
+ if links and next(links) then
+ for i=1, #links do
+ if text:match(links[i]:gsub('%-', '%%-')) then
+ return true
+ end
+ end
+ end
+end
+
+function plugin.onEveryMessage(msg)
+
+ if not msg.inline then
+
+ local msg_type = 'text'
+ if msg.forward_from or msg.forward_from_chat then msg_type = 'forward' end
+ if msg.media_type then msg_type = msg.media_type end
+ if not is_ignored(msg.chat.id, msg_type) and not msg.edited then
+ local is_flooding, msgs_sent, msgs_max = is_flooding_funct(msg)
+ if is_flooding then
+ local status = (db:hget('chat:'..msg.chat.id..':settings', 'Flood')) or config.chat_settings['settings']['Flood']
+ if status == 'on' and not msg.cb and not msg.from.admin then --if the status is on, and the user is not an admin, and the message is not a callback, then:
+ local action = db:hget('chat:'..msg.chat.id..':flood', 'ActionFlood')
+ local name = u.getname_final(msg.from)
+ local res, message
+ --try to kick or ban
+ if action == 'ban' then
+ res = api.banUser(msg.chat.id, msg.from.id)
+ elseif action == 'kick' then
+ res = api.kickUser(msg.chat.id, msg.from.id)
+ elseif action == 'mute' then
+ res = api.muteUser(msg.chat.id, msg.from.id)
+ end
+ --if kicked/banned, send a message
+ if res then
+ local log_hammered = action
+ if msgs_sent == (msgs_max + 1) then --send the message only if it's the message after the first message flood. Repeat after 5
+ if action == 'ban' then
+ message = i18n("%s banned for flood!"):format(name)
+ elseif action == 'kick' then
+ message = i18n("%s kicked for flood!"):format(name)
+ elseif action == 'mute' then
+ message = i18n("%s muted for flood!"):format(name)
+ end
+ api.sendMessage(msg.chat.id, message, 'html')
+ u.logEvent('flood', msg, {hammered = log_hammered})
+ end
+ end
+ end
+
+ -- if msg.cb then
+ -- api.answerCallbackQuery(msg.cb_id, i18n("ā¼ļø Please don't abuse the keyboard, requests will be ignored")) -- avoid to hit the limits with answerCallbackQuery
+ -- end
+ return false --if an user is spamming, don't go through plugins
+ end
+ end
+
+ if not msg.from.admin then
+
+ if msg.media and msg.chat.type ~= 'private' and not msg.cb and not msg.edited then
+ local media = msg.media_type
+ local hash = 'chat:'..msg.chat.id..':media'
+ local media_status = (db:hget(hash, media)) or config.chat_settings.media[media]
+ local blacklisted
+ if media == 'link' then
+ blacklisted = is_blacklisted(msg.chat.id, msg.text)
+ end
+
+ if blacklisted then
+ api.deleteMessage(msg.chat.id, msg.message_id)
+ elseif media_status ~= 'ok' then
+ local whitelisted
+ if media == 'link' then
+ whitelisted = is_whitelisted(msg.chat.id, msg.text)
+ end
+
+ if not whitelisted then
+ local status
+ local name = u.getname_final(msg.from)
+ local max_reached_var, n, max = max_reached(msg.chat.id, msg.from.id)
+ if max_reached_var then --max num reached. Kick/ban the user
+ status = (db:hget('chat:'..msg.chat.id..':warnsettings', 'mediatype'))
+ or config.chat_settings['warnsettings']['mediatype']
+ --try to kick/ban
+ local res, punishment
+ if status == 'kick' then
+ res = api.kickUser(msg.chat.id, msg.from.id)
+ punishment = i18n('kicked')
+ elseif status == 'ban' then
+ res = api.banUser(msg.chat.id, msg.from.id)
+ punishment = i18n('banned')
+ elseif status == 'mute' then
+ res = api.muteUser(msg.chat.id, msg.from.id)
+ punishment = i18n('muted')
+ end
+ if res then --kick worked
+ db:hdel('chat:'..msg.chat.id..':mediawarn', msg.from.id) --remove media warns
+ local message =
+ i18n('%s %s: media sent not allowed!\nāļø %d/%d
'):format(name, punishment, n, max)
+ api.sendMessage(msg.chat.id, message, 'html')
+ end
+
+ if media_status == 'del' then --do not forget to delete the message
+ api.deleteMessage(msg.chat.id, msg.message_id)
+ end
+ else --max num not reached -> warn or delete
+ if media_status ~= 'del' then
+ local message =
+ i18n('%s, this type of media is not allowed in this chat.\n(%d/%d
)'):format(name, n, max)
+ api.sendReply(msg, message, 'html')
+ elseif media_status == 'del' and n + 1 >= max then
+ api.deleteMessage(msg.chat.id, msg.message_id)
+ local message =
+ i18n([[%s, this type of media is not allowed in this chat.\nThe next time you will be banned/kicked/muted
+ ]]):format(name)
+ api.sendMessage(msg.chat.id, message, 'html')
+ elseif media_status == 'del' then
+ api.deleteMessage(msg.chat.id, msg.message_id)
+ end
+ end
+ u.logEvent('mediawarn', msg, {warns = n, warnmax = max, media = i18n(media), hammered = status})
+ end
+ end
+ end
+
+
+ local rtl_status = (db:hget('chat:'..msg.chat.id..':char', 'Rtl')) or config.chat_settings.char.Rtl
+ if rtl_status ~= 'allowed' then
+ local rtl = 'ā®'
+ local last_name = 'x'
+ if msg.from.last_name then last_name = msg.from.last_name end
+ local check = msg.text:find(rtl..'+') or msg.from.first_name:find(rtl..'+') or last_name:find(rtl..'+')
+ if check ~= nil then
+ local res, message
+ if rtl_status == 'kick' then
+ res = api.kickUser(msg.chat.id, msg.from.id)
+ message = i18n("%s kicked: RTL character in names/messages are not allowed!")
+ elseif rtl_status == 'ban' then
+ res = api.banUser(msg.chat.id, msg.from.id)
+ message = i18n("%s banned: RTL character in names/messages are not allowed!")
+ elseif rtl_status == 'mute' then
+ res = api.muteUser(msg.chat.id, msg.from.id)
+ message = i18n("%s muted: RTL character in names/messages are not allowed!")
+ end
+ if res then
+ local name = u.getname_final(msg.from)
+ api.sendMessage(msg.chat.id, message:format(name), 'html')
+ return false
+ end
+ end
+ end
+
+ if msg.text and msg.text:find('([\216-\219][\128-\191])') then
+ local arab_status = (db:hget('chat:'..msg.chat.id..':char', 'Arab')) or config.chat_settings.char.Arab
+ if arab_status ~= 'allowed' then
+ local res, message
+ if arab_status == 'kick' then
+ res = api.kickUser(msg.chat.id, msg.from.id)
+ message = i18n("%s kicked: arab/persian message detected!")
+ elseif arab_status == 'ban' then
+ res = api.banUser(msg.chat.id, msg.from.id)
+ message = i18n("%s banned: arab/persian message detected!")
+ elseif arab_status == 'mute' then
+ res = api.muteUser(msg.chat.id, msg.from.id)
+ message = i18n("%s muted: arab/persian message detected!")
+ end
+ if res then
+ local name = u.getname_final(msg.from)
+ api.sendMessage(msg.chat.id, message:format(name), 'html')
+ return false
+ end
+ end
+ end
+ end
+
+ end --if not msg.inline then [if statement closed]
+
+ if is_blocked(msg.from.id) then --ignore blocked users
+ return false --if an user is blocked, don't go through plugins
+ end
+
+ --don't return false for edited messages: the antispam needs to process them
+
+ return true
+end
+
+return plugin