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