diff --git a/.gitignore b/.gitignore index 4fd526d..86b10b3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ plugins/mokubot* plugins/qtbot* plugins/mjolnir* plugins/antisquigbot* +profile-pictures *.db lua-tg drua-tg diff --git a/bindings.lua b/bindings.lua index 533cbc1..704af41 100755 --- a/bindings.lua +++ b/bindings.lua @@ -12,6 +12,8 @@ function bindings.sendRequest(url) local dat, res = HTTPS.request(url) + if not dat then return false, res end + local tab = JSON.decode(dat) if not tab.ok then diff --git a/plugins/about.lua b/plugins/about.lua index 0e9667a..6feaca4 100755 --- a/plugins/about.lua +++ b/plugins/about.lua @@ -18,13 +18,10 @@ function about:action(msg) local message = self.config.about_text .. '\nBased on @otouto v'..bot.version..' by topkecleon.' - if msg.new_chat_participant and msg.new_chat_participant.id == self.info.id then - bindings.sendMessage(self, msg.chat.id, message, true) - return - elseif msg.text_lower:match('^/about[@'..self.info.username..']*') then - bindings.sendMessage(self, msg.chat.id, message, true) - return - elseif msg.text_lower:match('^/start') then + if (msg.new_chat_participant and msg.new_chat_participant.id == self.info.id) + or msg.text_lower:match('^/about') + or msg.text_lower:match('^/about@'..self.info.username:lower()) + or msg.text_lower:match('^/start') then bindings.sendMessage(self, msg.chat.id, message, true) return end diff --git a/plugins/administration.lua b/plugins/administration.lua index 3c2b232..d6f551e 100644 --- a/plugins/administration.lua +++ b/plugins/administration.lua @@ -1,6 +1,6 @@ --[[ administration.lua - Version 1.8.1 + Version 1.8.2 Part of the otouto project. © 2016 topkecleon GNU General Public License, version 2 @@ -23,6 +23,9 @@ 1.8.1 - /rule will return that numbered rule, if it exists. + 1.8.2 - Will now attempt to unban users kicked from supergroups. Other small + changes. + ]]-- local JSON = require('dkjson') @@ -257,6 +260,9 @@ function administration.init_command(self_) return true end drua.kick_user(msg.chat.id, msg.from.id) + if msg.chat.type == 'supergroup' then + bindings.unbanChatMember(self, msg.chat.id, msg.from.id) + end local output = administration.flags[2].kicked:gsub('GROUPNAME', msg.chat.title) bindings.sendMessage(self, msg.from.id, output) end @@ -285,6 +291,9 @@ function administration.init_command(self_) if group.flags[3] == true then if msg.from.name:match('[\216-\219][\128-\191]') or msg.from.name:match('‮') or msg.from.name:match('‏') then drua.kick_user(msg.chat.id, msg.from.id) + if msg.chat.type == 'supergroup' then + bindings.unbanChatMember(self, msg.chat.id, msg.from.id) + end local output = administration.flags[3].kicked:gsub('GROUPNAME', msg.chat.title) bindings.sendMessage(self, msg.from.id, output) return @@ -323,6 +332,9 @@ function administration.init_command(self_) end if self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] > 99 then drua.kick_user(msg.chat.id, msg.from.id) + if msg.chat.type == 'supergroup' then + bindings.unbanChatMember(self, msg.chat.id, msg.from.id) + end local output = administration.flags[5].kicked:gsub('GROUPNAME', msg.chat.title) bindings.sendMessage(self, msg.from.id, output) self.admin_temp.flood[msg.chat.id_str][msg.from.id_str] = nil @@ -347,6 +359,9 @@ function administration.init_command(self_) if group.flags[3] == true then if msg.new_chat_participant.name:match('[\216-\219][\128-\191]') or msg.new_chat_participant.name:match('‮') or msg.new_chat_participant.name:match('‏') then drua.kick_user(msg.chat.id, msg.new_chat_participant.id) + if msg.chat.type == 'supergroup' then + bindings.unbanChatMember(self, msg.chat.id, msg.from.id) + end local output = administration.flags[3].kicked:gsub('GROUPNAME', msg.chat.title) bindings.sendMessage(self, msg.new_chat_participant.id, output) return @@ -402,14 +417,15 @@ function administration.init_command(self_) group.photo = nil end return - end -- Last active time for group listing. - for i,v in pairs(self.database.administration.activity) do - if v == msg.chat.id_str then - table.remove(self.database.administration.activity, i) - table.insert(self.database.administration.activity, 1, msg.chat.id_str) + if msg.text:len() > 0 then + for i,v in pairs(self.database.administration.activity) do + if v == msg.chat.id_str then + table.remove(self.database.administration.activity, i) + table.insert(self.database.administration.activity, 1, msg.chat.id_str) + end end end @@ -431,7 +447,7 @@ function administration.init_command(self_) local group = self.database.administration.groups[v] if not group.flags[1] then -- no unlisted groups if group.link then - output = output .. '• [' .. group.name .. '](' .. group.link .. ')\n' + output = output .. '• [' .. utilities.md_escape(group.name) .. '](' .. group.link .. ')\n' else output = output .. '• ' .. group.name .. '\n' end @@ -595,6 +611,9 @@ function administration.init_command(self_) return end drua.kick_user(msg.chat.id, target.id) + if msg.chat.type == 'supergroup' then + bindings.unbanChatMember(self, msg.chat.id, target.id) + end bindings.sendMessage(self, msg.chat.id, target.name .. ' has been kicked.') end }, @@ -1016,21 +1035,28 @@ function administration.init_command(self_) command = 'gremove \\[chat]', privilege = 5, - interior = true, + interior = false, action = function(self, msg) local input = utilities.input(msg.text) or msg.chat.id_str + local output if self.database.administration.groups[input] then + local chat_name = self.administration.groups[input].name self.database.administration.groups[input] = nil for i,v in ipairs(self.database.administration.activity) do if v == input then table.remove(self.database.administration.activity, i) end end - bindings.sendReply(self, msg, 'I am no longer administrating that group.') + output = 'I am no longer administrating _' .. utilities.md_escape(chat_name) .. '_.' else - bindings.sendReply(self, msg, 'I do not administrate that group.') + if input == msg.chat.id_str then + output = 'I do not administrate this group.' + else + output = 'I do not administrate that group.' + end end + bindings.sendMessage(self, msg.chat.id, output, true, nil, true) end }, diff --git a/plugins/control.lua b/plugins/control.lua index a0dd221..a8f372b 100644 --- a/plugins/control.lua +++ b/plugins/control.lua @@ -14,7 +14,7 @@ function control:action(msg) return end - if msg.date < os.time() then return end + if msg.date < os.time() - 1 then return end if msg.text:match('^'..utilities.INVOCATION_PATTERN..'reload') then bot.init(self) diff --git a/plugins/remind.lua b/plugins/remind.lua new file mode 100644 index 0000000..adb00e4 --- /dev/null +++ b/plugins/remind.lua @@ -0,0 +1,98 @@ +local remind = {} + +local bindings = require('bindings') +local utilities = require('utilities') + +remind.command = 'remind ' +remind.doc = [[``` + /remind + Repeats a message after a duration of time, in minutes. + ```]] + +function remind:init() + self.database.reminders = self.database.reminders or {} + + remind.triggers = utilities.triggers(self.info.username):t('remind', true).table +end + +function remind:action(msg) + -- Ensure there are arguments. If not, send doc. + local input = msg.text:input() + if not input then + bindings.sendMessage(self, msg.chat.id, remind.doc, true, msg.message_id, true) + return + end + -- Ensure first arg is a number. If not, send doc. + local duration = utilities.get_word(input, 1) + if not tonumber(duration) then + bindings.sendMessage(self, msg.chat.id, remind.doc, true, msg.message_id, true) + return + end + -- Duration must be between one minute and one year (approximately). + duration = tonumber(duration) + if duration < 1 then + duration = 1 + elseif duration > 526000 then + duration = 526000 + end + -- Ensure there is a second arg. + local message = input:input() + if not message then + bindings.sendMessage(self, msg.chat.id, remind.doc, true, msg.message_id, true) + return + end + -- Make a database entry for the group/user if one does not exist. + self.database.reminders[msg.chat.id_str] = self.database.reminders[msg.chat.id_str] or {} + -- Limit group reminders to 10 and private reminders to 50. + if msg.chat.type ~= 'private' and utilities.table_size(self.database.reminders[msg.chat.id_str]) > 9 then + bindings.sendReply(self, msg, 'Sorry, this group already has ten reminders.') + return + elseif msg.chat.type == 'private' and utilities.table_size(self.database.reminders[msg.chat.id_str]) > 49 then + bindings.sendReply(msg, 'Sorry, you already have fifty reminders.') + return + end + -- Put together the reminder with the expiration, message, and message to reply to. + local reminder = { + time = os.time() + duration * 60, + message = message + } + table.insert(self.database.reminders[msg.chat.id_str], reminder) + local output = 'I will remind you in ' .. duration + if duration == 1 then + output = output .. ' minute!' + else + output = output .. ' minutes!' + end + bindings.sendReply(self, msg, output) +end + +function remind:cron() + local time = os.time() + -- Iterate over the group entries in the reminders database. + for chat_id, group in pairs(self.database.reminders) do + local new_group = {} + -- Iterate over each reminder. + for _, reminder in ipairs(group) do + -- If the reminder is past-due, send it and nullify it. + -- Otherwise, add it to the replacement table. + if time > reminder.time then + local output = 'Reminder:\n"' .. reminder.message .. '"' + local res = bindings.sendMessage(self, chat_id, output, true) + -- If the message fails to send, save it for later. + if not res then + table.insert(new_group, reminder) + end + else + table.insert(new_group, reminder) + end + end + -- Nullify the original table and replace it with the new one. + self.database.reminders[chat_id] = new_group + -- Nullify the table if it is empty. + if #new_group == 0 then + self.database.reminders[chat_id] = nil + end + end +end + +return remind diff --git a/utilities.lua b/utilities.lua index 1aa7bd6..cead6c8 100755 --- a/utilities.lua +++ b/utilities.lua @@ -261,19 +261,14 @@ function utilities.markdown_escape(text) text = text:gsub('_', '\\_') text = text:gsub('%[', '\\[') + text = text:gsub('%]', '\\]') text = text:gsub('%*', '\\*') text = text:gsub('`', '\\`') return text end -function utilities.md_escape(s) - s = s:gsub('_', '\\_') - s = s:gsub('%[', '\\[') - s = s:gsub('%*', '\\*') - s = s:gsub('`', '\\`') - return s -end +utilities.md_escape = utilities.markdown_escape utilities.INVOCATION_PATTERN = '/'