Upstream
This commit is contained in:
commit
72262be90c
@ -6,4 +6,5 @@ insert_final_newline = true
|
|||||||
|
|
||||||
[*.lua]
|
[*.lua]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
indent_style = tab
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
@ -187,6 +187,4 @@ Das ist die Datenbank-Struktur:
|
|||||||
|
|
||||||
`database.userdata` speichert Daten von verschiedenen Plugins, hierzu wird aber für Brawlbot-Plugins Redis verwendet.
|
`database.userdata` speichert Daten von verschiedenen Plugins, hierzu wird aber für Brawlbot-Plugins Redis verwendet.
|
||||||
|
|
||||||
`database.version` speichert die Bot-Version.
|
`database.version` speichert die Bot-Version.
|
||||||
|
|
||||||
* * *
|
|
@ -35,44 +35,20 @@ Sende /hilfe, um zu starten
|
|||||||
syntax = 'Invalide Syntax.',
|
syntax = 'Invalide Syntax.',
|
||||||
chatter_connection = 'Ich möchte gerade nicht reden',
|
chatter_connection = 'Ich möchte gerade nicht reden',
|
||||||
chatter_response = 'Ich weiß nicht, was ich darauf antworten soll.'
|
chatter_response = 'Ich weiß nicht, was ich darauf antworten soll.'
|
||||||
}
|
},
|
||||||
|
|
||||||
|
remind = {
|
||||||
|
persist = true,
|
||||||
|
max_length = 1000,
|
||||||
|
max_duration = 526000,
|
||||||
|
max_reminders_group = 10,
|
||||||
|
max_reminders_private = 50
|
||||||
|
},
|
||||||
|
|
||||||
plugins = { -- To enable a plugin, add its name to the list.
|
chatter = {
|
||||||
'control',
|
cleverbot_api = 'https://brawlbot.tk/apis/chatter-bot-api/cleverbot.php?text=',
|
||||||
'blacklist',
|
connection = 'I don\'t feel like talking right now.',
|
||||||
'about',
|
response = 'I don\'t know what to say to that.'
|
||||||
'ping',
|
}
|
||||||
'whoami',
|
|
||||||
'nick',
|
|
||||||
'echo',
|
|
||||||
'imgblacklist',
|
|
||||||
'gImages',
|
|
||||||
'gSearch',
|
|
||||||
'gMaps',
|
|
||||||
'wikipedia',
|
|
||||||
'hackernews',
|
|
||||||
'imdb',
|
|
||||||
'calc',
|
|
||||||
'urbandictionary',
|
|
||||||
'time',
|
|
||||||
'dice',
|
|
||||||
'reddit',
|
|
||||||
'xkcd',
|
|
||||||
'slap',
|
|
||||||
'commit',
|
|
||||||
'pun',
|
|
||||||
'currency',
|
|
||||||
'shout',
|
|
||||||
'set',
|
|
||||||
'get',
|
|
||||||
'patterns',
|
|
||||||
'9gag',
|
|
||||||
'shell',
|
|
||||||
'adfly',
|
|
||||||
'twitter',
|
|
||||||
-- Put new plugins above this line.
|
|
||||||
'help',
|
|
||||||
'greetings'
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
lua main.lua
|
lua main.lua
|
||||||
echo 'otouto has stopped. ^C to exit.'
|
echo 'otouto has stopped. ^C to exit.'
|
||||||
sleep 5s
|
sleep 5s
|
||||||
done
|
done
|
||||||
|
@ -48,7 +48,7 @@ function bindings:request(method, parameters, file)
|
|||||||
end
|
end
|
||||||
local response = {}
|
local response = {}
|
||||||
local body, boundary = MP_ENCODE(parameters)
|
local body, boundary = MP_ENCODE(parameters)
|
||||||
local success = HTTPS.request{
|
local success, code = HTTPS.request{
|
||||||
url = self.BASE_URL .. method,
|
url = self.BASE_URL .. method,
|
||||||
method = 'POST',
|
method = 'POST',
|
||||||
headers = {
|
headers = {
|
||||||
@ -60,7 +60,7 @@ function bindings:request(method, parameters, file)
|
|||||||
}
|
}
|
||||||
local data = table.concat(response)
|
local data = table.concat(response)
|
||||||
if not success then
|
if not success then
|
||||||
print(method .. ': Connection error.')
|
print(method .. ': Connection error. [' .. code .. ']')
|
||||||
return false, false
|
return false, false
|
||||||
else
|
else
|
||||||
local result = JSON.decode(data)
|
local result = JSON.decode(data)
|
||||||
|
@ -3,13 +3,13 @@ local bot = {}
|
|||||||
bindings = require('otouto.bindings')
|
bindings = require('otouto.bindings')
|
||||||
utilities = require('otouto.utilities')
|
utilities = require('otouto.utilities')
|
||||||
|
|
||||||
bot.version = '2.2.6'
|
bot.version = '2.2.6.1'
|
||||||
|
|
||||||
function bot:init(config) -- The function run when the bot is started or reloaded.
|
function bot:init(config) -- The function run when the bot is started or reloaded.
|
||||||
cred_data = load_cred()
|
cred_data = load_cred()
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
config.bot_api_key and config.bot_api_key ~= '',
|
config.bot_api_key,
|
||||||
'You did not set your bot token in the config!'
|
'You did not set your bot token in the config!'
|
||||||
)
|
)
|
||||||
self.BASE_URL = 'https://api.telegram.org/bot' .. config.bot_api_key .. '/'
|
self.BASE_URL = 'https://api.telegram.org/bot' .. config.bot_api_key .. '/'
|
||||||
@ -28,19 +28,22 @@ function bot:init(config) -- The function run when the bot is started or reloade
|
|||||||
|
|
||||||
self.plugins = {} -- Load plugins.
|
self.plugins = {} -- Load plugins.
|
||||||
enabled_plugins = load_plugins()
|
enabled_plugins = load_plugins()
|
||||||
|
t = {}
|
||||||
for k,v in pairs(enabled_plugins) do
|
for k,v in pairs(enabled_plugins) do
|
||||||
local p = require('otouto.plugins.'..v)
|
local p = require('otouto.plugins.'..v)
|
||||||
-- print('loading plugin',v)
|
-- print('loading plugin',v)
|
||||||
self.plugins[k] = p
|
self.plugins[k] = p
|
||||||
self.plugins[k].name = v
|
self.plugins[k].name = v
|
||||||
if p.init then p.init(self, config) end
|
if p.init then p.init(self, config) end
|
||||||
|
if not p.triggers then p.triggers = t end
|
||||||
end
|
end
|
||||||
|
|
||||||
print('Bot started successfully as:\n@' .. self.info.username .. ', AKA ' .. self.info.first_name ..' ('..self.info.id..')')
|
print('Bot started successfully as:\n@' .. self.info.username .. ', AKA ' .. self.info.first_name ..' ('..self.info.id..')')
|
||||||
|
|
||||||
self.last_update = self.last_update or 0 -- Set loop variables: Update offset,
|
-- Set loop variables
|
||||||
self.last_cron = self.last_cron or os.date('%M') -- the time of the last cron job,
|
self.last_update = self.last_update or 0 -- Update offset.
|
||||||
self.last_database_save = self.last_database_save or os.date('%H') -- the time of the last database save,
|
self.last_cron = self.last_cron or os.date('%M') -- Last cron job.
|
||||||
|
self.last_database_save = self.last_database_save or os.date('%H') -- Last db save.
|
||||||
self.is_started = true -- and whether or not the bot should be running.
|
self.is_started = true -- and whether or not the bot should be running.
|
||||||
|
|
||||||
end
|
end
|
||||||
@ -179,13 +182,15 @@ function bot:process_inline_query(inline_query, config) -- When an inline query
|
|||||||
utilities.answer_inline_query(self, inline_query, nil, 0, true)
|
utilities.answer_inline_query(self, inline_query, nil, 0, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- main
|
||||||
function bot:run(config)
|
function bot:run(config)
|
||||||
bot.init(self, config) -- Actually start the script.
|
bot.init(self, config)
|
||||||
|
while self.is_started do
|
||||||
while self.is_started do -- Start a loop while the bot should be running.
|
-- Update loop
|
||||||
local res = bindings.getUpdates(self, { timeout=20, offset = self.last_update+1 } )
|
local res = bindings.getUpdates(self, { timeout = 20, offset = self.last_update + 1 } )
|
||||||
if res then
|
if res then
|
||||||
for n=1, #res.result do -- Go through every new message.
|
-- Iterate over every new message.
|
||||||
|
for n=1, #res.result do
|
||||||
local v = res.result[n]
|
local v = res.result[n]
|
||||||
self.last_update = v.update_id
|
self.last_update = v.update_id
|
||||||
if v.inline_query then
|
if v.inline_query then
|
||||||
@ -200,7 +205,8 @@ function bot:run(config)
|
|||||||
print('Connection error while fetching updates.')
|
print('Connection error while fetching updates.')
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.last_cron ~= os.date('%M') then -- Run cron jobs every minute.
|
-- Run cron jobs every minute.
|
||||||
|
if self.last_cron ~= os.date('%M') then
|
||||||
self.last_cron = os.date('%M')
|
self.last_cron = os.date('%M')
|
||||||
utilities.save_data(self.info.username..'.db', self.database) -- Save the database.
|
utilities.save_data(self.info.username..'.db', self.database) -- Save the database.
|
||||||
for n=1, #self.plugins do
|
for n=1, #self.plugins do
|
||||||
@ -256,7 +262,7 @@ function match_inline_plugins(self, inline_query, config, plugin)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function match_plugins(self, msg, config, plugin)
|
function match_plugins(self, msg, config, plugin)
|
||||||
local match_table = plugin.triggers or {}
|
local match_table = plugin.triggers
|
||||||
for n=1, #match_table do
|
for n=1, #match_table do
|
||||||
local trigger = plugin.triggers[n]
|
local trigger = plugin.triggers[n]
|
||||||
if string.match(msg.text_lower, trigger) then
|
if string.match(msg.text_lower, trigger) then
|
||||||
|
@ -5,33 +5,16 @@ local bot = require('otouto.bot')
|
|||||||
about.command = 'about'
|
about.command = 'about'
|
||||||
about.doc = '`Sendet Informationen über den Bot.`'
|
about.doc = '`Sendet Informationen über den Bot.`'
|
||||||
|
|
||||||
about.triggers = {
|
function about:init(config)
|
||||||
|
about.text = config.about_text..'\n[Brawlbot](https://github.com/Brawl345/Brawlbot-v2) v'..bot.version..', basierend auf [Otouto](http://github.com/topkecleon/otouto) von topkecleon.'
|
||||||
|
about.triggers = {
|
||||||
'/about',
|
'/about',
|
||||||
'/start'
|
'/start'
|
||||||
}
|
}
|
||||||
|
end
|
||||||
|
|
||||||
function about:action(msg, config)
|
function about:action(msg, config)
|
||||||
|
utilities.send_message(self, msg.chat.id, about.text, true, nil, true)
|
||||||
-- Filthy hack, but here is where we'll stop forwarded messages from hitting
|
|
||||||
-- other plugins.
|
|
||||||
-- disabled to restore old behaviour
|
|
||||||
-- if msg.forward_from then return end
|
|
||||||
|
|
||||||
local output = config.about_text .. '\nBrawlbot v'..bot.version..', basierend auf Otouto von topkecleon.'
|
|
||||||
|
|
||||||
if
|
|
||||||
(msg.new_chat_member and msg.new_chat_member.id == self.info.id)
|
|
||||||
or msg.text_lower:match('^'..config.cmd_pat..'about$')
|
|
||||||
or msg.text_lower:match('^'..config.cmd_pat..'about@'..self.info.username:lower()..'$')
|
|
||||||
or msg.text_lower:match('^'..config.cmd_pat..'start$')
|
|
||||||
or msg.text_lower:match('^'..config.cmd_pat..'start@'..self.info.username:lower()..'$')
|
|
||||||
then
|
|
||||||
utilities.send_message(self, msg.chat.id, output, true, nil, true)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
return true
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return about
|
return about
|
||||||
|
@ -5,21 +5,27 @@ function cleverbot:init(config)
|
|||||||
"^/cbot (.+)$",
|
"^/cbot (.+)$",
|
||||||
"^[Bb]rawlbot, (.+)$",
|
"^[Bb]rawlbot, (.+)$",
|
||||||
}
|
}
|
||||||
|
cleverbot.url = config.chatter.cleverbot_api
|
||||||
cleverbot.doc = [[*
|
|
||||||
]]..config.cmd_pat..[[cbot* _<Text>_*: Befragt den Cleverbot]]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
cleverbot.command = 'cbot <Text>'
|
cleverbot.command = 'cbot <Text>'
|
||||||
|
|
||||||
function cleverbot:action(msg, config)
|
function cleverbot:action(msg, config, matches)
|
||||||
local text = msg.text
|
|
||||||
local url = "https://brawlbot.tk/apis/chatter-bot-api/cleverbot.php?text="..URL.escape(text)
|
|
||||||
utilities.send_typing(self, msg.chat.id, 'typing')
|
utilities.send_typing(self, msg.chat.id, 'typing')
|
||||||
local query = https.request(url)
|
local text = matches[1]
|
||||||
if query == nil then utilities.send_reply(self, msg, 'Ein Fehler ist aufgetreten :(') return end
|
local query, code = https.request(cleverbot.url..URL.escape(text))
|
||||||
local decode = json.decode(query)
|
if code ~= 200 then
|
||||||
local answer = string.gsub(decode.clever, "Ä", "Ä")
|
utilities.send_reply(self, msg, 'Ich möchte jetzt nicht reden...')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local data = json.decode(query)
|
||||||
|
if not data.clever then
|
||||||
|
utilities.send_reply(self, msg, 'Ich möchte jetzt nicht reden...')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local answer = string.gsub(data.clever, "Ä", "Ä")
|
||||||
local answer = string.gsub(answer, "ä", "ä")
|
local answer = string.gsub(answer, "ä", "ä")
|
||||||
local answer = string.gsub(answer, "Ö", "Ö")
|
local answer = string.gsub(answer, "Ö", "Ö")
|
||||||
local answer = string.gsub(answer, "ö", "ö")
|
local answer = string.gsub(answer, "ö", "ö")
|
||||||
@ -29,4 +35,4 @@ function cleverbot:action(msg, config)
|
|||||||
utilities.send_reply(self, msg, answer)
|
utilities.send_reply(self, msg, answer)
|
||||||
end
|
end
|
||||||
|
|
||||||
return cleverbot
|
return cleverbot
|
@ -26,7 +26,7 @@ function echo:inline_callback(inline_query, config, matches)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function echo:action(msg)
|
function echo:action(msg)
|
||||||
local input = utilities.input(msg.text)
|
local input = utilities.input_from_msg(msg)
|
||||||
if not input then
|
if not input then
|
||||||
utilities.send_message(self, msg.chat.id, echo.doc, true, msg.message_id, true)
|
utilities.send_message(self, msg.chat.id, echo.doc, true, msg.message_id, true)
|
||||||
else
|
else
|
||||||
|
@ -30,14 +30,10 @@ function gMaps:inline_callback(inline_query, config, matches)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function gMaps:action(msg, config)
|
function gMaps:action(msg, config)
|
||||||
local input = utilities.input(msg.text)
|
local input = utilities.input_from_msg(msg)
|
||||||
if not input then
|
if not input then
|
||||||
if msg.reply_to_message and msg.reply_to_message.text then
|
utilities.send_reply(self, msg, gMaps.doc, true)
|
||||||
input = msg.reply_to_message.text
|
return
|
||||||
else
|
|
||||||
utilities.send_message(self, msg.chat.id, gMaps.doc, true, msg.message_id, true)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
utilities.send_typing(self, msg.chat.id, 'find_location')
|
utilities.send_typing(self, msg.chat.id, 'find_location')
|
||||||
|
@ -51,14 +51,10 @@ function gSearch:stringlinks(results, stats)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function gSearch:action(msg, config)
|
function gSearch:action(msg, config)
|
||||||
local input = utilities.input(msg.text)
|
local input = utilities.input_from_msg(msg)
|
||||||
if not input then
|
if not input then
|
||||||
if msg.reply_to_message and msg.reply_to_message.text then
|
utilities.send_reply(self, msg, gImages.doc, true)
|
||||||
input = msg.reply_to_message.text
|
return
|
||||||
else
|
|
||||||
utilities.send_message(self, msg.chat.id, gSearch.doc, true, msg.message_id, true)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local results, stats = gSearch:googlethat(input, onfig)
|
local results, stats = gSearch:googlethat(input, onfig)
|
||||||
|
@ -67,14 +67,10 @@ function imdb:inline_callback(inline_query, config, matches)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function imdb:action(msg, config)
|
function imdb:action(msg, config)
|
||||||
local input = utilities.input(msg.text)
|
local input = utilities.input_from_msg(msg)
|
||||||
if not input then
|
if not input then
|
||||||
if msg.reply_to_message and msg.reply_to_message.text then
|
utilities.send_reply(self, msg, imdb.doc, true)
|
||||||
input = msg.reply_to_message.text
|
return
|
||||||
else
|
|
||||||
utilities.send_message(self, msg.chat.id, imdb.doc, true, msg.message_id, true)
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local url = BASE_URL..'/?t='..URL.escape(input)
|
local url = BASE_URL..'/?t='..URL.escape(input)
|
||||||
|
@ -2,11 +2,22 @@ local luarun = {}
|
|||||||
|
|
||||||
function luarun:init(config)
|
function luarun:init(config)
|
||||||
luarun.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('lua', true):t('return', true).table
|
luarun.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('lua', true):t('return', true).table
|
||||||
|
if config.luarun_serpent then
|
||||||
|
serpent = require('serpent')
|
||||||
|
luarun.serialize = function(t)
|
||||||
|
return serpent.block(t, {comment=false})
|
||||||
|
end
|
||||||
|
else
|
||||||
|
JSON = require('dkjson')
|
||||||
|
luarun.serialize = function(t)
|
||||||
|
return JSON.encode(t, {indent=true})
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function luarun:action(msg, config)
|
function luarun:action(msg, config)
|
||||||
|
|
||||||
if msg.from.id ~= config.admin then
|
if not is_sudo(msg, config) then
|
||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -24,17 +35,18 @@ function luarun:action(msg, config)
|
|||||||
local bot = require('otouto.bot')
|
local bot = require('otouto.bot')
|
||||||
local bindings = require('otouto.bindings')
|
local bindings = require('otouto.bindings')
|
||||||
local utilities = require('otouto.utilities')
|
local utilities = require('otouto.utilities')
|
||||||
local json = require('dkjson')
|
local drua = require('otouto.drua-tg')
|
||||||
|
local JSON = require('dkjson')
|
||||||
local URL = require('socket.url')
|
local URL = require('socket.url')
|
||||||
local http = require('socket.http')
|
local HTTP = require('socket.http')
|
||||||
local https = require('ssl.https')
|
local HTTPS = require('ssl.https')
|
||||||
return function (self, msg, config) ]] .. input .. [[ end
|
return function (self, msg, config) ]] .. input .. [[ end
|
||||||
]] )()(self, msg, config)
|
]] )()(self, msg, config)
|
||||||
if output == nil then
|
if output == nil then
|
||||||
output = 'Done!'
|
output = 'Done!'
|
||||||
else
|
else
|
||||||
if type(output) == 'table' then
|
if type(output) == 'table' then
|
||||||
local s = json.encode(output, {indent=true})
|
local s = luarun.serialize(output)
|
||||||
if URL.escape(s):len() < 4000 then
|
if URL.escape(s):len() < 4000 then
|
||||||
output = s
|
output = s
|
||||||
end
|
end
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
local patterns = {}
|
local patterns = {}
|
||||||
|
|
||||||
patterns.triggers = {
|
function patterns:init(config)
|
||||||
'^/?s/.-/.-$'
|
patterns.command = 's/<Pattern>/<Ersetzung>'
|
||||||
}
|
patterns.triggers = {
|
||||||
|
config.cmd_pat .. '?s/.-/.-$'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
function patterns:action(msg)
|
function patterns:action(msg)
|
||||||
if not msg.reply_to_message then return true end
|
if not msg.reply_to_message then return true end
|
||||||
|
@ -11,34 +11,31 @@ Returns a full-message, "unlinked" preview.
|
|||||||
end
|
end
|
||||||
|
|
||||||
function preview:action(msg)
|
function preview:action(msg)
|
||||||
|
local input = utilities.input_from_msg(msg)
|
||||||
|
if not input then
|
||||||
|
utilities.send_reply(self, msg, preview.doc, true)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local input = utilities.input(msg.text)
|
input = utilities.get_word(input, 1)
|
||||||
|
if not input:match('^https?://.+') then
|
||||||
|
input = 'http://' .. input
|
||||||
|
end
|
||||||
|
|
||||||
if not input then
|
local res = http.request(input)
|
||||||
utilities.send_message(self, msg.chat.id, preview.doc, true, nil, true)
|
if not res then
|
||||||
return
|
utilities.send_reply(self, msg, 'Bitte gebe einen validen Link an.')
|
||||||
end
|
return
|
||||||
|
end
|
||||||
|
|
||||||
input = utilities.get_word(input, 1)
|
if res:len() == 0 then
|
||||||
if not input:match('^https?://.+') then
|
utilities.send_reply(self, msg, 'Sorry, dieser Link lässt uns keine Vorschau erstellen.')
|
||||||
input = 'http://' .. input
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local res = http.request(input)
|
|
||||||
if not res then
|
|
||||||
utilities.send_reply(self, msg, 'Please provide a valid link.')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
if res:len() == 0 then
|
|
||||||
utilities.send_reply(self, msg, 'Sorry, the link you provided is not letting us make a preview.')
|
|
||||||
return
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Invisible zero-width, non-joiner.
|
|
||||||
local output = '[](' .. input .. ')'
|
|
||||||
utilities.send_message(self, msg.chat.id, output, false, nil, true)
|
|
||||||
|
|
||||||
|
-- Invisible zero-width, non-joiner.
|
||||||
|
local output = '<a href="' .. input .. '">' .. utilities.char.zwnj .. '</a>'
|
||||||
|
utilities.send_message(self, msg.chat.id, output, false, nil, 'HTML')
|
||||||
end
|
end
|
||||||
|
|
||||||
return preview
|
return preview
|
@ -7,88 +7,79 @@ function remind:init(config)
|
|||||||
|
|
||||||
remind.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('remind', true).table
|
remind.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('remind', true).table
|
||||||
remind.doc = [[*
|
remind.doc = [[*
|
||||||
]]..config.cmd_pat..[[remind* _<Länge>_ _<Nachricht>_: Erinnert dich in X Minuten an die Nachricht]]
|
]]..config.cmd_pat..[[remind* _<Länge>_ _<Nachricht>_
|
||||||
|
Erinnert dich in der angegeben Länge in Minuten an eine Nachricht.
|
||||||
|
Die maximale Länge einer Erinnerung beträgt %s Buchstaben, die maximale Zeit beträgt %s Minuten, die maximale Anzahl an Erinnerung für eine Gruppe ist %s und für private Chats %s.]]
|
||||||
|
remind.doc = remind.doc:format(config.remind.max_length, config.remind.max_duration, config.remind.max_reminders_group, config.remind.max_reminders_private)
|
||||||
end
|
end
|
||||||
|
|
||||||
function remind:action(msg)
|
function remind:action(msg, config)
|
||||||
-- Ensure there are arguments. If not, send doc.
|
|
||||||
local input = utilities.input(msg.text)
|
local input = utilities.input(msg.text)
|
||||||
if not input then
|
if not input then
|
||||||
utilities.send_message(self, msg.chat.id, remind.doc, true, msg.message_id, true)
|
utilities.send_reply(self, msg, remind.doc, true)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Ensure first arg is a number. If not, send doc.
|
local duration = tonumber(utilities.get_word(input, 1))
|
||||||
local duration = utilities.get_word(input, 1)
|
if not duration then
|
||||||
if not tonumber(duration) then
|
utilities.send_reply(self, msg, remind.doc, true)
|
||||||
utilities.send_message(self, msg.chat.id, remind.doc, true, msg.message_id, true)
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Duration must be between one minute and one day (approximately).
|
|
||||||
duration = tonumber(duration)
|
|
||||||
if duration < 1 then
|
if duration < 1 then
|
||||||
duration = 1
|
duration = 1
|
||||||
elseif duration > 1440 then
|
elseif duration > config.remind.max_duration then
|
||||||
duration = 1440
|
duration = config.remind.max_duration
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Ensure there is a second arg.
|
|
||||||
local message = utilities.input(input)
|
local message = utilities.input(input)
|
||||||
if not message then
|
if not message then
|
||||||
utilities.send_message(self, msg.chat.id, remind.doc, true, msg.message_id, true)
|
utilities.send_reply(self, msg, remind.doc, true)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
if #message > config.remind.max_length then
|
||||||
|
utilities.send_reply(self, msg, 'Die maximale Länge einer Erinnerung ist ' .. config.remind.max_length .. '.')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Make a database entry for the group/user if one does not exist.
|
local chat_id_str = tostring(msg.chat.id)
|
||||||
self.database.reminders[msg.chat.id_str] = self.database.reminders[msg.chat.id_str] or {}
|
local output
|
||||||
-- Limit group reminders to 10 and private reminders to 50.
|
self.database.reminders[chat_id_str] = self.database.reminders[chat_id_str] or {}
|
||||||
if msg.chat.type ~= 'private' and utilities.table_size(self.database.reminders[msg.chat.id_str]) > 9 then
|
if msg.chat.type == 'private' and utilities.table_size(self.database.reminders[chat_id_str]) >= config.remind.max_reminders_private then
|
||||||
utilities.send_reply(self, msg, 'Diese Gruppe hat schon zehn Erinnerungen!')
|
output = 'Sorry, du kannst keine Erinnerungen mehr hinzufügen.'
|
||||||
return
|
elseif msg.chat.type ~= 'private' and utilities.table_size(self.database.reminders[chat_id_str]) >= config.remind.max_reminders_group then
|
||||||
elseif msg.chat.type == 'private' and utilities.table_size(self.database.reminders[msg.chat.id_str]) > 49 then
|
output = 'Sorry, diese Gruppe kann keine Erinnerungen mehr hinzufügen.'
|
||||||
utilities.send_reply(msg, 'Du hast schon 50 Erinnerungen!')
|
else
|
||||||
return
|
-- Put together the reminder with the expiration, message, and message to reply to.
|
||||||
|
local timestamp = os.time() + duration * 60
|
||||||
|
local reminder = {
|
||||||
|
time = timestamp,
|
||||||
|
message = message
|
||||||
|
}
|
||||||
|
table.insert(self.database.reminders[chat_id_str], reminder)
|
||||||
|
local human_readable_time = convert_timestamp(timestamp, '%H:%M:%S')
|
||||||
|
output = 'Ich werde dich um *'..human_readable_time..' Uhr* erinnern.'
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Put together the reminder with the expiration, message, and message to reply to.
|
|
||||||
local timestamp = os.time() + duration * 60
|
|
||||||
local reminder = {
|
|
||||||
time = timestamp,
|
|
||||||
message = message
|
|
||||||
}
|
|
||||||
table.insert(self.database.reminders[msg.chat.id_str], reminder)
|
|
||||||
local human_readable_time = convert_timestamp(timestamp, '%H:%M:%S')
|
|
||||||
local output = 'Ich werde dich um *'..human_readable_time..' Uhr* erinnern.'
|
|
||||||
utilities.send_reply(self, msg, output, true)
|
utilities.send_reply(self, msg, output, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
function remind:cron()
|
function remind:cron(config)
|
||||||
local time = os.time()
|
local time = os.time()
|
||||||
-- Iterate over the group entries in the reminders database.
|
-- Iterate over the group entries in the reminders database.
|
||||||
for chat_id, group in pairs(self.database.reminders) do
|
for chat_id, group in pairs(self.database.reminders) do
|
||||||
local new_group = {}
|
|
||||||
-- Iterate over each reminder.
|
-- Iterate over each reminder.
|
||||||
for _, reminder in ipairs(group) do
|
for k, reminder in pairs(group) do
|
||||||
-- If the reminder is past-due, send it and nullify it.
|
-- If the reminder is past-due, send it and nullify it.
|
||||||
-- Otherwise, add it to the replacement table.
|
-- Otherwise, add it to the replacement table.
|
||||||
if time > reminder.time then
|
if time > reminder.time then
|
||||||
local output = '*ERINNERUNG:*\n"' .. utilities.md_escape(reminder.message) .. '"'
|
local output = '*ERINNERUNG:*\n"' .. utilities.md_escape(reminder.message) .. '"'
|
||||||
local res = utilities.send_message(self, chat_id, output, true, nil, true)
|
local res = utilities.send_message(self, chat_id, output, true, nil, true)
|
||||||
-- If the message fails to send, save it for later.
|
-- If the message fails to send, save it for later (if enabled in config).
|
||||||
if not res then
|
if res or not config.remind.persist then
|
||||||
table.insert(new_group, reminder)
|
group[k] = nil
|
||||||
end
|
end
|
||||||
else
|
|
||||||
table.insert(new_group, reminder)
|
|
||||||
end
|
end
|
||||||
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
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ function time:inline_callback(inline_query, config, matches)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function time:action(msg, config)
|
function time:action(msg, config)
|
||||||
local input = utilities.input(msg.text)
|
local input = utilities.input_from_msg(msg)
|
||||||
if not input then
|
if not input then
|
||||||
local output = os.date("%A, %d. %B %Y, *%H:%M:%S Uhr*")
|
local output = os.date("%A, %d. %B %Y, *%H:%M:%S Uhr*")
|
||||||
utilities.send_reply(self, msg, time:localize(output), true)
|
utilities.send_reply(self, msg, time:localize(output), true)
|
||||||
|
@ -22,52 +22,42 @@ https.timeout = 5
|
|||||||
-- For the sake of ease to new contributors and familiarity to old contributors,
|
-- For the sake of ease to new contributors and familiarity to old contributors,
|
||||||
-- we'll provide a couple of aliases to real bindings here.
|
-- we'll provide a couple of aliases to real bindings here.
|
||||||
function utilities:send_message(chat_id, text, disable_web_page_preview, reply_to_message_id, use_markdown, reply_markup)
|
function utilities:send_message(chat_id, text, disable_web_page_preview, reply_to_message_id, use_markdown, reply_markup)
|
||||||
if use_markdown == true then
|
local parse_mode
|
||||||
use_markdown = 'Markdown'
|
if type(use_markdown) == 'string' then
|
||||||
elseif not use_markdown then
|
parse_mode = use_markdown
|
||||||
use_markdown = nil
|
elseif use_markdown == true then
|
||||||
|
parse_mode = 'Markdown'
|
||||||
end
|
end
|
||||||
return bindings.request(self, 'sendMessage', {
|
return bindings.request(self, 'sendMessage', {
|
||||||
chat_id = chat_id,
|
chat_id = chat_id,
|
||||||
text = text,
|
text = text,
|
||||||
disable_web_page_preview = disable_web_page_preview,
|
disable_web_page_preview = disable_web_page_preview,
|
||||||
reply_to_message_id = reply_to_message_id,
|
reply_to_message_id = reply_to_message_id,
|
||||||
parse_mode = use_markdown,
|
parse_mode = parse_mode,
|
||||||
reply_markup = reply_markup
|
reply_markup = reply_markup
|
||||||
} )
|
} )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- https://core.telegram.org/bots/api#editmessagetext
|
-- https://core.telegram.org/bots/api#editmessagetext
|
||||||
function utilities:edit_message(chat_id, message_id, text, disable_web_page_preview, use_markdown, reply_markup)
|
function utilities:edit_message(chat_id, message_id, text, disable_web_page_preview, use_markdown, reply_markup)
|
||||||
if use_markdown == true then
|
local parse_mode
|
||||||
use_markdown = 'Markdown'
|
if type(use_markdown) == 'string' then
|
||||||
elseif not use_markdown then
|
parse_mode = use_markdown
|
||||||
use_markdown = nil
|
elseif use_markdown == true then
|
||||||
|
parse_mode = 'Markdown'
|
||||||
end
|
end
|
||||||
return bindings.request(self, 'editMessageText', {
|
return bindings.request(self, 'editMessageText', {
|
||||||
chat_id = chat_id,
|
chat_id = chat_id,
|
||||||
message_id = message_id,
|
message_id = message_id,
|
||||||
text = text,
|
text = text,
|
||||||
disable_web_page_preview = disable_web_page_preview,
|
disable_web_page_preview = disable_web_page_preview,
|
||||||
parse_mode = use_markdown,
|
parse_mode = parse_mode,
|
||||||
reply_markup = reply_markup
|
reply_markup = reply_markup
|
||||||
} )
|
} )
|
||||||
end
|
end
|
||||||
|
|
||||||
function utilities:send_reply(old_msg, text, use_markdown, reply_markup)
|
function utilities:send_reply(old_msg, text, use_markdown, reply_markup)
|
||||||
if use_markdown == true then
|
return utilities.send_message(self, old_msg.chat.id, text, true, old_msg.message_id, use_markdown, reply_markup)
|
||||||
use_markdown = 'Markdown'
|
|
||||||
elseif not use_markdown then
|
|
||||||
use_markdown = nil
|
|
||||||
end
|
|
||||||
return bindings.request(self, 'sendMessage', {
|
|
||||||
chat_id = old_msg.chat.id,
|
|
||||||
text = text,
|
|
||||||
disable_web_page_preview = true,
|
|
||||||
reply_to_message_id = old_msg.message_id,
|
|
||||||
parse_mode = use_markdown,
|
|
||||||
reply_markup = reply_markup
|
|
||||||
} )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- NOTE: Telegram currently only allows file uploads up to 50 MB
|
-- NOTE: Telegram currently only allows file uploads up to 50 MB
|
||||||
@ -222,27 +212,6 @@ function utilities:answer_inline_query(inline_query, results, cache_time, is_per
|
|||||||
} )
|
} )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get the indexed word in a string
|
|
||||||
function utilities.get_word(s, i)
|
|
||||||
s = s or ''
|
|
||||||
i = i or 1
|
|
||||||
local t = {}
|
|
||||||
for w in s:gmatch('%g+') do
|
|
||||||
table.insert(t, w)
|
|
||||||
end
|
|
||||||
return t[i] or false
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Like get_word(), but better.
|
|
||||||
-- Returns the actual index.
|
|
||||||
function utilities.index(s)
|
|
||||||
local t = {}
|
|
||||||
for w in s:gmatch('%g+') do
|
|
||||||
table.insert(t, w)
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Returns the string after the first space.
|
-- Returns the string after the first space.
|
||||||
function utilities.input(s)
|
function utilities.input(s)
|
||||||
if not s:find(' ') then
|
if not s:find(' ') then
|
||||||
@ -251,6 +220,10 @@ function utilities.input(s)
|
|||||||
return s:sub(s:find(' ')+1)
|
return s:sub(s:find(' ')+1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function utilities.input_from_msg(msg)
|
||||||
|
return utilities.input(msg.text) or (msg.reply_to_message and #msg.reply_to_message.text > 0 and msg.reply_to_message.text) or false
|
||||||
|
end
|
||||||
|
|
||||||
-- Calculates the length of the given string as UTF-8 characters
|
-- Calculates the length of the given string as UTF-8 characters
|
||||||
function utilities.utf8_len(s)
|
function utilities.utf8_len(s)
|
||||||
local chars = 0
|
local chars = 0
|
||||||
@ -343,13 +316,13 @@ end
|
|||||||
-- Loads a JSON file as a table.
|
-- Loads a JSON file as a table.
|
||||||
function utilities.load_data(filename)
|
function utilities.load_data(filename)
|
||||||
local f = io.open(filename)
|
local f = io.open(filename)
|
||||||
if not f then
|
if f then
|
||||||
|
local s = f:read('*all')
|
||||||
|
f:close()
|
||||||
|
return json.decode(s)
|
||||||
|
else
|
||||||
return {}
|
return {}
|
||||||
end
|
end
|
||||||
local s = f:read('*all')
|
|
||||||
f:close()
|
|
||||||
local data = json.decode(s)
|
|
||||||
return data
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Saves a table to a JSON file.
|
-- Saves a table to a JSON file.
|
||||||
@ -412,78 +385,6 @@ function utilities:resolve_username(input)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Simpler than above function; only returns an ID.
|
|
||||||
-- Returns nil if no ID is available.
|
|
||||||
function utilities:id_from_username(input)
|
|
||||||
input = input:gsub('^@', '')
|
|
||||||
for _, user in pairs(self.database.users) do
|
|
||||||
if user.username and user.username:lower() == input:lower() then
|
|
||||||
return user.id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Simpler than below function; only returns an ID.
|
|
||||||
-- Returns nil if no ID is available.
|
|
||||||
function utilities:id_from_message(msg)
|
|
||||||
if msg.reply_to_message then
|
|
||||||
return msg.reply_to_message.from.id
|
|
||||||
else
|
|
||||||
local input = utilities.input(msg.text)
|
|
||||||
if input then
|
|
||||||
if tonumber(input) then
|
|
||||||
return tonumber(input)
|
|
||||||
elseif input:match('^@') then
|
|
||||||
return utilities.id_from_username(self, input)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function utilities:user_from_message(msg, no_extra)
|
|
||||||
local input = utilities.input(msg.text_lower)
|
|
||||||
local target = {}
|
|
||||||
if msg.reply_to_message then
|
|
||||||
for k,v in pairs(self.database.users[msg.reply_to_message.from.id_str]) do
|
|
||||||
target[k] = v
|
|
||||||
end
|
|
||||||
elseif input and tonumber(input) then
|
|
||||||
target.id = tonumber(input)
|
|
||||||
if self.database.users[input] then
|
|
||||||
for k,v in pairs(self.database.users[input]) do
|
|
||||||
target[k] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif input and input:match('^@') then
|
|
||||||
local uname = input:gsub('^@', '')
|
|
||||||
for _,v in pairs(self.database.users) do
|
|
||||||
if v.username and uname == v.username:lower() then
|
|
||||||
for key, val in pairs(v) do
|
|
||||||
target[key] = val
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not target.id then
|
|
||||||
target.err = 'Sorry, I don\'t recognize that username.'
|
|
||||||
end
|
|
||||||
else
|
|
||||||
target.err = 'Please specify a user via reply, ID, or username.'
|
|
||||||
end
|
|
||||||
|
|
||||||
if not no_extra then
|
|
||||||
if target.id then
|
|
||||||
target.id_str = tostring(target.id)
|
|
||||||
end
|
|
||||||
if not target.first_name then
|
|
||||||
target.first_name = 'User'
|
|
||||||
end
|
|
||||||
target.name = utilities.build_name(target.first_name, target.last_name)
|
|
||||||
end
|
|
||||||
|
|
||||||
return target
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function utilities:handle_exception(err, message, config)
|
function utilities:handle_exception(err, message, config)
|
||||||
if not err then err = '' end
|
if not err then err = '' end
|
||||||
local output = '\n[' .. os.date('%F %T', os.time()) .. ']\n' .. self.info.username .. ': ' .. err .. '\n' .. message .. '\n'
|
local output = '\n[' .. os.date('%F %T', os.time()) .. ']\n' .. self.info.username .. ': ' .. err .. '\n' .. message .. '\n'
|
||||||
@ -500,15 +401,17 @@ function utilities.download_file(url, filename)
|
|||||||
return download_to_file(url, filename)
|
return download_to_file(url, filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
function utilities.markdown_escape(text)
|
function utilities.md_escape(text)
|
||||||
text = text:gsub('_', '\\_')
|
return text:gsub('_', '\\_')
|
||||||
text = text:gsub('%[', '\\[')
|
:gsub('%[', '\\['):gsub('%]', '\\]')
|
||||||
text = text:gsub('%*', '\\*')
|
:gsub('%*', '\\*'):gsub('`', '\\`')
|
||||||
text = text:gsub('`', '\\`')
|
|
||||||
return text
|
|
||||||
end
|
end
|
||||||
|
|
||||||
utilities.md_escape = utilities.markdown_escape
|
utilities.markdown_escape = utilities.md_escape
|
||||||
|
|
||||||
|
function utilities.html_escape(text)
|
||||||
|
return text:gsub('&', '&'):gsub('<', '<'):gsub('>', '>')
|
||||||
|
end
|
||||||
|
|
||||||
utilities.triggers_meta = {}
|
utilities.triggers_meta = {}
|
||||||
utilities.triggers_meta.__index = utilities.triggers_meta
|
utilities.triggers_meta.__index = utilities.triggers_meta
|
||||||
@ -584,7 +487,8 @@ utilities.char = {
|
|||||||
arabic = '[\216-\219][\128-\191]',
|
arabic = '[\216-\219][\128-\191]',
|
||||||
rtl_override = '',
|
rtl_override = '',
|
||||||
rtl_mark = '',
|
rtl_mark = '',
|
||||||
em_dash = '—'
|
em_dash = '—',
|
||||||
|
utf_8 = '[%z\1-\127\194-\244][\128-\191]',
|
||||||
}
|
}
|
||||||
|
|
||||||
-- taken from http://stackoverflow.com/a/11130774/3163199
|
-- taken from http://stackoverflow.com/a/11130774/3163199
|
||||||
|
Reference in New Issue
Block a user