diff --git a/config.lua.example b/config.lua.example index a4e4eb7..81fe21b 100644 --- a/config.lua.example +++ b/config.lua.example @@ -2,6 +2,8 @@ return { -- Your authorization token from the botfather. bot_api_key = '', + -- Bot's username without @ + bot_user_name = '', -- Your Telegram ID. admin = 1337, -- Two-letter language code. diff --git a/otouto/bot.lua b/otouto/bot.lua index 45cd581..25a79c9 100644 --- a/otouto/bot.lua +++ b/otouto/bot.lua @@ -71,7 +71,11 @@ function bot:on_msg_receive(msg, config) -- The fn run whenever a message is rec msg.text_lower = msg.text:lower() end - pre_process_msg(self, msg) + -- gsub out user name if multiple bots are in the same group + msg.text = string.gsub(msg.text, '@'..config.bot_user_name, "") + msg.text_lower = string.gsub(msg.text, '@'..string.lower(config.bot_user_name), "") + + msg = pre_process_msg(self, msg, config) for _, plugin in ipairs(self.plugins) do for _, trigger in pairs(plugin.triggers) do if string.match(msg.text_lower, trigger) then @@ -148,13 +152,14 @@ function bot:run(config) end -- Apply plugin.pre_process function -function pre_process_msg(self, msg) +function pre_process_msg(self, msg, config) for number,plugin in ipairs(self.plugins) do if plugin.pre_process and msg then -- print('Preprocess #'..number) -- remove comment to restore old behaviour - plugin:pre_process(msg, self) + new_msg = plugin:pre_process(msg, self, config) end end + return new_msg end function load_cred() diff --git a/otouto/plugins/afk.lua b/otouto/plugins/afk.lua index 9ba5e75..d2f615f 100644 --- a/otouto/plugins/afk.lua +++ b/otouto/plugins/afk.lua @@ -101,7 +101,7 @@ function afk:pre_process(msg, self) end end - return + return msg end function afk:action(msg) diff --git a/otouto/plugins/banhammer.lua b/otouto/plugins/banhammer.lua new file mode 100644 index 0000000..f62c388 --- /dev/null +++ b/otouto/plugins/banhammer.lua @@ -0,0 +1,253 @@ +local banhammer = {} + +local bindings = require('otouto.bindings') +local utilities = require('otouto.utilities') +local redis = (loadfile "./otouto/redis.lua")() + +banhammer.command = 'banhammer ' + +function banhammer:init(config) + banhammer.triggers = { + "^/(whitelist) (enable)$", + "^/(whitelist) (disable)$", + "^/(whitelist) (user) (%d+)$", + "^/(whitelist) (chat)$", + "^/(whitelist) (delete) (user) (%d+)$", + "^/(whitelist) (delete) (chat)$", + "^/(ban) (user) (%d+)$", + "^/(ban) (delete) (%d+)$", + "^/(kick) (%d+)$" + } + banhammer.doc = [[* +]]..config.cmd_pat..[[whitelist* __/__: Aktiviert/deaktiviert Whitelist +*]]..config.cmd_pat..[[whitelist* user __: Whiteliste User +*]]..config.cmd_pat..[[whitelist* chat: Whiteliste ganze Gruppe +*]]..config.cmd_pat..[[whitelist* delete user __: Lösche User von der Whitelist +*]]..config.cmd_pat..[[whitelist* delete chat: Lösche ganze Gruppe von der Whitelist +*]]..config.cmd_pat..[[ban* user __: Kicke User vom Chat und kicke ihn, wenn er erneut beitritt +*]]..config.cmd_pat..[[ban* delete __: Entbanne User +*]]..config.cmd_pat..[[kick* __: Kicke User aus dem Chat]] +end + +function banhammer:kick_user(user_id, chat_id, self, onlykick) + if user_id == tostring(our_id) then + return "Ich werde mich nicht selbst kicken!" + else + local request = bindings.request(self, 'kickChatMember', { + chat_id = chat_id, + user_id = user_id + } ) + if onlykick then return end + if not request then return 'User gebannt, aber kicken war nicht erfolgreich. Bin ich Administrator oder ist der User hier überhaupt?' end + return 'User '..user_id..' gebannt!' + end +end + +function banhammer:ban_user(user_id, chat_id, self) + if user_id == tostring(our_id) then + return "Ich werde mich nicht selbst kicken!" + else + -- Save to redis + local hash = 'banned:'..chat_id..':'..user_id + redis:set(hash, true) + -- Kick from chat + return banhammer:kick_user(user_id, chat_id, self) + end +end + +function banhammer:unban_user(user_id, chat_id, self, chat_type) + local hash = 'banned:'..chat_id..':'..user_id + redis:del(hash) + if chat_type == 'supergroup' then -- how can bots be admins anyway? + local request = bindings.request(self, 'unbanChatMember', { + chat_id = chat_id, + user_id = user_id + } ) + end + return 'User '..user_id..' wurde entbannt.' +end + +function banhammer:is_banned(user_id, chat_id) + local hash = 'banned:'..chat_id..':'..user_id + local banned = redis:get(hash) + return banned or false +end + +function banhammer:is_user_whitelisted(id) + local hash = 'whitelist:user#id'..id + local white = redis:get(hash) or false + return white +end + +function banhammer:is_chat_whitelisted(id) + local hash = 'whitelist:chat#id'..id + local white = redis:get(hash) or false + return white +end + +function banhammer:pre_process(msg, self, config) + -- SERVICE MESSAGE + if msg.new_chat_member then + local user_id = msg.new_chat_member.id + print('Checking invited user '..user_id) + local banned = banhammer:is_banned(user_id, msg.chat.id) + if banned then + print('User is banned!') + banhammer:kick_user(user_id, msg.chat.id, self, true) + end + -- No further checks + return msg + end + + -- BANNED USER TALKING + if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then + local user_id = msg.from.id + local chat_id = msg.chat.id + local banned = banhammer:is_banned(user_id, chat_id) + if banned then + print('Banned user talking!') + banhammer:ban_user(user_id, chat_id, self) + msg.text = '' + end + end + + + -- WHITELIST + local hash = 'whitelist:enabled' + local whitelist = redis:get(hash) + local issudo = is_sudo(msg, config) + + -- Allow all sudo users even if whitelist is allowed + if whitelist and not issudo then + print('Whitelist enabled and not sudo') + -- Check if user or chat is whitelisted + local allowed = banhammer:is_user_whitelisted(msg.from.id) + local has_been_warned = redis:hget('user:'..msg.from.id, 'has_been_warned') + + if not allowed then + print('User '..msg.from.id..' not whitelisted') + if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then + allowed = banhammer:is_chat_whitelisted(msg.chat.id) + if not allowed then + print ('Chat '..msg.chat.id..' not whitelisted') + else + print ('Chat '..msg.chat.id..' whitelisted :)') + end + else + if not has_been_warned then + utilities.send_reply(self, msg, "Dies ist ein privater Bot, der erst nach einer Freischaltung benutzt werden kann.\nThis is a private bot, which can only be after an approval.") + redis:hset('user:'..msg.from.id, 'has_been_warned', true) + else + print('User has already been warned!') + end + end + else + print('User '..msg.from.id..' allowed :)') + end + + if not allowed then + msg.text = '' + msg.text_lower = '' + msg.entities = '' + end + + else + print('Whitelist not enabled or is sudo') + end + + return msg +end + +function banhammer:action(msg, config) + if msg.from.id ~= config.admin then + utilities.send_reply(self, msg, config.errors.sudo) + return + end + + if matches[1] == 'ban' then + local user_id = matches[3] + local chat_id = msg.chat.id + + if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then + if matches[2] == 'user' then + local text = banhammer:ban_user(user_id, chat_id, self) + utilities.send_reply(self, msg, text) + return + end + if matches[2] == 'delete' then + local text = banhammer:unban_user(user_id, chat_id, self, msg.chat.type) + utilities.send_reply(self, msg, text) + return + end + else + utilities.send_reply(self, msg, 'Das ist keine Chat-Gruppe') + return + end + end + + if matches[1] == 'kick' then + if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then + banhammer:kick_user(matches[2], msg.chat.id, self, true) + return + else + utilities.send_reply(self, msg, 'Das ist keine Chat-Gruppe') + return + end + end + + if matches[1] == 'whitelist' then + if matches[2] == 'enable' then + local hash = 'whitelist:enabled' + redis:set(hash, true) + utilities.send_reply(self, msg, 'Whitelist aktiviert') + return + end + + if matches[2] == 'disable' then + local hash = 'whitelist:enabled' + redis:del(hash) + utilities.send_reply(self, msg, 'Whitelist deaktiviert') + return + end + + if matches[2] == 'user' then + local hash = 'whitelist:user#id'..matches[3] + redis:set(hash, true) + utilities.send_reply(self, msg, 'User '..matches[3]..' whitelisted') + return + end + + if matches[2] == 'chat' then + if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then + local hash = 'whitelist:chat#id'..msg.chat.id + redis:set(hash, true) + utilities.send_reply(self, msg, 'Chat '..msg.chat.id..' whitelisted') + return + else + utilities.send_reply(self, msg, 'Das ist keine Chat-Gruppe!') + return + end + end + + if matches[2] == 'delete' and matches[3] == 'user' then + local hash = 'whitelist:user#id'..matches[4] + redis:del(hash) + utilities.send_reply(self, msg, 'User '..matches[4]..' von der Whitelist entfernt!') + return + end + + if matches[2] == 'delete' and matches[3] == 'chat' then + if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then + local hash = 'whitelist:chat#id'..msg.chat.id + redis:del(hash) + utilities.send_reply(self, msg, 'Chat '..msg.chat.id..' von der Whitelist entfernt') + return + else + utilities.send_reply(self, msg, 'Das ist keine Chat-Gruppe!') + return + end + end + end +end + +return banhammer \ No newline at end of file diff --git a/otouto/plugins/getfile.lua b/otouto/plugins/getfile.lua index 5bca07f..378d96b 100644 --- a/otouto/plugins/getfile.lua +++ b/otouto/plugins/getfile.lua @@ -104,7 +104,7 @@ function media_download:pre_process(msg, self) -- Save file_id to redis to prevent downloading the same file over and over when forwarding redis:sadd('telegram:file_id', file_id) - return + return msg end function media_download:action(msg) diff --git a/otouto/plugins/stats.lua b/otouto/plugins/stats.lua index 12503a7..45ed444 100644 --- a/otouto/plugins/stats.lua +++ b/otouto/plugins/stats.lua @@ -103,7 +103,7 @@ function stats:pre_process(msg, self) -- Total user msgs local hash = 'msgs:'..msg.from.id..':'..msg.chat.id redis:incr(hash) - return + return msg end function stats:action(msg, config, matches) diff --git a/otouto/utilities.lua b/otouto/utilities.lua index ea15b8a..98ae417 100644 --- a/otouto/utilities.lua +++ b/otouto/utilities.lua @@ -586,8 +586,7 @@ utilities.char = { arabic = '[\216-\219][\128-\191]', rtl_override = '‮', rtl_mark = '‏', - em_dash = '—', - utf_8 = '([%z\1-\127\194-\244][\128-\191]*)', + em_dash = '—' } -- Returns a table with matches or nil @@ -602,6 +601,15 @@ function match_pattern(pattern, text) -- nil end +function is_sudo(msg, config) + local var = false + -- Check if user id is sudoer + if config.admin == msg.from.id then + var = true + end + return var +end + function post_petition(url, arguments, headers) local url, h = string.gsub(url, "http://", "") local url, hs = string.gsub(url, "https://", "")