Übernehme Änderungen von Brawl345/Brawlbot-v2
Hoffentlich ._.
This commit is contained in:
parent
7a98601d3e
commit
dbf323a02a
@ -6,4 +6,5 @@ insert_final_newline = true
|
||||
|
||||
[*.lua]
|
||||
charset = utf-8
|
||||
indent_style = tab
|
||||
indent_style = space
|
||||
indent_size = 4
|
18
README.md
18
README.md
@ -3,12 +3,12 @@
|
||||
|
||||
Der multifunktionale Telegram-Bot.
|
||||
|
||||
[Entwickler auf Telegram](http://telegram.me/Brawl) | [Offizieller Kanal](https://telegram.me/brawlbot_updates)
|
||||
[Offizielle Webseite](https://brawlbot.tk) | [Entwickler auf Telegram](http://telegram.me/Brawl) | [Offizieller Kanal](https://telegram.me/brawlbot_updates)
|
||||
|
||||
Brawlbot ist ein auf Plugins basierender Bot, der die [offizielle Telegram Bot API](http://core.telegram.org/bots/api) benutzt. Ursprünglich wurde er im Dezember 2014 auf Basis von Yagops [Telegram Bot](https://github.com/yagop/telegram-bot/) entwickelt, da aber die Entwicklung von tg-cli [zum Stillstand](https://brawlbot.tk/posts/ein-neuanfang) gekommen ist, wurden alle Plugins des bisher proprietären Brawlbots im Juni 2016 auf die Bot-API portiert und open-sourced.
|
||||
**Brawlbot v2 basiert auf [otouto](https://github.com/topkecleon/otouto) von Topkecleon.**
|
||||
|
||||
Brawlbot v2 ist freie Software; du darfst in modifizieren und weiterverbreiten, allerdings musst du dich an die GNU Affero General Public License v3 halten, siehe **LICENSE** für Details.
|
||||
Brawlbot v2 ist freie Software; du darfst ihn modifizieren und weiterverbreiten, allerdings musst du dich an die GNU Affero General Public License v3 halten, siehe **LICENSE** für Details.
|
||||
|
||||
##Anleitung
|
||||
|
||||
@ -22,7 +22,7 @@ Brawlbot v2 ist freie Software; du darfst in modifizieren und weiterverbreiten,
|
||||
# Für User
|
||||
## Setup
|
||||
### Ubuntu und Debian
|
||||
Ubuntu und Debian liefern Luarocks nur für Lua 5.1 aus. Um Luarocks für Lua 5.2 zu verwenden, folge bitte der [Anleitung auf StackOverflow](http://stackoverflow.com/a/20359102)
|
||||
Ubuntu und Debian liefern Luarocks nur für Lua 5.1 aus. Um Luarocks für Lua 5.2 zu verwenden, folge bitte der [Anleitung auf StackOverflow](http://stackoverflow.com/a/20359102).
|
||||
|
||||
### Setup
|
||||
Du benötigst **Lua 5.2+**, eine aktive **Redis-Instanz** und die folgenden **LuaRocks-Module**:
|
||||
@ -80,22 +80,24 @@ Brawlbot erhält laufend neue Plugins und wird kontinuierlich weiterentwickelt!
|
||||
## Plugins
|
||||
Brawlbot benutzt ein Plugin-System, ähnlich Yagops [Telegram-Bot](http://github.com/yagop/telegram-bot).
|
||||
|
||||
Ein Plugin kann fünf Komponenten haben, aber nur zwei werden benötigt:
|
||||
Ein Plugin kann zehn Komponenten haben, aber nur zwei werden benötigt:
|
||||
|
||||
| Komponente | Beschreibung | Benötigt? |
|
||||
|:------------------|:---------------------------------------------|:----------|
|
||||
| `plugin:action` | Hauptfunktion. Benötigt `msg` als Argument, empfohlen wird auch `matches` als drittes Argument nach `config` | J |
|
||||
| `plugin.triggers` | Tabelle von Triggern, (Lua-Patterns), auf die der Bot reagiert | J |
|
||||
| `plugin.triggers` | Tabelle von Triggern (Lua-Patterns), auf die der Bot reagiert | J |
|
||||
| `plugin.inline_triggers` | Tabelle von Triggern (Lua-Patterns), auf die der Bot bei Inline-Querys reagiert | N |
|
||||
| `plugin:init` | Optionale Funkion, die beim Start geladen wird | N |
|
||||
| `plugin:cron` | Wird jede Minute ausgeführt | N |
|
||||
| `plugin.command` | Einfaches Kommando mit Syntax. Wird bei `/hilfe` gelistet | N |
|
||||
| `plugin.doc` | Plugin-Hilfe. Wird mit `/help $kommando` gelistet | N |
|
||||
| `plugin.error` | Plugin-spezifische Fehlermeldung | N |
|
||||
| `plugin:callback` | Aktion, die ausgeführt wird, nachdem auf einen Callback-Button gedrückt wird. Siehe `gImages.lua` für ein Beispiel. Argumente: `callback` (enthält Callback-Daten), `msg`, `self`, `config`, `input` (enthält Parameter ohne `callback`) | N |
|
||||
| `plugin:inline_callback` | Aktion, die ausgeführt wird, wenn der Bot per Inline-Query ausgelöst wird. Argumente sind `inline_query` für die Daten, `config` und `matches` | N |
|
||||
|
||||
|
||||
Die`bot:on_msg_receive` Funktion fügt einige nützte Variablen zur ` msg` Tabelle hinzu. Diese sind:`msg.from.id_str`, `msg.to.id_str`, `msg.chat.id_str`, `msg.text_lower`, `msg.from.name`.
|
||||
|
||||
Rückgabewerte für `plugin:action` sind optional, aber wenn eine Tabelle zurückgegeben wird, wird diese die neue `msg`,-Tabelle und `on_msg_receive` wird damit fortfahren.
|
||||
|
||||
Interaktionen mit der Bot-API sind sehr einfach. Siehe [Bindings](#bindings) für Details.
|
||||
|
||||
Einige Funktionen, die oft benötigt werden, sind in `utilites.lua` verfügbar.
|
||||
@ -186,5 +188,3 @@ Das ist die Datenbank-Struktur:
|
||||
`database.userdata` speichert Daten von verschiedenen Plugins, hierzu wird aber für Brawlbot-Plugins Redis verwendet.
|
||||
|
||||
`database.version` speichert die Bot-Version.
|
||||
|
||||
* * *
|
@ -14,7 +14,7 @@ return {
|
||||
cli_port = 4567,
|
||||
-- The block of text returned by /start.
|
||||
about_text = [[
|
||||
Dies ist die BETA-Version von Brawlbot v2.
|
||||
Dies ist die BETA-Version von Mikubot v2.
|
||||
|
||||
Sende /hilfe, um zu starten
|
||||
]],
|
||||
@ -35,43 +35,20 @@ Sende /hilfe, um zu starten
|
||||
syntax = 'Invalide Syntax.',
|
||||
chatter_connection = 'Ich möchte gerade nicht reden',
|
||||
chatter_response = 'Ich weiß nicht, was ich darauf antworten soll.'
|
||||
}
|
||||
},
|
||||
|
||||
plugins = { -- To enable a plugin, add its name to the list.
|
||||
'control',
|
||||
'blacklist',
|
||||
'about',
|
||||
'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'
|
||||
}
|
||||
remind = {
|
||||
persist = true,
|
||||
max_length = 1000,
|
||||
max_duration = 526000,
|
||||
max_reminders_group = 10,
|
||||
max_reminders_private = 50
|
||||
},
|
||||
|
||||
chatter = {
|
||||
cleverbot_api = 'https://brawlbot.tk/apis/chatter-bot-api/cleverbot.php?text=',
|
||||
connection = 'I don\'t feel like talking right now.',
|
||||
response = 'I don\'t know what to say to that.'
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
while true; do
|
||||
lua main.lua
|
||||
echo 'Miku wurde gestoppt. ^C zum beenden.'
|
||||
sleep 5s
|
||||
lua main.lua
|
||||
echo 'Miku wurde gestoppt. ^C zum beenden.'
|
||||
sleep 5s
|
||||
done
|
@ -3,7 +3,6 @@
|
||||
otouto's bindings for the Telegram bot API.
|
||||
https://core.telegram.org/bots/api
|
||||
Copyright 2016 topkecleon. Published under the AGPLv3.
|
||||
|
||||
See the "Bindings" section of README.md for usage information.
|
||||
]]--
|
||||
|
||||
@ -48,7 +47,7 @@ function bindings:request(method, parameters, file)
|
||||
end
|
||||
local response = {}
|
||||
local body, boundary = MP_ENCODE(parameters)
|
||||
local success = HTTPS.request{
|
||||
local success, code = HTTPS.request{
|
||||
url = self.BASE_URL .. method,
|
||||
method = 'POST',
|
||||
headers = {
|
||||
@ -60,7 +59,7 @@ function bindings:request(method, parameters, file)
|
||||
}
|
||||
local data = table.concat(response)
|
||||
if not success then
|
||||
print(method .. ': Connection error.')
|
||||
print(method .. ': Connection error. [' .. code .. ']')
|
||||
return false, false
|
||||
else
|
||||
local result = JSON.decode(data)
|
||||
|
160
miku/bot.lua
160
miku/bot.lua
@ -3,20 +3,20 @@ local bot = {}
|
||||
bindings = require('miku.bindings')
|
||||
utilities = require('miku.utilities')
|
||||
|
||||
bot.version = '160801'
|
||||
bot.version = '160815'
|
||||
|
||||
function bot:init(config) -- The function run when the bot is started or reloaded.
|
||||
cred_data = load_cred()
|
||||
|
||||
assert(
|
||||
config.bot_api_key and config.bot_api_key ~= '',
|
||||
config.bot_api_key,
|
||||
'You did not set your bot token in the config!'
|
||||
)
|
||||
self.BASE_URL = 'https://api.telegram.org/bot' .. config.bot_api_key .. '/'
|
||||
|
||||
-- Fetch bot information. Try until it succeeds.
|
||||
repeat
|
||||
print('Fetching bot information...')
|
||||
print('Sammel Bot-Informationen...')
|
||||
self.info = bindings.getMe(self)
|
||||
until self.info
|
||||
self.info = self.info.result
|
||||
@ -26,33 +26,23 @@ function bot:init(config) -- The function run when the bot is started or reloade
|
||||
self.database = utilities.load_data(self.info.username..'.db')
|
||||
end
|
||||
|
||||
-- Table to cache user info (usernames, IDs, etc).
|
||||
self.database.users = self.database.users or {}
|
||||
-- Table to store userdata (nicknames, lastfm usernames, etc).
|
||||
self.database.userdata = self.database.userdata or {}
|
||||
-- Save the bot's version in the database to make migration simpler.
|
||||
self.database.version = bot.version
|
||||
-- Add updated bot info to the user info cache.
|
||||
self.database.users = self.database.users or {} -- Table to cache userdata.
|
||||
self.database.users[tostring(self.info.id)] = self.info
|
||||
|
||||
self.plugins = {} -- Load plugins.
|
||||
enabled_plugins = load_plugins()
|
||||
for k,v in pairs(enabled_plugins) do
|
||||
local p = require('miku.plugins.'..v)
|
||||
-- print('loading plugin',v)
|
||||
table.insert(self.plugins, p)
|
||||
self.plugins[k] = p
|
||||
self.plugins[k].name = v
|
||||
if p.init then p.init(self, config) end
|
||||
end
|
||||
|
||||
print('Bot wurde erfolgreich gestartet!\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,
|
||||
self.last_cron = self.last_cron or os.date('%M') -- the time of the last cron job,
|
||||
self.last_database_save = self.last_database_save or os.date('%H') -- the time of the last database save,
|
||||
-- Set loop variables
|
||||
self.last_update = self.last_update or 0 -- Update offset.
|
||||
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.
|
||||
|
||||
end
|
||||
|
||||
function bot:on_msg_receive(msg, config) -- The fn run whenever a message is received.
|
||||
@ -62,18 +52,6 @@ function bot:on_msg_receive(msg, config) -- The fn run whenever a message is rec
|
||||
|
||||
if msg.date < os.time() - 5 then return end -- Do not process old messages.
|
||||
|
||||
-- Cache user info for those involved.
|
||||
self.database.users[tostring(msg.from.id)] = msg.from
|
||||
if msg.reply_to_message then
|
||||
self.database.users[tostring(msg.reply_to_message.from.id)] = msg.reply_to_message.from
|
||||
elseif msg.forward_from then
|
||||
self.database.users[tostring(msg.forward_from.id)] = msg.forward_from
|
||||
elseif msg.new_chat_member then
|
||||
self.database.users[tostring(msg.new_chat_member.id)] = msg.new_chat_member
|
||||
elseif msg.left_chat_member then
|
||||
self.database.users[tostring(msg.left_chat_member.id)] = msg.left_chat_member
|
||||
end
|
||||
|
||||
msg = utilities.enrich_message(msg)
|
||||
|
||||
if msg.reply_to_message then
|
||||
@ -92,6 +70,7 @@ function bot:on_msg_receive(msg, config) -- The fn run whenever a message is rec
|
||||
msg.text_lower = msg.text:lower()
|
||||
end
|
||||
msg = pre_process_msg(self, msg, config)
|
||||
if not msg then return end -- deleted by banning
|
||||
|
||||
if is_service_msg(msg) then
|
||||
msg = service_modify_msg(msg)
|
||||
@ -115,6 +94,41 @@ function bot:on_callback_receive(callback, msg, config) -- whenever a new callba
|
||||
if not callback.data:find(':') or not callback.data:find('@'..self.info.username..' ') then
|
||||
return
|
||||
end
|
||||
|
||||
-- Check if user is blocked
|
||||
local user_id = callback.from.id
|
||||
local chat_id = msg.chat.id
|
||||
if redis:get('blocked:'..user_id) then
|
||||
utilities.answer_callback_query(self, callback, 'Du darfst den Bot nicht nutzen!', true)
|
||||
return
|
||||
end
|
||||
|
||||
-- Check if user is banned
|
||||
local banned = redis:get('banned:'..chat_id..':'..user_id)
|
||||
if banned then
|
||||
utilities.answer_callback_query(self, callback, 'Du darfst den Bot nicht nutzen!', true)
|
||||
return
|
||||
end
|
||||
|
||||
-- Check if whitelist is enabled and user/chat is whitelisted
|
||||
local whitelist = redis:get('whitelist:enabled')
|
||||
if whitelist and not is_sudo(msg, config) then
|
||||
local hash = 'whitelist:user#id'..user_id
|
||||
local allowed = redis:get(hash) or false
|
||||
if not allowed then
|
||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||
local allowed = redis:get('whitelist:chat#id'.. chat_id)
|
||||
if not allowed then
|
||||
utilities.answer_callback_query(self, callback, 'Du darfst den Bot nicht nutzen!', true)
|
||||
return
|
||||
end
|
||||
else
|
||||
utilities.answer_callback_query(self, callback, 'Du darfst den Bot nicht nutzen!', true)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
callback.data = string.gsub(callback.data, '@'..self.info.username..' ', "")
|
||||
local called_plugin = callback.data:match('(.*):.*')
|
||||
local param = callback.data:sub(callback.data:find(':')+1)
|
||||
@ -123,7 +137,8 @@ function bot:on_callback_receive(callback, msg, config) -- whenever a new callba
|
||||
|
||||
msg = utilities.enrich_message(msg)
|
||||
|
||||
for _, plugin in ipairs(self.plugins) do
|
||||
for n=1, #self.plugins do
|
||||
local plugin = self.plugins[n]
|
||||
if plugin.name == called_plugin then
|
||||
if is_plugin_disabled_on_chat(plugin.name, msg) then return end
|
||||
plugin:callback(callback, msg, self, config, param)
|
||||
@ -136,26 +151,43 @@ function bot:process_inline_query(inline_query, config) -- When an inline query
|
||||
-- remove comment to enable debugging
|
||||
-- vardump(inline_query)
|
||||
|
||||
-- PLEASE READ: Blocking every single InlineQuery IS NOT POSSIBLE!
|
||||
-- When the request is cached, the user can still send this query
|
||||
-- but he WON'T be able to make new requests.
|
||||
local user_id = inline_query.from.id
|
||||
if redis:get('blocked:'..user_id) then
|
||||
utilities.answer_inline_query(self, inline_query, nil, 0, true)
|
||||
return
|
||||
end
|
||||
|
||||
if not config.enable_inline_for_everyone then
|
||||
local is_whitelisted = redis:get('whitelist:user#id'..inline_query.from.id)
|
||||
if not is_whitelisted then return end
|
||||
if not is_whitelisted then utilities.answer_inline_query(self, inline_query, nil, 0, true) return end
|
||||
end
|
||||
|
||||
if inline_query.query:match('"') then
|
||||
inline_query.query = inline_query.query:gsub('"', '\\"')
|
||||
end
|
||||
for _, plugin in ipairs(self.plugins) do
|
||||
|
||||
for n=1, #self.plugins do
|
||||
local plugin = self.plugins[n]
|
||||
match_inline_plugins(self, inline_query, config, plugin)
|
||||
end
|
||||
|
||||
-- Stop the spinning circle
|
||||
utilities.answer_inline_query(self, inline_query, nil, 0, true)
|
||||
end
|
||||
|
||||
function bot:run(config)
|
||||
bot.init(self, config) -- Actually start the script.
|
||||
bot.init(self, config)
|
||||
|
||||
while self.is_started do -- Start a loop while the bot should be running.
|
||||
local res = bindings.getUpdates(self, { timeout=20, offset = self.last_update+1 } )
|
||||
while self.is_started do
|
||||
-- Update loop
|
||||
local res = bindings.getUpdates(self, { timeout = 20, offset = self.last_update+1 } )
|
||||
if res then
|
||||
for _,v in ipairs(res.result) do -- Go through every new message.
|
||||
-- Iterate over every new message.
|
||||
for n=1, #res.result do
|
||||
local v = res.result[n]
|
||||
self.last_update = v.update_id
|
||||
if v.inline_query then
|
||||
bot.process_inline_query(self, v.inline_query, config)
|
||||
@ -169,10 +201,12 @@ function bot:run(config)
|
||||
print('Connection error while fetching updates.')
|
||||
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')
|
||||
utilities.save_data(self.info.username..'.db', self.database) -- Save the database.
|
||||
for i,v in ipairs(self.plugins) do
|
||||
for n=1, #self.plugins do
|
||||
local v = self.plugins[n]
|
||||
if v.cron then -- Call each plugin's cron function, if it has one.
|
||||
local result, err = pcall(function() v.cron(self, config) end)
|
||||
if not result then
|
||||
@ -194,7 +228,8 @@ end
|
||||
|
||||
-- Apply plugin.pre_process function
|
||||
function pre_process_msg(self, msg, config)
|
||||
for _,plugin in ipairs(self.plugins) do
|
||||
for n=1, #self.plugins do
|
||||
local plugin = self.plugins[n]
|
||||
if plugin.pre_process and msg then
|
||||
-- print('Preprocess '..plugin.name) -- remove comment to restore old behaviour
|
||||
new_msg = plugin:pre_process(msg, self, config)
|
||||
@ -204,7 +239,9 @@ function pre_process_msg(self, msg, config)
|
||||
end
|
||||
|
||||
function match_inline_plugins(self, inline_query, config, plugin)
|
||||
for _, trigger in ipairs(plugin.inline_triggers or {}) do
|
||||
local match_table = plugin.inline_triggers or {}
|
||||
for n=1, #match_table do
|
||||
local trigger = plugin.inline_triggers[n]
|
||||
if string.match(string.lower(inline_query.query), trigger) then
|
||||
local success, result = pcall(function()
|
||||
for k, pattern in pairs(plugin.inline_triggers) do
|
||||
@ -216,50 +253,33 @@ function match_inline_plugins(self, inline_query, config, plugin)
|
||||
print('Inline: '..plugin.name..' ausgelöst')
|
||||
return plugin.inline_callback(self, inline_query, config, matches)
|
||||
end)
|
||||
if not success then
|
||||
print(result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function match_plugins(self, msg, config, plugin)
|
||||
for _, trigger in ipairs(plugin.triggers or {}) do
|
||||
local match_table = plugin.triggers or {}
|
||||
for n=1, #match_table do
|
||||
local trigger = plugin.triggers[n]
|
||||
if string.match(msg.text_lower, trigger) then
|
||||
-- Check if Plugin is disabled
|
||||
if is_plugin_disabled_on_chat(plugin.name, msg) then return end
|
||||
local success, result = pcall(function()
|
||||
-- trying to port matches to miku
|
||||
for k, pattern in pairs(plugin.triggers) do
|
||||
matches = match_pattern(pattern, msg.text)
|
||||
if matches then
|
||||
break;
|
||||
end
|
||||
local pattern = plugin.triggers[n]
|
||||
local matches = match_pattern(pattern, msg.text)
|
||||
if matches then
|
||||
print('msg matches: ', pattern, ' for "'..plugin.name..'"')
|
||||
return plugin.action(self, msg, config, matches)
|
||||
end
|
||||
print(plugin.name..' ausgelöst')
|
||||
return plugin.action(self, msg, config, matches)
|
||||
end)
|
||||
if not success then
|
||||
-- If the plugin has an error message, send it. If it does
|
||||
-- not, use the generic one specified in config. If it's set
|
||||
-- to false, do nothing.
|
||||
if plugin.error then
|
||||
utilities.send_reply(self, msg, plugin.error)
|
||||
elseif plugin.error == nil then
|
||||
utilities.send_reply(self, msg, config.errors.generic, true)
|
||||
utilities.handle_exception(self, result, msg.from.id .. ': ' .. msg.text, config)
|
||||
return
|
||||
end
|
||||
utilities.handle_exception(self, result, msg.from.id .. ': ' .. msg.text, config)
|
||||
-- if one pattern matches, end
|
||||
return
|
||||
end
|
||||
|
||||
-- If the action returns a table, make that table the new msg.
|
||||
if type(result) == 'table' then
|
||||
msg = result
|
||||
-- If the action returns true, continue.
|
||||
elseif result ~= true then
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -294,7 +314,7 @@ function create_plugin_set()
|
||||
'banhammer',
|
||||
'channels',
|
||||
'plugins',
|
||||
'help',
|
||||
'help'
|
||||
}
|
||||
print ('Aktiviere Plugins und speicher in telegram:enabled_plugins')
|
||||
for _,plugin in pairs(enabled_plugins) do
|
||||
|
@ -31,13 +31,15 @@ end
|
||||
|
||||
function ninegag:inline_callback(inline_query, config)
|
||||
local res, code = http.request(url)
|
||||
if code ~= 200 then return end
|
||||
if code ~= 200 then utilities.answer_inline_query(self, inline_query) return end
|
||||
local gag = json.decode(res)
|
||||
|
||||
local results = '['
|
||||
local id = 50
|
||||
for n in pairs(gag) do
|
||||
local title = gag[n].title:gsub('"', '\\"')
|
||||
results = results..'{"type":"photo","id":"'..math.random(100000000000000000)..'","photo_url":"'..gag[n].src..'","thumb_url":"'..gag[n].src..'","caption":"'..title..'","reply_markup":{"inline_keyboard":[[{"text":"9GAG aufrufen","url":"'..gag[n].url..'"}]]}}'
|
||||
results = results..'{"type":"photo","id":"'..id..'","photo_url":"'..gag[n].src..'","thumb_url":"'..gag[n].src..'","caption":"'..title..'","reply_markup":{"inline_keyboard":[[{"text":"9GAG aufrufen","url":"'..gag[n].url..'"}]]}}'
|
||||
id = id+1
|
||||
if n < #gag then
|
||||
results = results..','
|
||||
end
|
||||
|
@ -5,33 +5,16 @@ local bot = require('miku.bot')
|
||||
about.command = 'about'
|
||||
about.doc = '`Sendet Informationen über den Bot.`'
|
||||
|
||||
about.triggers = {
|
||||
function about:init(config)
|
||||
about.text = config.about_text .. '\n[Mikudayobot](https://github.com/Akamaru/Mikubot-V2) v'..bot.version..' von @Akamaru, basierend auf [otouto](https://github.com/topkecleon/otouto) von topkecleon.'
|
||||
about.triggers = {
|
||||
'/[Aa][Bb][Oo][Uu][Tt]',
|
||||
'/[Ss][Tt][Aa][Rr][Tt]'
|
||||
}
|
||||
end
|
||||
|
||||
function about:action(msg, config)
|
||||
|
||||
-- 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 .. '\n[Mikudayobot](https://github.com/Akamaru/Mikubot-V2) v'..bot.version..' von @Akamaru, basierend auf [otouto](https://github.com/topkecleon/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
|
||||
|
||||
utilities.send_message(self, msg.chat.id, about.text, true, nil, true)
|
||||
end
|
||||
|
||||
return about
|
@ -27,10 +27,10 @@ function adfly:inline_callback(inline_query, config, matches)
|
||||
url = redis:get(hash)
|
||||
end
|
||||
|
||||
if not url then return end
|
||||
if url == 'NOTFOUND' then return end
|
||||
if not url then utilities.answer_inline_query(self, inline_query) return end
|
||||
if url == 'NOTFOUND' then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
local results = '[{"type":"article","id":"'..math.random(100000000000000000)..'","title":"Verlängerte URL","description":"'..url..'","url":"'..url..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/generic/internet.jpg","thumb_width":165,"thumb_height":150,"hide_url":true,"input_message_content":{"message_text":"'..url..'"}}]'
|
||||
local results = '[{"type":"article","id":"1","title":"Verlängerte URL","description":"'..url..'","url":"'..url..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/generic/internet.jpg","thumb_width":165,"thumb_height":150,"hide_url":true,"input_message_content":{"message_text":"'..url..'"}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, 3600, true)
|
||||
end
|
||||
|
||||
|
@ -5,7 +5,7 @@ local afk = {}
|
||||
|
||||
function afk:init(config)
|
||||
afk.triggers = {
|
||||
"^/([Aa][Ff][Kk])$",
|
||||
"^/([Aa][Ff][Kk])$",
|
||||
"^/([Aa][Ff][Kk]) (.*)$"
|
||||
}
|
||||
afk.doc = [[*
|
||||
@ -68,7 +68,7 @@ function afk:pre_process(msg, self)
|
||||
local user_id = msg.from.id
|
||||
local chat_id = msg.chat.id
|
||||
local hash = 'afk:'..chat_id..':'..user_id
|
||||
|
||||
local uhash = 'user:'..user_id
|
||||
|
||||
if afk:is_offline(hash) then
|
||||
local afk_text = afk:get_afk_text(hash)
|
||||
@ -80,18 +80,27 @@ function afk:pre_process(msg, self)
|
||||
local duration = makeHumanTime(afk_time)
|
||||
|
||||
redis:hset(hash, 'afk', false)
|
||||
local show_afk_keyboard = redis:hget(uhash, 'afk_keyboard')
|
||||
if afk_text then
|
||||
redis:hset(hash, 'afk_text', false)
|
||||
utilities.send_reply(self, msg, user_name..' ist wieder da! (war: <b>'..afk_text..'</b> für '..duration..')', 'HTML', '{"hide_keyboard":true,"selective":true}')
|
||||
if show_afk_keyboard == 'true' then
|
||||
utilities.send_reply(self, msg, user_name..' ist wieder da! (war: <b>'..afk_text..'</b> für '..duration..')', 'HTML', '{"hide_keyboard":true,"selective":true}')
|
||||
else
|
||||
utilities.send_message(self, chat_id, user_name..' ist wieder da! (war: <b>'..afk_text..'</b> für '..duration..')', true, nil, 'HTML')
|
||||
end
|
||||
else
|
||||
utilities.send_reply(self, msg, user_name..' ist wieder da! (war '..duration..' weg)', nil, '{"hide_keyboard":true,"selective":true}')
|
||||
if show_afk_keyboard == 'true' then
|
||||
utilities.send_reply(self, msg, user_name..' ist wieder da! (war '..duration..' weg)', nil, '{"hide_keyboard":true,"selective":true}')
|
||||
else
|
||||
utilities.send_message(self, chat_id, user_name..' ist wieder da! (war '..duration..' weg)')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return msg
|
||||
end
|
||||
|
||||
function afk:action(msg)
|
||||
function afk:action(msg, config, matches)
|
||||
if msg.chat.type == "private" then
|
||||
utilities.send_reply(self, msg, "Mir ist's egal, ob du AFK bist.")
|
||||
return
|
||||
|
@ -36,11 +36,13 @@ function bImages:getImages(query)
|
||||
|
||||
|
||||
local results = '['
|
||||
local id = 300
|
||||
for n in pairs(images) do
|
||||
if images[n].encodingFormat == 'jpeg' then -- Inline-Querys MUST use JPEG photos!
|
||||
local photo_url = images[n].contentUrl
|
||||
local thumb_url = images[n].thumbnailUrl
|
||||
results = results..'{"type":"photo","id":"'..math.random(100000000000000000)..'","photo_url":"'..photo_url..'","thumb_url":"'..thumb_url..'","photo_width":'..images[n].width..',"photo_height":'..images[n].height..',"reply_markup":{"inline_keyboard":[[{"text":"Bing aufrufen","url":"'..images[n].webSearchUrl..'"},{"text":"Bild öffnen","url":"'..photo_url..'"}]]}},'
|
||||
results = results..'{"type":"photo","id":"'..id..'","photo_url":"'..photo_url..'","thumb_url":"'..thumb_url..'","photo_width":'..images[n].width..',"photo_height":'..images[n].height..',"reply_markup":{"inline_keyboard":[[{"text":"Bing aufrufen","url":"'..images[n].webSearchUrl..'"},{"text":"Bild öffnen","url":"'..photo_url..'"}]]}},'
|
||||
id = id+1
|
||||
end
|
||||
end
|
||||
|
||||
@ -57,7 +59,7 @@ function bImages:inline_callback(inline_query, config, matches)
|
||||
results = bImages:getImages(query)
|
||||
end
|
||||
|
||||
if not results then return end
|
||||
if not results then utilities.answer_inline_query(self, inline_query) return end
|
||||
utilities.answer_inline_query(self, inline_query, results, 3600)
|
||||
end
|
||||
|
||||
|
@ -12,7 +12,17 @@ function banhammer:init(config)
|
||||
"^/(whitelist) (delete) (chat)$",
|
||||
"^/(ban) (user) (%d+)$",
|
||||
"^/(ban) (delete) (%d+)$",
|
||||
"^/(kick) (%d+)$"
|
||||
"^/(block) (user) (%d+)$",
|
||||
"^/(block) (delete) (%d+)$",
|
||||
"^/(whitelist)$",
|
||||
"^/(whitelist) (delete)$",
|
||||
"^/(ban)$",
|
||||
"^/(ban) (delete)$",
|
||||
"^/(block)$",
|
||||
"^/(block) (delete)$",
|
||||
"^/(kick) (%d+)$",
|
||||
"^/(kick)$",
|
||||
"^/(leave)$"
|
||||
}
|
||||
banhammer.doc = [[*
|
||||
]]..config.cmd_pat..[[whitelist* _<enable>_/_<disable>_: Aktiviert/deaktiviert Whitelist
|
||||
@ -22,7 +32,11 @@ function banhammer:init(config)
|
||||
*]]..config.cmd_pat..[[whitelist* delete chat: Lösche ganze Gruppe von der Whitelist
|
||||
*]]..config.cmd_pat..[[ban* user _<user#id>_: Kicke User vom Chat und kicke ihn, wenn er erneut beitritt
|
||||
*]]..config.cmd_pat..[[ban* delete _<user#id>_: Entbanne User
|
||||
*]]..config.cmd_pat..[[kick* _<user#id>_: Kicke User aus dem Chat]]
|
||||
*]]..config.cmd_pat..[[block* user _<user#id>_: Blocke User vom Bot
|
||||
*]]..config.cmd_pat..[[block* delete _<user#id>_: Entblocke User
|
||||
*]]..config.cmd_pat..[[kick* _<user#id>_: Kicke User aus dem Chat
|
||||
*]]..config.cmd_pat..[[leave*: Bot verlässt die Gruppe
|
||||
Alternativ kann auch auf die Nachricht des Users geantwortet werden, die Befehle sind dnn die obrigen ohne `user` bzw.`delete`.]]
|
||||
end
|
||||
|
||||
function banhammer:kick_user(user_id, chat_id, self, onlykick)
|
||||
@ -54,8 +68,8 @@ 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', {
|
||||
if chat_type == 'supergroup' then
|
||||
bindings.request(self, 'unbanChatMember', {
|
||||
chat_id = chat_id,
|
||||
user_id = user_id
|
||||
} )
|
||||
@ -96,76 +110,94 @@ function banhammer:pre_process(msg, self, config)
|
||||
end
|
||||
|
||||
-- BANNED USER TALKING
|
||||
local user_id = msg.from.id
|
||||
local chat_id = msg.chat.id
|
||||
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 = ''
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- BLOCKED USER TALKING (block = user can't use bot, but won't be kicked from group)
|
||||
local hash = 'blocked:'..user_id
|
||||
local issudo = is_sudo(msg, config)
|
||||
local blocked = redis:get(hash)
|
||||
if blocked and not issudo then
|
||||
print('User '..user_id..' blocked')
|
||||
return
|
||||
end
|
||||
|
||||
-- WHITELIST
|
||||
-- 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')
|
||||
local allowed = banhammer:is_user_whitelisted(user_id)
|
||||
local has_been_warned = redis:hget('user:'..user_id, 'has_been_warned')
|
||||
|
||||
if not allowed then
|
||||
print('User '..msg.from.id..' not whitelisted')
|
||||
print('User '..user_id..' not whitelisted')
|
||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||
allowed = banhammer:is_chat_whitelisted(msg.chat.id)
|
||||
allowed = banhammer:is_chat_whitelisted(chat_id)
|
||||
if not allowed then
|
||||
print ('Chat '..msg.chat.id..' not whitelisted')
|
||||
print ('Chat '..chat_id..' not whitelisted')
|
||||
else
|
||||
print ('Chat '..msg.chat.id..' whitelisted :)')
|
||||
print ('Chat '..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)
|
||||
redis:hset('user:'..user_id, 'has_been_warned', true)
|
||||
else
|
||||
print('User has already been warned!')
|
||||
end
|
||||
end
|
||||
else
|
||||
print('User '..msg.from.id..' allowed :)')
|
||||
print('User '..user_id..' allowed :)')
|
||||
end
|
||||
|
||||
if not allowed then
|
||||
msg.text = ''
|
||||
msg.text_lower = ''
|
||||
msg.entities = ''
|
||||
return
|
||||
end
|
||||
|
||||
-- else
|
||||
-- print('Whitelist not enabled or is sudo')
|
||||
end
|
||||
|
||||
return msg
|
||||
end
|
||||
|
||||
function banhammer:action(msg, config, matches)
|
||||
if msg.from.id ~= config.admin then
|
||||
if not is_sudo(msg, config) then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
|
||||
if matches[1] == 'leave' then
|
||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||
bindings.request(self, 'leaveChat', {
|
||||
chat_id = msg.chat.id
|
||||
} )
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if matches[1] == 'ban' then
|
||||
local user_id = matches[3]
|
||||
local chat_id = msg.chat.id
|
||||
if not user_id then
|
||||
if not msg.reply_to_message then
|
||||
return
|
||||
end
|
||||
user_id = msg.reply_to_message.from.id
|
||||
end
|
||||
|
||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||
if matches[2] == 'user' then
|
||||
if matches[2] == 'user' or not matches[2] then
|
||||
local text = banhammer:ban_user(user_id, chat_id, self)
|
||||
utilities.send_reply(self, msg, text)
|
||||
return
|
||||
@ -183,7 +215,14 @@ function banhammer:action(msg, config, matches)
|
||||
|
||||
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)
|
||||
local user_id = matches[2]
|
||||
if not user_id then
|
||||
if not msg.reply_to_message then
|
||||
return
|
||||
end
|
||||
user_id = msg.reply_to_message.from.id
|
||||
end
|
||||
banhammer:kick_user(user_id, msg.chat.id, self, true)
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, 'Das ist keine Chat-Gruppe')
|
||||
@ -206,6 +245,28 @@ function banhammer:action(msg, config, matches)
|
||||
return
|
||||
end
|
||||
|
||||
if not matches[2] then
|
||||
if not msg.reply_to_message then
|
||||
return
|
||||
end
|
||||
local user_id = msg.reply_to_message.from.id
|
||||
local hash = 'whitelist:user#id'..user_id
|
||||
redis:set(hash, true)
|
||||
utilities.send_reply(self, msg, 'User '..user_id..' whitelisted')
|
||||
return
|
||||
end
|
||||
|
||||
if matches[2] == 'delete' and not matches[3] then
|
||||
if not msg.reply_to_message then
|
||||
return
|
||||
end
|
||||
local user_id = msg.reply_to_message.from.id
|
||||
local hash = 'whitelist:user#id'..user_id
|
||||
redis:del(hash)
|
||||
utilities.send_reply(self, msg, 'User '..user_id..' von der Whitelist entfernt!')
|
||||
return
|
||||
end
|
||||
|
||||
if matches[2] == 'user' then
|
||||
local hash = 'whitelist:user#id'..matches[3]
|
||||
redis:set(hash, true)
|
||||
@ -244,6 +305,46 @@ function banhammer:action(msg, config, matches)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if matches[1] == 'block' then
|
||||
|
||||
if matches[2] == 'user' and matches[3] then
|
||||
local hash = 'blocked:'..matches[3]
|
||||
redis:set(hash, true)
|
||||
utilities.send_reply(self, msg, 'User '..matches[3]..' darf den Bot nun nicht mehr nutzen.')
|
||||
return
|
||||
end
|
||||
|
||||
if matches[2] == 'delete' and matches[3] then
|
||||
local hash = 'blocked:'..matches[3]
|
||||
redis:del(hash)
|
||||
utilities.send_reply(self, msg, 'User '..matches[3]..' darf den Bot wieder nutzen.')
|
||||
return
|
||||
end
|
||||
|
||||
if not matches[2] then
|
||||
if not msg.reply_to_message then
|
||||
return
|
||||
end
|
||||
local user_id = msg.reply_to_message.from.id
|
||||
local hash = 'blocked:'..user_id
|
||||
redis:set(hash, true)
|
||||
utilities.send_reply(self, msg, 'User '..user_id..' darf den Bot nun nicht mehr nutzen.')
|
||||
return
|
||||
end
|
||||
|
||||
if matches[2] == 'delete' and not matches[3] then
|
||||
if not msg.reply_to_message then
|
||||
return
|
||||
end
|
||||
local user_id = msg.reply_to_message.from.id
|
||||
local hash = 'blocked:'..user_id
|
||||
redis:del(hash)
|
||||
utilities.send_reply(self, msg, 'User '..user_id..' darf den Bot wieder nutzen.')
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
return banhammer
|
@ -38,9 +38,9 @@ function bitly:inline_callback(inline_query, config, matches)
|
||||
url = data.long_url
|
||||
end
|
||||
|
||||
if not url then return end
|
||||
if not url then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
local results = '[{"type":"article","id":"'..math.random(100000000000000000)..'","title":"Verlängerte URL","description":"'..url..'","url":"'..url..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/generic/internet.jpg","thumb_width":165,"thumb_height":150,"hide_url":true,"input_message_content":{"message_text":"'..url..'"}}]'
|
||||
local results = '[{"type":"article","id":"2","title":"Verlängerte URL","description":"'..url..'","url":"'..url..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/generic/internet.jpg","thumb_width":165,"thumb_height":150,"hide_url":true,"input_message_content":{"message_text":"'..url..'"}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, 3600)
|
||||
end
|
||||
|
||||
|
@ -5,7 +5,7 @@ cats.command = 'kitty [gif]'
|
||||
function cats:init(config)
|
||||
if not cred_data.cat_apikey then
|
||||
print('Fehlender Key: cat_apikey.')
|
||||
print('cats.lua will be enabled, but there are more features with a key.')
|
||||
print('cats.lua wird aktiviert, aber mit einem Key gibt es mehr Features.')
|
||||
end
|
||||
|
||||
cats.triggers = {
|
||||
@ -29,8 +29,10 @@ local apikey = cred_data.cat_apikey or "" -- apply for one here: http://thecatap
|
||||
function cats:inline_callback(inline_query, config, matches)
|
||||
if matches[1] == 'gif' then
|
||||
img_type = 'gif'
|
||||
id = 100
|
||||
else
|
||||
img_type = 'jpg'
|
||||
id = 200
|
||||
end
|
||||
local url = 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20xml%20where%20url%3D%27http%3A%2F%2Fthecatapi.com%2Fapi%2Fimages%2Fget%3Fformat%3Dxml%26results_per_page%3D50%26type%3D'..img_type..'%26apikey%3D'..apikey..'%27&format=json' -- no way I'm using XML, plz die
|
||||
local res, code = https.request(url)
|
||||
@ -43,9 +45,11 @@ function cats:inline_callback(inline_query, config, matches)
|
||||
|
||||
for n in pairs(data) do
|
||||
if img_type == 'gif' then
|
||||
results = results..'{"type":"gif","id":"'..math.random(100000000000000000)..'","gif_url":"'..data[n].url..'","thumb_url":"'..data[n].url..'"}'
|
||||
results = results..'{"type":"gif","id":"'..id..'","gif_url":"'..data[n].url..'","thumb_url":"'..data[n].url..'"}'
|
||||
id = id+1
|
||||
else
|
||||
results = results..'{"type":"photo","id":"'..math.random(100000000000000000)..'","photo_url":"'..data[n].url..'","thumb_url":"'..data[n].url..'"}'
|
||||
results = results..'{"type":"photo","id":"'..id..'","photo_url":"'..data[n].url..'","thumb_url":"'..data[n].url..'"}'
|
||||
id = id+1
|
||||
end
|
||||
if n < #data then
|
||||
results = results..','
|
||||
|
@ -2,22 +2,30 @@ local cleverbot = {}
|
||||
|
||||
function cleverbot:init(config)
|
||||
cleverbot.triggers = {
|
||||
"^/[Cc][Bb][Oo][Tt] (.*)$"
|
||||
"^/[Cc][Bb][Oo][Tt] (.*)$",
|
||||
"^[Mm][Ii][Kk][Uu][Bb][Oo][Tt], (.+)$",
|
||||
}
|
||||
|
||||
cleverbot.doc = [[*
|
||||
]]..config.cmd_pat..[[cbot* _<Text>_*: Befragt den Cleverbot]]
|
||||
cleverbot.url = config.chatter.cleverbot_api
|
||||
end
|
||||
|
||||
cleverbot.command = 'cbot <Text>'
|
||||
|
||||
function cleverbot:action(msg, config)
|
||||
local text = msg.text
|
||||
local url = "https://brawlbot.tk/apis/chatter-bot-api/cleverbot.php?text="..URL.escape(text)
|
||||
local query = https.request(url)
|
||||
if query == nil then utilities.send_reply(self, msg, 'Ein Fehler ist aufgetreten :(') return end
|
||||
local decode = json.decode(query)
|
||||
local answer = string.gsub(decode.clever, "Ä", "Ä")
|
||||
function cleverbot:action(msg, config, matches)
|
||||
utilities.send_typing(self, msg.chat.id, 'typing')
|
||||
local text = matches[1]
|
||||
local query, code = https.request(cleverbot.url..URL.escape(text))
|
||||
if code ~= 200 then
|
||||
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, "ö", "ö")
|
||||
|
@ -4,57 +4,119 @@ currency.command = 'cash [Menge] <von> <zu>'
|
||||
|
||||
function currency:init(config)
|
||||
currency.triggers = {
|
||||
"^/[Cc][Aa][Ss][Hh] ([A-Za-z]+)$",
|
||||
"^/[Cc][Aa][Ss][Hh] ([A-Za-z]+) ([A-Za-z]+)$",
|
||||
"^/[Cc][Aa][Ss][Hh] (%d+[%d%.,]*) ([A-Za-z]+) ([A-Za-z]+)$",
|
||||
"^(/[Ee][Uu][Rr])$"
|
||||
"^/cash ([A-Za-z]+)$",
|
||||
"^/cash ([A-Za-z]+) ([A-Za-z]+)$",
|
||||
"^/cash (%d+[%d%.,]*) ([A-Za-z]+) ([A-Za-z]+)$",
|
||||
"^(/cash)$"
|
||||
}
|
||||
currency.inline_triggers = {
|
||||
"^c ([A-Za-z]+)$",
|
||||
"^c ([A-Za-z]+) ([A-Za-z]+)$",
|
||||
"^c (%d+[%d%.,]*) ([A-Za-z]+) ([A-Za-z]+)$"
|
||||
}
|
||||
currency.doc = [[*
|
||||
]]..config.cmd_pat..[[cash* _[Menge]_ _<von>_ _<zu>_
|
||||
*]]..config.cmd_pat..[[cash* _<von>_: Rechnet in Euro um
|
||||
*]]..config.cmd_pat..[[cash* _<von>_ _<zu>_: Rechnet mit der Einheit 1
|
||||
Beispiel: _]]..config.cmd_pat..[[cash 5 USD EUR_]]
|
||||
end
|
||||
|
||||
function currency:action(msg, config)
|
||||
if not matches[2] then
|
||||
from = string.upper(matches[1])
|
||||
to = 'EUR'
|
||||
local BASE_URL = 'https://api.fixer.io'
|
||||
|
||||
function currency:inline_callback(inline_query, config, matches)
|
||||
if not matches[2] then -- first pattern
|
||||
base = 'EUR'
|
||||
to = string.upper(matches[1])
|
||||
amount = 1
|
||||
elseif matches[3] then
|
||||
from = string.upper(matches[2])
|
||||
elseif matches[3] then -- third pattern
|
||||
base = string.upper(matches[2])
|
||||
to = string.upper(matches[3])
|
||||
amount = matches[1]
|
||||
else
|
||||
from = string.upper(matches[1])
|
||||
else -- second pattern
|
||||
base = string.upper(matches[1])
|
||||
to = string.upper(matches[2])
|
||||
amount = 1
|
||||
end
|
||||
|
||||
local value, iserr = currency:convert_money(base, to, amount)
|
||||
if iserr then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
local output = amount..' '..base..' = *'..value..' '..to..'*'
|
||||
if tonumber(amount) == 1 then
|
||||
title = amount..' '..base..' entspricht'
|
||||
else
|
||||
title = amount..' '..base..' entsprechen'
|
||||
end
|
||||
local results = '[{"type":"article","id":"20","title":"'..title..'","description":"'..value..' '..to..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/currency/cash.jpg","thumb_width":157,"thumb_height":140,"input_message_content":{"message_text":"'..output..'","parse_mode":"Markdown"}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, 3600)
|
||||
end
|
||||
|
||||
function currency:convert_money(base, to, amount)
|
||||
local url = BASE_URL..'/latest?base='..base..'&symbols='..to
|
||||
local amount = string.gsub(amount, ",", ".")
|
||||
amount = tonumber(amount)
|
||||
local result = 1
|
||||
local BASE_URL = 'https://www.google.com/finance/converter'
|
||||
local amount = tonumber(amount)
|
||||
local res, code = https.request(url)
|
||||
if code ~= 200 and code ~= 422 then
|
||||
return 'NOCONNECT', true
|
||||
end
|
||||
|
||||
local res, code = https.request(url)
|
||||
local data = json.decode(res)
|
||||
if data.error then
|
||||
return 'WRONGBASE', true
|
||||
end
|
||||
|
||||
local rate = data.rates[to]
|
||||
if not rate then
|
||||
return 'WRONGCONVERTRATE', true
|
||||
end
|
||||
|
||||
if amount == 1 then
|
||||
value = round(rate, 2)
|
||||
else
|
||||
value = round(rate * amount, 2)
|
||||
end
|
||||
local value = tostring(string.gsub(value, "%.", ","))
|
||||
|
||||
return value
|
||||
end
|
||||
|
||||
function currency:action(msg, config, matches)
|
||||
if matches[1] == '/cash' then
|
||||
utilities.send_reply(self, msg, currency.doc, true)
|
||||
return
|
||||
elseif not matches[2] then -- first pattern
|
||||
base = 'EUR'
|
||||
to = string.upper(matches[1])
|
||||
amount = 1
|
||||
elseif matches[3] then -- third pattern
|
||||
base = string.upper(matches[2])
|
||||
to = string.upper(matches[3])
|
||||
amount = matches[1]
|
||||
else -- second pattern
|
||||
base = string.upper(matches[1])
|
||||
to = string.upper(matches[2])
|
||||
amount = 1
|
||||
end
|
||||
|
||||
if from == to then
|
||||
utilities.send_reply(self, msg, 'Jaja, sehr witzig...')
|
||||
return
|
||||
end
|
||||
|
||||
local url = BASE_URL..'?from='..from..'&to='..to..'&a='..amount
|
||||
local str, res = https.request(url)
|
||||
if res ~= 200 then
|
||||
local value = currency:convert_money(base, to, amount)
|
||||
if value == 'NOCONNECT' then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
return
|
||||
end
|
||||
|
||||
local str = str:match('<span class=bld>(.*) %u+</span>')
|
||||
if not str then
|
||||
utilities.send_reply(self, msg, 'Keine gültige Währung - sieh dir die Währungsliste bei [Google Finanzen](https://www.google.com/finance/converter) an.', true)
|
||||
elseif value == 'WRONGBASE' then
|
||||
utilities.send_reply(self, msg, 'Keine gültige Basiswährung.')
|
||||
return
|
||||
elseif value == 'WRONGCONVERTRATE' then
|
||||
utilities.send_reply(self, msg, 'Keine gültige Umwandlungswährung.')
|
||||
return
|
||||
end
|
||||
local result = string.format('%.2f', str)
|
||||
local result = string.gsub(result, "%.", ",")
|
||||
|
||||
local amount = tostring(string.gsub(amount, "%.", ","))
|
||||
local output = amount..' '..from..' = *'..result..' '..to..'*'
|
||||
local output = amount..' '..base..' = *'..value..' '..to..'*'
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
end
|
||||
|
||||
|
@ -18,15 +18,15 @@ function echo:inline_callback(inline_query, config, matches)
|
||||
|
||||
-- enable custom markdown button
|
||||
if text:match('%[.*%]%(.*%)') or text:match('%*.*%*') or text:match('_.*_') or text:match('`.*`') then
|
||||
results = results..'{"type":"article","id":"'..math.random(100000000000000000)..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/echo/custom.jpg","title":"Eigenes Markdown","description":"'..text..'","input_message_content":{"message_text":"'..text..'","parse_mode":"Markdown"}},'
|
||||
results = results..'{"type":"article","id":"3","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/echo/custom.jpg","title":"Eigenes Markdown","description":"'..text..'","input_message_content":{"message_text":"'..text..'","parse_mode":"Markdown"}},'
|
||||
end
|
||||
|
||||
local results = results..'{"type":"article","id":"'..math.random(100000000000000000)..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/echo/fett.jpg","title":"Fett","description":"*'..text..'*","input_message_content":{"message_text":"<b>'..text..'</b>","parse_mode":"HTML"}},{"type":"article","id":"'..math.random(100000000000000000)..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/echo/kursiv.jpg","title":"Kursiv","description":"_'..text..'_","input_message_content":{"message_text":"<i>'..text..'</i>","parse_mode":"HTML"}},{"type":"article","id":"'..math.random(100000000000000000)..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/echo/fixedsys.jpg","title":"Feste Breite","description":"`'..text..'`","input_message_content":{"message_text":"<code>'..text..'</code>","parse_mode":"HTML"}}]'
|
||||
local results = results..'{"type":"article","id":"4","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/echo/fett.jpg","title":"Fett","description":"*'..text..'*","input_message_content":{"message_text":"<b>'..text..'</b>","parse_mode":"HTML"}},{"type":"article","id":"5","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/echo/kursiv.jpg","title":"Kursiv","description":"_'..text..'_","input_message_content":{"message_text":"<i>'..text..'</i>","parse_mode":"HTML"}},{"type":"article","id":"6","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/echo/fixedsys.jpg","title":"Feste Breite","description":"`'..text..'`","input_message_content":{"message_text":"<code>'..text..'</code>","parse_mode":"HTML"}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, 0)
|
||||
end
|
||||
|
||||
function echo:action(msg)
|
||||
local input = utilities.input(msg.text)
|
||||
local input = utilities.input_from_msg(msg)
|
||||
if not input then
|
||||
utilities.send_message(self, msg.chat.id, echo.doc, true, msg.message_id, true)
|
||||
else
|
||||
|
@ -26,7 +26,7 @@ function expand:inline_callback(inline_query, config, matches)
|
||||
description = url
|
||||
end
|
||||
|
||||
local results = '[{"type":"article","id":"'..math.random(100000000000000000)..'","title":"'..title..'","description":"'..description..'","url":"'..url..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/generic/internet.jpg","thumb_width":165,"thumb_height":150,"hide_url":true,"input_message_content":{"message_text":"'..url..'"}}]'
|
||||
local results = '[{"type":"article","id":"7","title":"'..title..'","description":"'..description..'","url":"'..url..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/generic/internet.jpg","thumb_width":165,"thumb_height":150,"hide_url":true,"input_message_content":{"message_text":"'..url..'"}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, 3600)
|
||||
end
|
||||
|
||||
|
@ -8,13 +8,13 @@ function facebook:init(config)
|
||||
end
|
||||
|
||||
facebook.triggers = {
|
||||
'facebook.com/([A-Za-z0-9-._-]+)/(posts)/(%d+)',
|
||||
'facebook.com/(permalink).php%?(story_fbid)=(%d+)&id=(%d+)',
|
||||
'facebook.com/(photo).php%?fbid=(%d+)',
|
||||
'facebook.com/([A-Za-z0-9-._-]+)/(photos)/a.(%d+[%d%.]*)/(%d+)',
|
||||
'facebook.com/(video).php%?v=(%d+)',
|
||||
'facebook.com/([A-Za-z0-9-._-]+)/(videos)/(%d+[%d%.]*)',
|
||||
'facebook.com/([A-Za-z0-9-._-]+)'
|
||||
"facebook.com/([A-Za-z0-9-._-]+)/(posts)/(%d+)",
|
||||
"facebook.com/(permalink).php%?(story_fbid)=(%d+)&id=(%d+)",
|
||||
"facebook.com/(photo).php%?fbid=(%d+)",
|
||||
"facebook.com/([A-Za-z0-9-._-]+)/(photos)/a.(%d+[%d%.]*)/(%d+)",
|
||||
"facebook.com/(video).php%?v=(%d+)",
|
||||
"facebook.com/([A-Za-z0-9-._-]+)/(videos)/(%d+[%d%.]*)",
|
||||
"facebook.com/([A-Za-z0-9-._-]+)/?$"
|
||||
}
|
||||
end
|
||||
|
||||
@ -22,7 +22,7 @@ local BASE_URL = 'https://graph.facebook.com/v2.5'
|
||||
local fb_access_token = cred_data.fb_access_token
|
||||
|
||||
local makeOurDate = function(dateString)
|
||||
local pattern = '(%d+)%/(%d+)%/(%d+)'
|
||||
local pattern = "(%d+)%/(%d+)%/(%d+)"
|
||||
local month, day, year = dateString:match(pattern)
|
||||
return day..'.'..month..'.'..year
|
||||
end
|
||||
@ -43,17 +43,18 @@ function facebook:fb_post (id, story_id)
|
||||
|
||||
local from = data.from.name
|
||||
local message = data.message
|
||||
if not message then return nil end
|
||||
local name = data.name
|
||||
if data.link then
|
||||
link = '\n<a href="'..data.link..'">'..data.name..'</a>'
|
||||
else
|
||||
link = ''
|
||||
link = ""
|
||||
end
|
||||
|
||||
if data.story then
|
||||
story = ' ('..data.story..')'
|
||||
else
|
||||
story = ''
|
||||
story = ""
|
||||
end
|
||||
|
||||
local text = '<b>'..from..'</b>'..story..':\n'..message..'\n'..link
|
||||
@ -104,13 +105,13 @@ function facebook:facebook_info(name)
|
||||
if data.about then
|
||||
about = '\n'..data.about
|
||||
else
|
||||
about = ''
|
||||
about = ""
|
||||
end
|
||||
|
||||
if data.general_info then
|
||||
general_info = '\n'..data.general_info
|
||||
else
|
||||
general_info = ''
|
||||
general_info = ""
|
||||
end
|
||||
|
||||
if data.birthday and data.founded then
|
||||
@ -120,7 +121,7 @@ function facebook:facebook_info(name)
|
||||
elseif data.founded and not data.birthday then
|
||||
birth = '\nGegründet: '..data.founded
|
||||
else
|
||||
birth = ''
|
||||
birth = ""
|
||||
end
|
||||
|
||||
local text = '<b>'..name..'</b> ('..category..')<i>'..about..'</i>'..general_info..birth
|
||||
|
@ -1,5 +1,7 @@
|
||||
local forecast = {}
|
||||
|
||||
require("./miku/plugins/weather")
|
||||
|
||||
function forecast:init(config)
|
||||
if not cred_data.forecastio_apikey then
|
||||
print('Fehlender Key: forecastio_apikey.')
|
||||
@ -21,6 +23,12 @@ function forecast:init(config)
|
||||
"^(/forecasth)$",
|
||||
"^(/forecasth) (.*)$"
|
||||
}
|
||||
forecast.inline_triggers = {
|
||||
"^(f) (.+)$",
|
||||
"^(fh) (.+)$",
|
||||
"^(fh)$",
|
||||
"^(f)$"
|
||||
}
|
||||
forecast.doc = [[*
|
||||
]]..config.cmd_pat..[[f*: Wettervorhersage für deinen Wohnort _(/location set <Ort>)_
|
||||
*]]..config.cmd_pat..[[f* _<Ort>_: Wettervorhersage für diesen Ort
|
||||
@ -35,39 +43,26 @@ local BASE_URL = "https://api.forecast.io/forecast"
|
||||
local apikey = cred_data.forecastio_apikey
|
||||
local google_apikey = cred_data.google_apikey
|
||||
|
||||
function get_city_name(lat, lng)
|
||||
local city = redis:hget('telegram:cache:weather:pretty_names', lat..','..lng)
|
||||
if city then return city end
|
||||
local url = 'https://maps.googleapis.com/maps/api/geocode/json?latlng='..lat..','..lng..'&result_type=political&language=de&key='..google_apikey
|
||||
local res, code = https.request(url)
|
||||
if code ~= 200 then return 'Unbekannte Stadt' end
|
||||
local data = json.decode(res).results[1]
|
||||
local city = data.formatted_address
|
||||
print('Setting '..lat..','..lng..' in redis hash telegram:cache:weather:pretty_names to "'..city..'"')
|
||||
redis:hset('telegram:cache:weather:pretty_names', lat..','..lng, city)
|
||||
return city
|
||||
end
|
||||
|
||||
function get_condition_symbol(weather, n)
|
||||
if weather.data[n].icon == 'clear-day' then
|
||||
function forecast:get_condition_symbol(weather_data)
|
||||
if weather_data.icon == 'clear-day' then
|
||||
return '☀️'
|
||||
elseif weather.data[n].icon == 'clear-night' then
|
||||
elseif weather_data.icon == 'clear-night' then
|
||||
return '🌙'
|
||||
elseif weather.data[n].icon == 'rain' then
|
||||
elseif weather_data.icon == 'rain' then
|
||||
return '☔️'
|
||||
elseif weather.data[n].icon == 'snow' then
|
||||
elseif weather_data.icon == 'snow' then
|
||||
return '❄️'
|
||||
elseif weather.data[n].icon == 'sleet' then
|
||||
elseif weather_data.icon == 'sleet' then
|
||||
return '🌨'
|
||||
elseif weather.data[n].icon == 'wind' then
|
||||
elseif weather_data.icon == 'wind' then
|
||||
return '💨'
|
||||
elseif weather.data[n].icon == 'fog' then
|
||||
elseif weather_data.icon == 'fog' then
|
||||
return '🌫'
|
||||
elseif weather.data[n].icon == 'cloudy' then
|
||||
elseif weather_data.icon == 'cloudy' then
|
||||
return '☁️☁️'
|
||||
elseif weather.data[n].icon == 'partly-cloudy-day' then
|
||||
elseif weather_data.icon == 'partly-cloudy-day' then
|
||||
return '🌤'
|
||||
elseif weather.data[n].icon == 'partly-cloudy-night' then
|
||||
elseif weather_data.icon == 'partly-cloudy-night' then
|
||||
return '🌙☁️'
|
||||
else
|
||||
return ''
|
||||
@ -75,22 +70,34 @@ function get_condition_symbol(weather, n)
|
||||
end
|
||||
|
||||
function get_temp(weather, n, hourly)
|
||||
local weather_data = weather.data[n]
|
||||
if hourly then
|
||||
local temperature = string.gsub(round(weather.data[n].temperature, 1), "%.", ",")
|
||||
local condition = weather.data[n].summary
|
||||
return temperature..'°C | '..get_condition_symbol(weather, n)..' '..condition
|
||||
local temperature = string.gsub(round(weather_data.temperature, 1), "%.", ",")
|
||||
local condition = weather_data.summary
|
||||
return temperature..'°C | '..forecast:get_condition_symbol(weather_data)..' '..condition
|
||||
else
|
||||
local day = string.gsub(round(weather.data[n].temperatureMax, 1), "%.", ",")
|
||||
local night = string.gsub(round(weather.data[n].temperatureMin, 1), "%.", ",")
|
||||
local condition = weather.data[n].summary
|
||||
return '☀️ '..day..'°C | 🌙 '..night..'°C | '..get_condition_symbol(weather, n)..' '..condition
|
||||
local day = string.gsub(round(weather_data.temperatureMax, 1), "%.", ",")
|
||||
local night = string.gsub(round(weather_data.temperatureMin, 1), "%.", ",")
|
||||
local condition = weather_data.summary
|
||||
return '☀️ '..day..'°C | 🌙 '..night..'°C | '..forecast:get_condition_symbol(weather_data)..' '..condition
|
||||
end
|
||||
end
|
||||
|
||||
function forecast:get_forecast(lat, lng)
|
||||
function forecast:get_forecast(lat, lng, is_inline)
|
||||
print('Finde Wetter in '..lat..', '..lng)
|
||||
local text = redis:get('telegram:cache:forecast:'..lat..','..lng)
|
||||
if text then print('...aus dem Cache..') return text end
|
||||
local hash = 'telegram:cache:forecast:'..lat..','..lng
|
||||
local text = redis:hget(hash, 'text')
|
||||
if text then
|
||||
print('...aus dem Cache..')
|
||||
if is_inline then
|
||||
local ttl = redis:ttl(hash)
|
||||
local city = redis:hget(hash, 'city')
|
||||
local summary = redis:hget(hash, 'summary')
|
||||
return city, summary, text, ttl
|
||||
else
|
||||
return text
|
||||
end
|
||||
end
|
||||
|
||||
local url = BASE_URL..'/'..apikey..'/'..lat..','..lng..'?lang=de&units=si&exclude=currently,minutely,hourly,alerts,flags'
|
||||
|
||||
@ -100,43 +107,61 @@ function forecast:get_forecast(lat, lng)
|
||||
method = "GET",
|
||||
sink = ltn12.sink.table(response_body)
|
||||
}
|
||||
local ok, response_code, response_headers, response_status_line = https.request(request_constructor)
|
||||
local ok, response_code, response_headers = https.request(request_constructor)
|
||||
if not ok then return nil end
|
||||
local data = json.decode(table.concat(response_body))
|
||||
local ttl = string.sub(response_headers["cache-control"], 9)
|
||||
|
||||
|
||||
local weather = data.daily
|
||||
local weather = json.decode(table.concat(response_body)).daily
|
||||
local ttl = tonumber(string.sub(response_headers["cache-control"], 9))
|
||||
local city = get_city_name(lat, lng)
|
||||
local weather_summary = weather.summary
|
||||
|
||||
local header = '*Vorhersage für '..city..':*\n_'..weather.summary..'_\n'
|
||||
local header = '*Vorhersage für '..city..':*\n_'..weather_summary..'_\n'
|
||||
|
||||
local text = '*Heute:* '..get_temp(weather, 1)
|
||||
local text = text..'\n*Morgen:* '..get_temp(weather, 2)
|
||||
|
||||
for day in pairs(weather.data) do
|
||||
local weather_data = weather.data
|
||||
for day in pairs(weather_data) do
|
||||
if day > 2 then
|
||||
text = text..'\n*'..convert_timestamp(weather.data[day].time, '%a, %d.%m')..'*: '..get_temp(weather, day)
|
||||
text = text..'\n*'..convert_timestamp(weather_data[day].time, '%a, %d.%m')..'*: '..get_temp(weather, day)
|
||||
end
|
||||
end
|
||||
|
||||
local text = string.gsub(text, "Mon", "Mo")
|
||||
local text = string.gsub(text, "Tue", "Di")
|
||||
local text = string.gsub(text, "Wed", "Mi")
|
||||
local text = string.gsub(text, "Thu", "Do")
|
||||
local text = string.gsub(text, "Fri", "Fr")
|
||||
local text = string.gsub(text, "Sat", "Sa")
|
||||
local text = string.gsub(text, "Sun", "So")
|
||||
local text = text:gsub("Mon", "Mo")
|
||||
local text = text:gsub("Tue", "Di")
|
||||
local text = text:gsub("Wed", "Mi")
|
||||
local text = text:gsub("Thu", "Do")
|
||||
local text = text:gsub("Fri", "Fr")
|
||||
local text = text:gsub("Sat", "Sa")
|
||||
local text = text:gsub("Sun", "So")
|
||||
|
||||
cache_data('forecast', lat..','..lng, header..text, tonumber(ttl), 'key')
|
||||
print('Caching data...')
|
||||
redis:hset(hash, 'city', city)
|
||||
redis:hset(hash, 'summary', weather_summary)
|
||||
redis:hset(hash, 'text', header..text)
|
||||
redis:expire(hash, ttl)
|
||||
|
||||
return header..text
|
||||
if is_inline then
|
||||
return city, weather_summary, header..text, ttl
|
||||
else
|
||||
return header..text
|
||||
end
|
||||
end
|
||||
|
||||
function forecast:get_forecast_hourly(lat, lng)
|
||||
function forecast:get_forecast_hourly(lat, lng, is_inline)
|
||||
print('Finde stündliches Wetter in '..lat..', '..lng)
|
||||
local text = redis:get('telegram:cache:forecast:'..lat..','..lng..':hourly')
|
||||
if text then print('...aus dem Cache..') return text end
|
||||
local hash = 'telegram:cache:forecast:'..lat..','..lng..':hourly'
|
||||
local text = redis:hget(hash, 'text')
|
||||
if text then
|
||||
print('...aus dem Cache..')
|
||||
if is_inline then
|
||||
local ttl = redis:ttl(hash)
|
||||
local city = redis:hget(hash, 'city')
|
||||
local summary = redis:hget(hash, 'summary')
|
||||
return city, summary, text, ttl
|
||||
else
|
||||
return text
|
||||
end
|
||||
end
|
||||
|
||||
local url = BASE_URL..'/'..apikey..'/'..lat..','..lng..'?lang=de&units=si&exclude=currently,minutely,daily,alerts,flags'
|
||||
|
||||
@ -146,32 +171,67 @@ function forecast:get_forecast_hourly(lat, lng)
|
||||
method = "GET",
|
||||
sink = ltn12.sink.table(response_body)
|
||||
}
|
||||
local ok, response_code, response_headers, response_status_line = https.request(request_constructor)
|
||||
local ok, response_code, response_headers = https.request(request_constructor)
|
||||
if not ok then return nil end
|
||||
local data = json.decode(table.concat(response_body))
|
||||
local ttl = string.sub(response_headers["cache-control"], 9)
|
||||
|
||||
|
||||
local weather = data.hourly
|
||||
local weather = json.decode(table.concat(response_body)).hourly
|
||||
local ttl = tonumber(string.sub(response_headers["cache-control"], 9))
|
||||
local city = get_city_name(lat, lng)
|
||||
local weather_summary = weather.summary
|
||||
|
||||
local header = '*24-Stunden-Vorhersage für '..city..':*\n_'..weather.summary..'_'
|
||||
local header = '*24-Stunden-Vorhersage für '..city..':*\n_'..weather_summary..'_'
|
||||
local text = ""
|
||||
|
||||
for hour in pairs(weather.data) do
|
||||
local weather_data = weather.data
|
||||
for hour in pairs(weather_data) do
|
||||
if hour < 26 then
|
||||
text = text..'\n*'..convert_timestamp(weather.data[hour].time, '%H:%M Uhr')..'* | '..get_temp(weather, hour, true)
|
||||
text = text..'\n*'..convert_timestamp(weather_data[hour].time, '%H:%M Uhr')..'* | '..get_temp(weather, hour, true)
|
||||
end
|
||||
end
|
||||
|
||||
cache_data('forecast', lat..','..lng..':hourly', header..text, tonumber(ttl), 'key')
|
||||
print('Caching data...')
|
||||
redis:hset(hash, 'city', city)
|
||||
redis:hset(hash, 'summary', weather_summary)
|
||||
redis:hset(hash, 'text', header..text)
|
||||
redis:expire(hash, ttl)
|
||||
|
||||
return header..text
|
||||
if is_inline then
|
||||
return city, weather_summary, header..text, ttl
|
||||
else
|
||||
return header..text
|
||||
end
|
||||
end
|
||||
|
||||
function forecast:inline_callback(inline_query, config, matches)
|
||||
local user_id = inline_query.from.id
|
||||
if matches[2] then
|
||||
city = matches[2]
|
||||
is_personal = false
|
||||
else
|
||||
local set_location = get_location(user_id)
|
||||
is_personal = true
|
||||
if not set_location then
|
||||
city = 'Berlin, Deutschland'
|
||||
else
|
||||
city = set_location
|
||||
end
|
||||
end
|
||||
|
||||
local lat, lng = get_city_coordinates(city, config)
|
||||
if not lat and not lng then utilities.answer_inline_query(self, inline_query) return end
|
||||
if matches[1] == 'f' then
|
||||
title, description, text, ttl = forecast:get_forecast(lat, lng, true)
|
||||
else
|
||||
title, description, text, ttl = forecast:get_forecast_hourly(lat, lng, true)
|
||||
end
|
||||
if not title and not description and not text and not ttl then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
local text = text:gsub('\n', '\\n')
|
||||
local results = '[{"type":"article","id":"28062013","title":"'..title..'","description":"'..description..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/weather/cloudy.jpg","thumb_width":80,"thumb_height":80,"input_message_content":{"message_text":"'..text..'", "parse_mode":"Markdown"}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, ttl, is_personal)
|
||||
end
|
||||
|
||||
function forecast:action(msg, config, matches)
|
||||
local user_id = msg.from.id
|
||||
local city = get_location(user_id)
|
||||
|
||||
if matches[2] then
|
||||
city = matches[2]
|
||||
@ -184,23 +244,12 @@ function forecast:action(msg, config, matches)
|
||||
end
|
||||
end
|
||||
|
||||
local lat = redis:hget('telegram:cache:weather:'..string.lower(city), 'lat')
|
||||
local lng = redis:hget('telegram:cache:weather:'..string.lower(city), 'lng')
|
||||
local lat, lng = get_city_coordinates(city, config)
|
||||
if not lat and not lng then
|
||||
print('Koordinaten nicht eingespeichert, frage Google...')
|
||||
coords = utilities.get_coords(city, config)
|
||||
lat = coords.lat
|
||||
lng = coords.lon
|
||||
end
|
||||
|
||||
if not lat and not lng then
|
||||
utilities.send_reply(self, msg, '*Diesen Ort gibt es nicht!*', true)
|
||||
utilities.send_reply(self, msg, '*Diesen Ort gibt es nicht!*', true)
|
||||
return
|
||||
end
|
||||
|
||||
redis:hset('telegram:cache:weather:'..string.lower(city), 'lat', lat)
|
||||
redis:hset('telegram:cache:weather:'..string.lower(city), 'lng', lng)
|
||||
|
||||
if matches[1] == '/forecasth' or matches[1] == '/fh' then
|
||||
text = forecast:get_forecast_hourly(lat, lng)
|
||||
else
|
||||
|
@ -131,7 +131,7 @@ end
|
||||
function gImages:cache_result(results, text)
|
||||
local cache = {}
|
||||
for v in pairs(results) do
|
||||
table.insert(cache, results[v].link)
|
||||
cache[v] = results[v].link
|
||||
end
|
||||
for n, link in pairs(cache) do
|
||||
redis:hset('telegram:cache:gImages:'..link, 'mime', results[n].mime)
|
||||
|
@ -131,7 +131,7 @@ end
|
||||
function gImages_nsfw:cache_result(results, text)
|
||||
local cache = {}
|
||||
for v in pairs(results) do
|
||||
table.insert(cache, results[v].link)
|
||||
cache[v] = results[v].link
|
||||
end
|
||||
for n, link in pairs(cache) do
|
||||
redis:hset('telegram:cache:gImages_nsfw:'..link, 'mime', results[n].mime)
|
||||
|
@ -4,6 +4,9 @@ gMaps.command = 'loc <Ort>'
|
||||
|
||||
function gMaps:init(config)
|
||||
gMaps.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('[Ll][Oo][Cc]', true).table
|
||||
gMaps.inline_triggers = {
|
||||
"^[Ll][Oo][Cc] (.+)"
|
||||
}
|
||||
gMaps.doc = [[*
|
||||
]]..config.cmd_pat..[[loc* _<Ort>_: Sendet Ort via Google Maps]]
|
||||
end
|
||||
@ -16,22 +19,29 @@ function gMaps:get_staticmap(area, lat, lon)
|
||||
return file
|
||||
end
|
||||
|
||||
function gMaps:inline_callback(inline_query, config, matches)
|
||||
local place = matches[1]
|
||||
local coords = utilities.get_coords(place, config)
|
||||
if type(coords) == 'string' then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
local results = '[{"type":"venue","id":"10","latitude":'..coords.lat..',"longitude":'..coords.lon..',"title":"Ort","address":"'..coords.addr..'"}]'
|
||||
|
||||
utilities.answer_inline_query(self, inline_query, results, 10000)
|
||||
end
|
||||
|
||||
function gMaps:action(msg, config)
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
if msg.reply_to_message and msg.reply_to_message.text then
|
||||
input = msg.reply_to_message.text
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, gMaps.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
utilities.send_typing(self, msg.chat.id, 'find_location')
|
||||
local coords = utilities.get_coords(input, config)
|
||||
if type(coords) == 'string' then
|
||||
utilities.send_reply(self, msg, coords)
|
||||
return
|
||||
end
|
||||
local input = utilities.input_from_msg(msg)
|
||||
if not input then
|
||||
utilities.send_reply(self, msg, gMaps.doc, true)
|
||||
return
|
||||
end
|
||||
|
||||
utilities.send_typing(self, msg.chat.id, 'find_location')
|
||||
local coords = utilities.get_coords(input, config)
|
||||
if type(coords) == 'string' then
|
||||
utilities.send_reply(self, msg, coords)
|
||||
return
|
||||
end
|
||||
|
||||
utilities.send_location(self, msg.chat.id, coords.lat, coords.lon, msg.message_id)
|
||||
utilities.send_photo(self, msg.chat.id, gMaps:get_staticmap(input, coords.lat, coords.lon), nil, msg.message_id)
|
||||
|
@ -51,14 +51,10 @@ function gSearch:stringlinks(results, stats)
|
||||
end
|
||||
|
||||
function gSearch:action(msg, config)
|
||||
local input = utilities.input(msg.text)
|
||||
local input = utilities.input_from_msg(msg)
|
||||
if not input then
|
||||
if msg.reply_to_message and msg.reply_to_message.text then
|
||||
input = msg.reply_to_message.text
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, gSearch.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
utilities.send_reply(self, msg, gImages.doc, true)
|
||||
return
|
||||
end
|
||||
|
||||
local results, stats = gSearch:googlethat(input, onfig)
|
||||
|
@ -1,6 +1,5 @@
|
||||
-- YOU NEED THE FOLLOWING FOLDERS: photo, document, video, voice
|
||||
-- PLEASE ADJUST YOUR PATH BELOW
|
||||
-- Save your bot api key in redis set telegram:credentials!
|
||||
|
||||
local media_download = {}
|
||||
|
||||
@ -34,7 +33,7 @@ function media_download:download_to_file_permanently(url, file_name)
|
||||
return true
|
||||
end
|
||||
|
||||
function media_download:pre_process(msg, self)
|
||||
function media_download:pre_process(msg, self, config)
|
||||
if msg.photo then
|
||||
local lv = #msg.photo -- find biggest photo, always the last value
|
||||
file_id = msg.photo[lv].file_id
|
||||
@ -89,7 +88,7 @@ function media_download:pre_process(msg, self)
|
||||
end
|
||||
|
||||
-- Construct what we want
|
||||
local download_url = 'https://api.telegram.org/file/bot'..cred_data.bot_api_key..'/'..request.result.file_path
|
||||
local download_url = 'https://api.telegram.org/file/bot'..config.bot_api_key..'/'..request.result.file_path
|
||||
local ok = media_download:download_to_file_permanently(download_url, file_path)
|
||||
if not ok then
|
||||
print('Download fehlgeschlagen!')
|
||||
|
@ -30,12 +30,14 @@ function giphy:inline_callback(inline_query, config, matches)
|
||||
else
|
||||
data = giphy:get_gifs(matches[2])
|
||||
end
|
||||
if not data then return end
|
||||
if not data[1] then return end
|
||||
if not data then utilities.answer_inline_query(self, inline_query) return end
|
||||
if not data[1] then utilities.answer_inline_query(self, inline_query) return end
|
||||
local results = '['
|
||||
local id = 450
|
||||
|
||||
for n in pairs(data) do
|
||||
results = results..'{"type":"mpeg4_gif","id":"'..math.random(100000000000000000)..'","mpeg4_url":"'..data[n].images.original.mp4..'","thumb_url":"'..data[n].images.fixed_height.url..'","mpeg4_width":'..data[n].images.original.width..',"mp4_height":'..data[n].images.original.height..'}'
|
||||
results = results..'{"type":"mpeg4_gif","id":"'..id..'","mpeg4_url":"'..data[n].images.original.mp4..'","thumb_url":"'..data[n].images.fixed_height.url..'","mpeg4_width":'..data[n].images.original.width..',"mp4_height":'..data[n].images.original.height..'}'
|
||||
id = id+1
|
||||
if n < #data then
|
||||
results = results..','
|
||||
end
|
||||
|
@ -25,9 +25,9 @@ end
|
||||
function googl:inline_callback(inline_query, config, matches)
|
||||
local shorturl = matches[1]
|
||||
local text, longUrl = googl:send_googl_info(shorturl)
|
||||
if not longUrl then return end
|
||||
if not longUrl then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
local results = '[{"type":"article","id":"'..math.random(100000000000000000)..'","title":"Verlängerte URL","description":"'..longUrl..'","url":"'..longUrl..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/generic/internet.jpg","thumb_width":165,"thumb_height":150,"hide_url":true,"input_message_content":{"message_text":"'..text..'"}}]'
|
||||
local results = '[{"type":"article","id":"9","title":"Verlängerte URL","description":"'..longUrl..'","url":"'..longUrl..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/generic/internet.jpg","thumb_width":165,"thumb_height":150,"hide_url":true,"input_message_content":{"message_text":"'..text..'"}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, 1)
|
||||
end
|
||||
|
||||
|
@ -5,6 +5,13 @@ gps.command = 'gps <Breitengrad>,<Längengrad>'
|
||||
function gps:init(config)
|
||||
gps.triggers = {
|
||||
"^/[Gg][Pp][Ss] ([^,]*)[,%s]([^,]*)$",
|
||||
"google.de/maps/@([^,]*)[,%s]([^,]*)",
|
||||
"google.com/maps/@([^,]*)[,%s]([^,]*)",
|
||||
"google.de/maps/place/@([^,]*)[,%s]([^,]*)",
|
||||
"google.com/maps/place/@([^,]*)[,%s]([^,]*)"
|
||||
}
|
||||
gps.inline_triggers = {
|
||||
"^[Gg][Pp][Ss] ([^,]*)[,%s]([^,]*)$",
|
||||
"google.de/maps/@([^,]*)[,%s]([^,]*)",
|
||||
"google.com/maps/@([^,]*)[,%s]([^,]*)",
|
||||
"google.de/maps/place/@([^,]*)[,%s]([^,]*)",
|
||||
@ -14,6 +21,15 @@ function gps:init(config)
|
||||
]]..config.cmd_pat..[[gps* _<Breitengrad>_,_<Längengrad>_: Sendet Karte mit diesen Koordinaten]]
|
||||
end
|
||||
|
||||
function gps:inline_callback(inline_query, config, matches)
|
||||
local lat = matches[1]
|
||||
local lon = matches[2]
|
||||
|
||||
local results = '[{"type":"location","id":"8","latitude":'..lat..',"longitude":'..lon..',"title":"Standort"}]'
|
||||
|
||||
utilities.answer_inline_query(self, inline_query, results, 10000)
|
||||
end
|
||||
|
||||
function gps:action(msg, config, matches)
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local lat = matches[1]
|
||||
|
@ -5,48 +5,81 @@ local help = {}
|
||||
local help_text
|
||||
|
||||
function help:init(config)
|
||||
help.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('[Hh][Ii][Ll][Ff][Ee]', true):t('[Hh][Ee][Ll][Pp]', true).table
|
||||
help.triggers = {
|
||||
"^/[Hh][Ii][Ll][Ff][Ee] (.+)",
|
||||
"^/[Hh][Ee][Ll][Pp] (.+)",
|
||||
"^/(hilfe)_(.+)",
|
||||
"^/[Hh][Ii][Ll][Ff][Ee]$"
|
||||
}
|
||||
help.inline_triggers = {
|
||||
"^[Hh][Ii][Ll][Ff][Ee] (.+)",
|
||||
"^[Hh][Ee][Ll][Pp] (.+)"
|
||||
}
|
||||
end
|
||||
|
||||
function help:action(msg, config)
|
||||
function help:inline_callback(inline_query, config, matches)
|
||||
local query = matches[1]
|
||||
|
||||
for n=1, #self.plugins do
|
||||
local plugin = self.plugins[n]
|
||||
if plugin.command and utilities.get_word(plugin.command, 1) == query and plugin.doc then
|
||||
local doc = plugin.doc
|
||||
local doc = doc:gsub('"', '\\"')
|
||||
local doc = doc:gsub('\\n', '\\\n')
|
||||
local chosen_plugin = utilities.get_word(plugin.command, 1)
|
||||
local results = '[{"type":"article","id":"9","title":"Hilfe für '..chosen_plugin..'","description":"Hilfe für das Plugin \\"'..chosen_plugin..'\\" wird gepostet.","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/help/hilfe.jpg","input_message_content":{"message_text":"'..doc..'","parse_mode":"Markdown"}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, 600, nil, nil, 'Hilfe anzeigen', 'hilfe_'..chosen_plugin)
|
||||
end
|
||||
end
|
||||
utilities.answer_inline_query(self, inline_query)
|
||||
end
|
||||
|
||||
function help:action(msg, config, matches)
|
||||
if matches[2] then
|
||||
input = matches[2]
|
||||
elseif matches[1] ~= '/hilfe' then
|
||||
input = matches[1]
|
||||
else
|
||||
input = nil
|
||||
end
|
||||
|
||||
|
||||
-- Attempts to send the help message via PM.
|
||||
-- If msg is from a group, it tells the group whether the PM was successful.
|
||||
if not input then
|
||||
local commandlist = {}
|
||||
help_text = '*Verfügbare Befehle:*\n• '..config.cmd_pat
|
||||
|
||||
for _,plugin in ipairs(self.plugins) do
|
||||
if plugin.command then
|
||||
|
||||
table.insert(commandlist, plugin.command)
|
||||
end
|
||||
local help_text = '*Verfügbare Befehle:*\n• '..config.cmd_pat
|
||||
for n=1, #self.plugins do
|
||||
local plugin = self.plugins[n]
|
||||
if plugin.command then
|
||||
commandlist[#commandlist+1] = plugin.command
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(commandlist, 'hilfe [Befehl]')
|
||||
commandlist[#commandlist+1] = 'hilfe [Befehl]'
|
||||
table.sort(commandlist)
|
||||
help_text = help_text .. table.concat(commandlist, '\n• '..config.cmd_pat) .. '\nParameter: <benötigt> [optional]'
|
||||
local help_text = help_text .. table.concat(commandlist, '\n• '..config.cmd_pat) .. '\nParameter: <benötigt> [optional]'
|
||||
local help_text = help_text:gsub('%[', '\\[')
|
||||
|
||||
help_text = help_text:gsub('%[', '\\[')
|
||||
local input = utilities.input(msg.text_lower)
|
||||
|
||||
-- Attempts to send the help message via PM.
|
||||
-- If msg is from a group, it tells the group whether the PM was successful.
|
||||
if not input then
|
||||
local res = utilities.send_message(self, msg.from.id, help_text, true, nil, true)
|
||||
if not res then
|
||||
utilities.send_reply(self, msg, 'Bitte schreibe mir zuerst [privat](http://telegram.me/' .. self.info.username .. '?start=help) für eine Hilfe.', true)
|
||||
elseif msg.chat.type ~= 'private' then
|
||||
utilities.send_reply(self, msg, 'Ich habe dir die Hilfe per PN gesendet!.')
|
||||
end
|
||||
return
|
||||
local res = utilities.send_message(self, msg.from.id, help_text, true, nil, true)
|
||||
if not res then
|
||||
utilities.send_reply(self, msg, 'Bitte schreibe mir zuerst [privat](http://telegram.me/' .. self.info.username .. '?start=help) für eine Hilfe.', true)
|
||||
elseif msg.chat.type ~= 'private' then
|
||||
utilities.send_reply(self, msg, 'Ich habe dir die Hilfe privat gesendet!.')
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
for _,plugin in ipairs(self.plugins) do
|
||||
if plugin.command and utilities.get_word(plugin.command, 1) == input and plugin.doc then
|
||||
local output = '*Hilfe für* _' .. utilities.get_word(plugin.command, 1) .. '_ *:*' .. plugin.doc
|
||||
utilities.send_message(self, msg.chat.id, output, true, nil, true)
|
||||
return
|
||||
end
|
||||
for n=1, #self.plugins do
|
||||
local plugin = self.plugins[n]
|
||||
if plugin.command and utilities.get_word(plugin.command, 1) == input and plugin.doc then
|
||||
local output = '*Hilfe für* _' .. utilities.get_word(plugin.command, 1) .. '_ *:*' .. plugin.doc
|
||||
utilities.send_message(self, msg.chat.id, output, true, nil, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
utilities.send_reply(self, msg, 'Für diesen Befehl gibt es keine Hilfe.')
|
||||
utilities.send_reply(self, msg, 'Für diesen Befehl gibt es keine Hilfe.')
|
||||
end
|
||||
|
||||
return help
|
@ -3,11 +3,16 @@ local id = {}
|
||||
id.command = 'id'
|
||||
|
||||
function id:init(config)
|
||||
id.triggers = {
|
||||
id.triggers = {
|
||||
"^/id$",
|
||||
"^/ids? (chat)$"
|
||||
}
|
||||
id.doc = [[```Zeige dir deine ID und die IDs aller Gruppenmitglieder an.``]]
|
||||
}
|
||||
|
||||
id.inline_triggers = {
|
||||
"^id$"
|
||||
}
|
||||
|
||||
id.doc = [[```Zeige dir deine ID und die IDs aller Gruppenmitglieder an.``]]
|
||||
end
|
||||
|
||||
function id:get_member_count(self, msg, chat_id)
|
||||
@ -41,7 +46,15 @@ function id:get_user(user_id, chat_id)
|
||||
return user_info
|
||||
end
|
||||
|
||||
function id:action(msg)
|
||||
function id:inline_callback(inline_query, config, matches)
|
||||
local id = tostring(inline_query.from.id)
|
||||
local name = utilities.build_name(inline_query.from.first_name, inline_query.from.last_name)
|
||||
|
||||
local results = '[{"type":"article","id":"30","title":"Deine Telegram-ID ist:","description":"'..id..'","input_message_content":{"message_text":"<b>'..name..'</b>: <code>'..id..'</code>","parse_mode":"HTML"}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, 10000, true)
|
||||
end
|
||||
|
||||
function id:action(msg, config, matches)
|
||||
|
||||
if matches[1] == "/id" then
|
||||
if msg.reply_to_message then
|
||||
@ -86,7 +99,7 @@ function id:action(msg)
|
||||
for i = 1, #users do
|
||||
local user_id = users[i]
|
||||
local user_info = id:get_user(user_id, chat_id)
|
||||
table.insert(users_info, user_info)
|
||||
users_info[#users_info+1] = user_info
|
||||
end
|
||||
|
||||
-- get all administrators and the creator
|
||||
@ -94,7 +107,7 @@ function id:action(msg)
|
||||
local admins = {}
|
||||
for num in pairs(administrators.result) do
|
||||
if administrators.result[num].status ~= 'creator' then
|
||||
table.insert(admins, tostring(administrators.result[num].user.id))
|
||||
admins[#admins+1] = tostring(administrators.result[num].user.id)
|
||||
else
|
||||
creator_id = administrators.result[num].user.id
|
||||
end
|
||||
|
@ -5,7 +5,7 @@ images.triggers = {
|
||||
"(https?://[%w-_%%%.%?%.:,/%+=~&%[%]]+%.[Jj][Pp][Ee]?[Gg])$"
|
||||
}
|
||||
|
||||
function images:action(msg)
|
||||
function images:action(msg, config, matches)
|
||||
local url = matches[1]
|
||||
local file, last_modified, nocache = get_cached_file(url, nil, msg.chat.id, 'upload_photo', self)
|
||||
local result = utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
|
@ -3,51 +3,99 @@ local imdb = {}
|
||||
imdb.command = 'imdb <query>'
|
||||
|
||||
function imdb:init(config)
|
||||
imdb.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('[Ii][Mm][Dd][Bb]', true).table
|
||||
imdb.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('imdb', true).table
|
||||
imdb.inline_triggers = {
|
||||
"^imdb (.+)"
|
||||
}
|
||||
imdb.doc = [[*
|
||||
]]..config.cmd_pat..[[imdb* _<Film>_
|
||||
Sucht einen _Film_ bei IMDb]]
|
||||
end
|
||||
|
||||
local BASE_URL = 'https://www.omdbapi.com'
|
||||
|
||||
function imdb:get_imdb_info(id)
|
||||
local url = BASE_URL..'/?i='..id
|
||||
local res, code = https.request(url)
|
||||
if code ~= 200 then return end
|
||||
local movie_info = json.decode(res)
|
||||
return movie_info
|
||||
end
|
||||
|
||||
function imdb:inline_callback(inline_query, config, matches)
|
||||
local query = matches[1]
|
||||
local url = BASE_URL..'/?s='..URL.escape(query)
|
||||
local res, code = https.request(url)
|
||||
if code ~= 200 then utilities.answer_inline_query(self, inline_query) return end
|
||||
local data = json.decode(res)
|
||||
if data.Response ~= "True" then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
local results = '['
|
||||
local id = 500
|
||||
for num in pairs(data.Search) do
|
||||
if num > 5 then
|
||||
break;
|
||||
end
|
||||
local imdb_id = data.Search[num].imdbID
|
||||
local movie_info = imdb:get_imdb_info(imdb_id)
|
||||
local title = movie_info.Title
|
||||
local year = movie_info.Year
|
||||
local text = '<b>'..movie_info.Title.. ' ('..movie_info.Year..')</b> von '..movie_info.Director..'\\n'..string.gsub(movie_info.imdbRating, '%.', ',')..'/10 | '..movie_info.Runtime..' | '.. movie_info.Genre
|
||||
if movie_info.Plot then
|
||||
text = text..'\\n<i>'..movie_info.Plot..'</i>'
|
||||
description = movie_info.Plot
|
||||
else
|
||||
description = 'Keine Beschreibung verfügbar'
|
||||
end
|
||||
local text = text:gsub('"', '\\"')
|
||||
local text = text:gsub("'", "\'")
|
||||
local description = description:gsub('"', '\\"')
|
||||
local description = description:gsub("'", "\'")
|
||||
|
||||
if movie_info.Poster == "N/A" then
|
||||
img_url = 'https://anditest.perseus.uberspace.de/inlineQuerys/imdb/logo.jpg'
|
||||
else
|
||||
img_url = movie_info.Poster
|
||||
end
|
||||
results = results..'{"type":"article","id":"'..id..'","title":"'..title..' ('..year..')","description":"'..description..'","url":"http://imdb.com/title/'..imdb_id..'","hide_url":true,"thumb_url":"'..img_url..'","reply_markup":{"inline_keyboard":[[{"text":"IMDb-Seite aufrufen","url":"http://imdb.com/title/'..imdb_id..'"}]]},"input_message_content":{"message_text":"'..text..'","parse_mode":"HTML"}},'
|
||||
id = id+1
|
||||
end
|
||||
|
||||
local results = results:sub(0, -2)
|
||||
local results = results..']'
|
||||
utilities.answer_inline_query(self, inline_query, results, 10000)
|
||||
end
|
||||
|
||||
function imdb:action(msg, config)
|
||||
local input = utilities.input_from_msg(msg)
|
||||
if not input then
|
||||
utilities.send_reply(self, msg, imdb.doc, true)
|
||||
return
|
||||
end
|
||||
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
if msg.reply_to_message and msg.reply_to_message.text then
|
||||
input = msg.reply_to_message.text
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, imdb.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
local url = BASE_URL..'/?t='..URL.escape(input)
|
||||
local jstr, res = https.request(url)
|
||||
if res ~= 200 then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
return
|
||||
end
|
||||
|
||||
local url = 'http://www.omdbapi.com/?t=' .. URL.escape(input)
|
||||
local jdat = json.decode(jstr)
|
||||
if jdat.Response ~= 'True' then
|
||||
utilities.send_reply(self, msg, config.errors.results)
|
||||
return
|
||||
end
|
||||
|
||||
local jstr, res = http.request(url)
|
||||
if res ~= 200 then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
return
|
||||
end
|
||||
local output = '<b>'..jdat.Title.. ' ('..jdat.Year..')</b> von '..jdat.Director..'\n'
|
||||
output = output..string.gsub(jdat.imdbRating, '%.', ',')..'/10 | '..jdat.Runtime..' | '.. jdat.Genre..'\n'
|
||||
output = output..'<i>' .. jdat.Plot .. '</i>'
|
||||
|
||||
local jdat = json.decode(jstr)
|
||||
|
||||
if jdat.Response ~= 'True' then
|
||||
utilities.send_reply(self, msg, config.errors.results)
|
||||
return
|
||||
end
|
||||
|
||||
local output = '*' .. jdat.Title .. ' ('.. jdat.Year ..')* von '..jdat.Director..'\n'
|
||||
output = output .. string.gsub(jdat.imdbRating, '%.', ',') ..'/10 | '.. jdat.Runtime ..' | '.. jdat.Genre ..'\n'
|
||||
output = output .. '_' .. jdat.Plot .. '_\n'
|
||||
output = output .. '[IMDb-Seite besuchen](http://imdb.com/title/' .. jdat.imdbID .. ')'
|
||||
|
||||
utilities.send_message(self, msg.chat.id, output, true, nil, true)
|
||||
|
||||
if jdat.Poster ~= "N/A" then
|
||||
local file = download_to_file(jdat.Poster)
|
||||
utilities.send_photo(self, msg.chat.id, file)
|
||||
end
|
||||
utilities.send_reply(self, msg, output, 'HTML', '{"inline_keyboard":[[{"text":"IMDb-Seite aufrufen","url":"http://imdb.com/title/'.. jdat.imdbID..'"}]]}')
|
||||
|
||||
if jdat.Poster ~= "N/A" then
|
||||
local file = download_to_file(jdat.Poster)
|
||||
utilities.send_photo(self, msg.chat.id, file)
|
||||
end
|
||||
end
|
||||
|
||||
return imdb
|
@ -1,7 +1,5 @@
|
||||
local media = {}
|
||||
|
||||
mimetype = (loadfile "./miku/mimetype.lua")()
|
||||
|
||||
media.triggers = {
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(gif))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(mp4))$",
|
||||
@ -23,10 +21,10 @@ media.triggers = {
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(webp))$"
|
||||
}
|
||||
|
||||
function media:action(msg)
|
||||
function media:action(msg, config, matches)
|
||||
local url = matches[1]
|
||||
local ext = matches[2]
|
||||
local mime_type = mimetype.get_content_type_no_sub(ext)
|
||||
local mime_type = mime.get_content_type_no_sub(ext)
|
||||
local receiver = msg.chat.id
|
||||
|
||||
if mime_type == 'audio' then
|
||||
@ -41,19 +39,14 @@ function media:action(msg)
|
||||
if not file then return end
|
||||
|
||||
if ext == 'gif' then
|
||||
print('Sende GIF')
|
||||
result = utilities.send_document(self, receiver, file, nil, msg.message_id)
|
||||
elseif ext == 'ogg' then
|
||||
print('Sende OGG')
|
||||
result = utilities.send_voice(self, receiver, file, nil, msg.message_id)
|
||||
elseif mime_type == 'audio' then
|
||||
print('Sende Audio')
|
||||
result = utilities.send_audio(self, receiver, file, nil, msg.message_id)
|
||||
elseif mime_type == 'video' then
|
||||
print('Sende Video')
|
||||
result = utilities.send_video(self, receiver, file, nil, msg.message_id)
|
||||
else
|
||||
print('Sende Datei')
|
||||
result = utilities.send_document(self, receiver, file, nil, msg.message_id)
|
||||
end
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
local patterns = {}
|
||||
|
||||
patterns.triggers = {
|
||||
'^/?s/.-/.-$'
|
||||
}
|
||||
function patterns:init(config)
|
||||
patterns.command = 's/<Pattern>/<Ersetzung>'
|
||||
patterns.triggers = {
|
||||
config.cmd_pat .. '?s/.-/.-$'
|
||||
}
|
||||
end
|
||||
|
||||
function patterns:action(msg)
|
||||
if not msg.reply_to_message then return true end
|
||||
|
@ -5,12 +5,12 @@ local bot = require('miku.bot')
|
||||
function plugin_manager:init(config)
|
||||
plugin_manager.triggers = {
|
||||
"^/plugins$",
|
||||
"^/plugins? (enable) ([%w_%.%-]+) (chat) (%d+)$",
|
||||
"^/plugins? (enable) ([%w_%.%-]+) (chat)$",
|
||||
"^/plugins? (disable) ([%w_%.%-]+) (chat) (%d+)$",
|
||||
"^/plugins? (disable) ([%w_%.%-]+) (chat)$",
|
||||
"^/plugins? (enable) ([%w_%.%-]+)$",
|
||||
"^/plugins? (disable) ([%w_%.%-]+)$",
|
||||
"^/plugins? (enable) ([%w_%.%-]+) (chat) (%d+)",
|
||||
"^/plugins? (enable) ([%w_%.%-]+) (chat)",
|
||||
"^/plugins? (disable) ([%w_%.%-]+) (chat) (%d+)",
|
||||
"^/plugins? (disable) ([%w_%.%-]+) (chat)",
|
||||
"^/plugins? (reload)$",
|
||||
"^/(reload)$"
|
||||
}
|
||||
|
39
miku/plugins/post_photo.lua
Normal file
39
miku/plugins/post_photo.lua
Normal file
@ -0,0 +1,39 @@
|
||||
-- This plugin goes through every message with a document and if the document is an image,
|
||||
-- it downloads the file and resends it as image
|
||||
|
||||
local post_photo = {}
|
||||
|
||||
post_photo.triggers = {
|
||||
'/nil'
|
||||
}
|
||||
|
||||
function post_photo:pre_process(msg, self, config)
|
||||
if not msg.document then return msg end -- Ignore
|
||||
local mime_type = msg.document.mime_type
|
||||
local valid_mimetypes = {['image/jpeg'] = true, ['image/png'] = true, ['image/bmp'] = true}
|
||||
if not valid_mimetypes[mime_type] then return msg end
|
||||
|
||||
local file_id = msg.document.file_id
|
||||
local file_size = msg.document.file_size
|
||||
if file_size > 19922944 then
|
||||
print('File is over 20 MB - can\'t download :(')
|
||||
return
|
||||
end
|
||||
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
-- Saving file to the Telegram Cloud
|
||||
local request = bindings.request(self, 'getFile', {
|
||||
file_id = file_id
|
||||
} )
|
||||
|
||||
local download_url = 'https://api.telegram.org/file/bot'..config.bot_api_key..'/'..request.result.file_path
|
||||
local file = download_to_file(download_url, msg.file_name)
|
||||
utilities.send_photo(self, msg.chat.id, file, msg.caption, msg.message_id)
|
||||
|
||||
return msg
|
||||
end
|
||||
|
||||
function post_photo:action(msg)
|
||||
end
|
||||
|
||||
return post_photo
|
@ -4,41 +4,73 @@ preview.command = 'preview <link>'
|
||||
|
||||
function preview:init(config)
|
||||
preview.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('preview', true).table
|
||||
preview.doc = [[```
|
||||
]]..config.cmd_pat..[[preview <link>
|
||||
Returns a full-message, "unlinked" preview.
|
||||
```]]
|
||||
preview.inline_triggers = {
|
||||
"^pr (https?://[%w-_%.%?%.:/%+=&%~%%#]+)$"
|
||||
}
|
||||
preview.doc = [[*
|
||||
]]..config.cmd_pat..[[preview* _<URL>_
|
||||
Erstellt einen Preview-Link]]
|
||||
end
|
||||
|
||||
function preview:inline_callback(inline_query, config, matches)
|
||||
local preview_url = matches[1]
|
||||
local res, code = https.request('https://brawlbot.tk/apis/simple_meta_api/?url='..URL.escape(preview_url))
|
||||
if code ~= 200 then utilities.answer_inline_query(self, inline_query) return end
|
||||
local data = json.decode(res)
|
||||
if data.remote_code >= 400 then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
if data.title then
|
||||
title = data.title
|
||||
else
|
||||
title = 'Kein Titel'
|
||||
end
|
||||
|
||||
if data.description then
|
||||
description = data.description
|
||||
description_in_text = '\n'..description
|
||||
else
|
||||
description_in_text = ''
|
||||
description = 'Keine Beschreibung verfügbar'
|
||||
end
|
||||
|
||||
if data.only_name then
|
||||
only_name = data.only_name
|
||||
else
|
||||
only_name = preview_url:match('^%w+://([^/]+)') -- we only need the domain
|
||||
end
|
||||
|
||||
local message_text = '<b>'..title..'</b>'..description_in_text..'\n— '..only_name
|
||||
|
||||
local results = '[{"type":"article","id":"77","title":"'..title..'","description":"'..description..'","url":"'..preview_url..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/generic/internet.jpg","thumb_width":150,"thumb_height":150,"hide_url":true,"reply_markup":{"inline_keyboard":[[{"text":"Webseite aufrufen","url":"'..preview_url..'"}]]},"input_message_content":{"message_text":"'..message_text..'","parse_mode":"HTML","disable_web_page_preview":true}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, 3600, true)
|
||||
end
|
||||
|
||||
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
|
||||
utilities.send_message(self, msg.chat.id, preview.doc, true, nil, true)
|
||||
return
|
||||
end
|
||||
local res = http.request(input)
|
||||
if not res then
|
||||
utilities.send_reply(self, msg, 'Bitte gebe einen validen Link an.')
|
||||
return
|
||||
end
|
||||
|
||||
input = utilities.get_word(input, 1)
|
||||
if not input:match('^https?://.+') then
|
||||
input = 'http://' .. input
|
||||
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)
|
||||
if res:len() == 0 then
|
||||
utilities.send_reply(self, msg, 'Sorry, dieser Link lässt uns keine Vorschau erstellen.')
|
||||
return
|
||||
end
|
||||
|
||||
-- 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
|
||||
|
||||
return preview
|
@ -71,11 +71,13 @@ end
|
||||
|
||||
function qr:inline_callback(inline_query, config, matches)
|
||||
local text = matches[1]
|
||||
if string.len(text) > 200 then return end
|
||||
if string.len(text) > 200 then utilities.answer_inline_query(self, inline_query) return end
|
||||
local image_url = qr:qr(text, nil, nil, 'jpg')
|
||||
if not image_url then return end
|
||||
if not image_url then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
local results = '[{"type":"photo","id":"'..math.random(100000000000000000)..'","photo_url":"'..image_url..'","thumb_url":"'..image_url..'","photo_width":600,"photo_height":600,"caption":"'..text..'"},'
|
||||
local id = 600
|
||||
|
||||
local results = '[{"type":"photo","id":"'..id..'","photo_url":"'..image_url..'","thumb_url":"'..image_url..'","photo_width":600,"photo_height":600,"caption":"'..text..'"},'
|
||||
|
||||
local i = 0
|
||||
while i < 29 do
|
||||
@ -83,7 +85,8 @@ function qr:inline_callback(inline_query, config, matches)
|
||||
local color = math.random(255)
|
||||
local bgcolor = math.random(255)
|
||||
local image_url = qr:qr(text, color, bgcolor, 'jpg')
|
||||
results = results..'{"type":"photo","id":"'..math.random(100000000000000000)..'","photo_url":"'..image_url..'","thumb_url":"'..image_url..'","photo_width":600,"photo_height":600,"caption":"'..text..'"}'
|
||||
id = id+1
|
||||
results = results..'{"type":"photo","id":"'..id..'","photo_url":"'..image_url..'","thumb_url":"'..image_url..'","photo_width":600,"photo_height":600,"caption":"'..text..'"}'
|
||||
if i < 29 then
|
||||
results = results..','
|
||||
end
|
||||
|
@ -7,88 +7,79 @@ function remind:init(config)
|
||||
|
||||
remind.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('remind', true).table
|
||||
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
|
||||
|
||||
function remind:action(msg)
|
||||
-- Ensure there are arguments. If not, send doc.
|
||||
function remind:action(msg, config)
|
||||
local input = utilities.input(msg.text)
|
||||
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
|
||||
end
|
||||
|
||||
-- Ensure first arg is a number. If not, send doc.
|
||||
local duration = utilities.get_word(input, 1)
|
||||
if not tonumber(duration) then
|
||||
utilities.send_message(self, msg.chat.id, remind.doc, true, msg.message_id, true)
|
||||
local duration = tonumber(utilities.get_word(input, 1))
|
||||
if not duration then
|
||||
utilities.send_reply(self, msg, remind.doc, true)
|
||||
return
|
||||
end
|
||||
|
||||
-- Duration must be between one minute and one day (approximately).
|
||||
duration = tonumber(duration)
|
||||
if duration < 1 then
|
||||
duration = 1
|
||||
elseif duration > 1440 then
|
||||
duration = 1440
|
||||
elseif duration > config.remind.max_duration then
|
||||
duration = config.remind.max_duration
|
||||
end
|
||||
|
||||
-- Ensure there is a second arg.
|
||||
local message = utilities.input(input)
|
||||
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
|
||||
|
||||
-- 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
|
||||
utilities.send_reply(self, msg, 'Diese Gruppe hat schon zehn Erinnerungen!')
|
||||
return
|
||||
elseif msg.chat.type == 'private' and utilities.table_size(self.database.reminders[msg.chat.id_str]) > 49 then
|
||||
utilities.send_reply(msg, 'Du hast schon 50 Erinnerungen!')
|
||||
if #message > config.remind.max_length then
|
||||
utilities.send_reply(self, msg, 'Die maximale Länge einer Erinnerung ist ' .. config.remind.max_length .. '.')
|
||||
return
|
||||
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.'
|
||||
local chat_id_str = tostring(msg.chat.id)
|
||||
local output
|
||||
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[chat_id_str]) >= config.remind.max_reminders_private then
|
||||
output = 'Sorry, du kannst keine Erinnerungen mehr hinzufügen.'
|
||||
elseif msg.chat.type ~= 'private' and utilities.table_size(self.database.reminders[chat_id_str]) >= config.remind.max_reminders_group then
|
||||
output = 'Sorry, diese Gruppe kann keine Erinnerungen mehr hinzufügen.'
|
||||
else
|
||||
-- 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
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
end
|
||||
|
||||
function remind:cron()
|
||||
function remind:cron(config)
|
||||
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
|
||||
for k, reminder in pairs(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 = '*ERINNERUNG:*\n"' .. utilities.md_escape(reminder.message) .. '"'
|
||||
local res = utilities.send_message(self, chat_id, output, true, nil, true)
|
||||
-- If the message fails to send, save it for later.
|
||||
if not res then
|
||||
table.insert(new_group, reminder)
|
||||
-- If the message fails to send, save it for later (if enabled in config).
|
||||
if res or not config.remind.persist then
|
||||
group[k] = nil
|
||||
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
|
||||
|
||||
|
@ -40,14 +40,14 @@ function respond:inline_callback(inline_query, config, matches)
|
||||
elseif string.match(text, "[Nn][Bb][Cc]") or string.match(text, "[Ii][Dd][Cc]") or string.match(text, "[Kk][Aa]") or string.match(text, "[Ii][Dd][Kk]") then
|
||||
face = '¯\\\\\\_(ツ)_/¯'
|
||||
end
|
||||
results = '[{"type":"article","id":"'..math.random(100000000000000000)..'","title":"'..face..'","input_message_content":{"message_text":"'..face..'"}}]'
|
||||
results = '[{"type":"article","id":"8","title":"'..face..'","input_message_content":{"message_text":"'..face..'"}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, 9999)
|
||||
end
|
||||
|
||||
function respond:action(msg, config, matches)
|
||||
local user_name = get_name(msg)
|
||||
local receiver = msg.chat.id
|
||||
local GDRIVE_URL = 'https://de2319bd4b4b51a5ef2939a7638c1d35646f49f8.googledrive.com/host/0B_mfIlDgPiyqU25vUHZqZE9IUXc'
|
||||
local BASE_URL = 'https://anditest.perseus.uberspace.de/plugins/respond'
|
||||
if user_name == "DefenderX" then user_name = "Deffu" end
|
||||
|
||||
if string.match(msg.text, "[Ff][Gg][Tt].? [Ss][Ww][Ii][Ff][Tt]") then
|
||||
@ -78,11 +78,11 @@ function respond:action(msg, config, matches)
|
||||
utilities.send_message(self, receiver, '🐸🐸🐸')
|
||||
return
|
||||
elseif string.match(msg.text, "[Ii][Nn][Ll][Oo][Vv][Ee]") then
|
||||
local file = download_to_file(GDRIVE_URL..'/inlove.gif')
|
||||
local file = download_to_file(BASE_URL..'/inlove.gif')
|
||||
utilities.send_document(self, receiver, file)
|
||||
return
|
||||
elseif string.match(msg.text, "[Ww][Aa][Tt]") then
|
||||
local WAT_URL = GDRIVE_URL..'/wat'
|
||||
local WAT_URL = BASE_URL..'/wat'
|
||||
local wats = {
|
||||
"/wat1.jpg",
|
||||
"/wat2.jpg",
|
||||
|
@ -13,7 +13,7 @@ function rss:init(config)
|
||||
"^/rss (sub) (https?://[%w-_%.%?%.:/%+=&%~]+)$",
|
||||
"^/rss (del) (%d+) @(.*)$",
|
||||
"^/rss (del) (%d+)$",
|
||||
"^/rss (del)",
|
||||
"^/rss (del)$",
|
||||
"^/rss (sync)$"
|
||||
}
|
||||
rss.doc = [[*
|
||||
|
66
miku/plugins/service_migrate_to_supergroup.lua
Normal file
66
miku/plugins/service_migrate_to_supergroup.lua
Normal file
@ -0,0 +1,66 @@
|
||||
local migrate = {}
|
||||
|
||||
migrate.triggers = {
|
||||
'^//tgservice migrate_to_chat_id$'
|
||||
}
|
||||
|
||||
function migrate:action(msg, config, matches)
|
||||
if not is_service_msg(msg) then return end -- Bad attempt at trolling!
|
||||
|
||||
local old_id = msg.chat.id
|
||||
local new_id = msg.migrate_to_chat_id
|
||||
print('Migrating every data from '..old_id..' to '..new_id..'...')
|
||||
print('--- SUPERGROUP MIGRATION STARTED ---')
|
||||
|
||||
local keys = redis:keys('*'..old_id..'*')
|
||||
for k,v in pairs(keys) do
|
||||
local string_before_id = string.match(v, '(.+)'..old_id..'.+') or string.match(v, '(.+)'..old_id)
|
||||
local string_after_id = string.match(v, '.+'..old_id..'(.+)') or ''
|
||||
print(string_before_id..old_id..string_after_id..' -> '..string_before_id..new_id..string_after_id)
|
||||
redis:rename(string_before_id..old_id..string_after_id, string_before_id..new_id..string_after_id)
|
||||
end
|
||||
|
||||
-- Migrate GH feed
|
||||
local keys = redis:keys('github:*:subs')
|
||||
if keys then
|
||||
for k,v in pairs(keys) do
|
||||
local repo = string.match(v, "github:(.+):subs")
|
||||
local is_in_set = redis:sismember('github:'..repo..':subs', old_id)
|
||||
if is_in_set then
|
||||
print('github:'..repo..':subs - Changing ID in set...')
|
||||
redis:srem('github:'..repo..':subs', old_id)
|
||||
redis:sadd('github:'..repo..':subs', new_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Migrate RSS feed
|
||||
local keys = redis:keys('rss:*:subs')
|
||||
if keys then
|
||||
for k,v in pairs(keys) do
|
||||
local feed = string.match(v, "rss:(.+):subs")
|
||||
local is_in_set = redis:sismember('rss:'..feed..':subs', 'chat#id'..old_id)
|
||||
if is_in_set then
|
||||
print('rss:'..feed..':subs - Changing ID in set...')
|
||||
redis:srem('rss:'..feed..':subs', 'chat#id'..old_id)
|
||||
redis:sadd('rss:'..feed..':subs', 'chat#id'..new_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Migrate Tagesschau-Eilmeldungen
|
||||
local does_tagesschau_set_exists = redis:exists('telegram:tagesschau:subs')
|
||||
if does_tagesschau_set_exists then
|
||||
local is_in_set = redis:sismember('telegram:tagesschau:subs', 'chat#id'..old_id)
|
||||
if is_in_set then
|
||||
print('telegram:tagesschau:subs - Changing ID in set...')
|
||||
redis:srem('telegram:tagesschau:subs', 'chat#id'..old_id)
|
||||
redis:sadd('telegram:tagesschau:subs', 'chat#id'..new_id)
|
||||
end
|
||||
end
|
||||
|
||||
print('--- SUPERGROUP MIGRATION ENDED ---')
|
||||
utilities.send_message(self, new_id, 'Die User-ID dieser Gruppe ist nun '..new_id..'.\nAlle Daten wurden übertragen.')
|
||||
end
|
||||
|
||||
return migrate
|
@ -70,11 +70,12 @@ function stats:chat_stats(chat_id)
|
||||
|
||||
local text = ''
|
||||
for k,user in pairs(users_info) do
|
||||
text = text..user.name..': '..comma_value(user.msgs)..'\n'
|
||||
text = string.gsub(text, "%_", " ") -- Bot API doesn't use underscores anymore! Yippie!
|
||||
local msg_num = user.msgs
|
||||
local percent = tostring(round(msg_num / all_msgs * 100, 1))
|
||||
text = text..user.name..': '..comma_value(msg_num)..' <code>('..percent:gsub('%.', ',')..'%)</code>\n'
|
||||
end
|
||||
if text:isempty() then return 'Keine Stats für diesen Chat verfügbar!'end
|
||||
local text = utilities.md_escape(text)..'\n*TOTAL*: '..comma_value(all_msgs)
|
||||
local text = text..'\n<b>TOTAL</b>: '..comma_value(all_msgs)
|
||||
return text
|
||||
end
|
||||
|
||||
@ -129,7 +130,7 @@ function stats:action(msg, config, matches)
|
||||
return
|
||||
else
|
||||
local chat_id = msg.chat.id
|
||||
utilities.send_reply(self, msg, stats:chat_stats(chat_id), true)
|
||||
utilities.send_reply(self, msg, stats:chat_stats(chat_id), 'HTML')
|
||||
return
|
||||
end
|
||||
end
|
||||
@ -139,7 +140,7 @@ function stats:action(msg, config, matches)
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, stats:chat_stats(matches[3]), true)
|
||||
utilities.send_reply(self, msg, stats:chat_stats(matches[3]), 'HTML')
|
||||
return
|
||||
end
|
||||
end
|
||||
|
@ -42,7 +42,7 @@ function tagesschau:inline_callback(inline_query, config, matches)
|
||||
local article = matches[1]
|
||||
local full_url = 'http://www.tagesschau.de/'..article..'.html'
|
||||
local text, img_url, headline, shorttext = tagesschau:get_tagesschau_article(article)
|
||||
if text == 'HTTP-Fehler' or text == 'Artikel nicht gefunden!' then return end
|
||||
if text == 'HTTP-Fehler' or text == 'Artikel nicht gefunden!' then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
if text:match('"') then
|
||||
text = text:gsub('"', '\\"')
|
||||
@ -55,7 +55,7 @@ function tagesschau:inline_callback(inline_query, config, matches)
|
||||
end
|
||||
|
||||
local text = text:gsub('\n', '\\n')
|
||||
local results = '[{"type":"article","id":"'..math.random(100000000000000000)..'","title":"'..headline..'","description":"'..shorttext..'","url":"'..full_url..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/tagesschau/tagesschau.jpg","thumb_width":150,"thumb_height":150,"hide_url":true,"reply_markup":{"inline_keyboard":[[{"text":"Artikel aufrufen","url":"'..full_url..'"}]]},"input_message_content":{"message_text":"'..text..'","parse_mode":"HTML"}}]'
|
||||
local results = '[{"type":"article","id":"11","title":"'..headline..'","description":"'..shorttext..'","url":"'..full_url..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/tagesschau/tagesschau.jpg","thumb_width":150,"thumb_height":150,"hide_url":true,"reply_markup":{"inline_keyboard":[[{"text":"Artikel aufrufen","url":"'..full_url..'"}]]},"input_message_content":{"message_text":"'..text..'","parse_mode":"HTML"}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, 7200)
|
||||
end
|
||||
|
||||
|
@ -4,6 +4,10 @@ time.command = 'time <Ort>'
|
||||
|
||||
function time:init(config)
|
||||
time.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('time', true).table
|
||||
time.inline_triggers = {
|
||||
"^time (.+)",
|
||||
"^time"
|
||||
}
|
||||
time.doc = [[*
|
||||
]]..config.cmd_pat..[[time*: Aktuelle Zeit in Deutschland
|
||||
*]]..config.cmd_pat..[[time* _<Ort>_: Gibt Zeit an diesem Ort aus]]
|
||||
@ -45,8 +49,49 @@ function time:localize(output)
|
||||
return output
|
||||
end
|
||||
|
||||
function time:get_time(coords)
|
||||
local now = os.time()
|
||||
local utc = os.time(os.date("!*t", now))
|
||||
|
||||
local url = 'https://maps.googleapis.com/maps/api/timezone/json?location=' .. coords.lat ..','.. coords.lon .. '×tamp='..utc..'&language=de'
|
||||
local jstr, res = https.request(url)
|
||||
if res ~= 200 then return nil end
|
||||
|
||||
local jdat = json.decode(jstr)
|
||||
local place = string.gsub(jdat.timeZoneId, '_', ' ' )
|
||||
local place = time:localize(place)
|
||||
local timezoneid = '*'..place..'*'
|
||||
local timestamp = now + jdat.rawOffset + jdat.dstOffset
|
||||
local utcoff = (jdat.rawOffset + jdat.dstOffset) / 3600
|
||||
if utcoff == math.abs(utcoff) then
|
||||
utcoff = '+'.. utilities.pretty_float(utcoff)
|
||||
else
|
||||
utcoff = utilities.pretty_float(utcoff)
|
||||
end
|
||||
-- "%A, %d. %B %Y, %H:%M:%S Uhr"
|
||||
local time_there = time:localize(os.date('!%A, %d. %B %Y, %H:%M:%S Uhr',timestamp))
|
||||
local output = timezoneid..':\n'..time_there
|
||||
|
||||
return output..'\n_'..jdat.timeZoneName .. ' (UTC' .. utcoff .. ')_', place, time_there
|
||||
end
|
||||
|
||||
function time:inline_callback(inline_query, config, matches)
|
||||
if matches[1] == 'time' then
|
||||
local desc_time = os.date("%A, %d. %B %Y, %H:%M:%S Uhr")
|
||||
local cur_time = time:localize(os.date("%A, %d. %B %Y, *%H:%M:%S Uhr*"))
|
||||
results = '[{"type":"article","id":"12","title":"Europa/Berlin","description":"'..desc_time..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/time/clock.jpg","input_message_content":{"message_text":"'..cur_time..'","parse_mode":"Markdown"}}]'
|
||||
else
|
||||
local coords = utilities.get_coords(matches[1], config)
|
||||
if type(coords) == 'string' then utilities.answer_inline_query(self, inline_query) return end
|
||||
local output, place, desc_time = time:get_time(coords)
|
||||
if not output then utilities.answer_inline_query(self, inline_query) return end
|
||||
results = '[{"type":"article","id":"13","title":"'..place..'","description":"'..desc_time..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/time/clock.jpg","input_message_content":{"message_text":"'..output..'","parse_mode":"Markdown"}}]'
|
||||
end
|
||||
utilities.answer_inline_query(self, inline_query, results, 1)
|
||||
end
|
||||
|
||||
function time:action(msg, config)
|
||||
local input = utilities.input(msg.text)
|
||||
local input = utilities.input_from_msg(msg)
|
||||
if not input then
|
||||
local output = os.date("%A, %d. %B %Y, *%H:%M:%S Uhr*")
|
||||
utilities.send_reply(self, msg, time:localize(output), true)
|
||||
@ -58,31 +103,8 @@ function time:action(msg, config)
|
||||
utilities.send_reply(self, msg, coords)
|
||||
return
|
||||
end
|
||||
|
||||
local now = os.time()
|
||||
local utc = os.time(os.date("!*t", now))
|
||||
|
||||
local url = 'https://maps.googleapis.com/maps/api/timezone/json?location=' .. coords.lat ..','.. coords.lon .. '×tamp='..utc..'&language=de'
|
||||
local jstr, res = https.request(url)
|
||||
if res ~= 200 then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
return
|
||||
end
|
||||
|
||||
local jdat = json.decode(jstr)
|
||||
local timezoneid = '*'..string.gsub(jdat.timeZoneId, '_', ' ' )..'*'
|
||||
local timestamp = now + jdat.rawOffset + jdat.dstOffset
|
||||
local utcoff = (jdat.rawOffset + jdat.dstOffset) / 3600
|
||||
if utcoff == math.abs(utcoff) then
|
||||
utcoff = '+'.. utilities.pretty_float(utcoff)
|
||||
else
|
||||
utcoff = utilities.pretty_float(utcoff)
|
||||
end
|
||||
-- "%A, %d. %B %Y, %H:%M:%S Uhr"
|
||||
local output = timezoneid..':\n'..os.date('!%A, %d. %B %Y, %H:%M:%S Uhr',timestamp)
|
||||
local output = time:localize(output)
|
||||
|
||||
local output = output..'\n_'..jdat.timeZoneName .. ' (UTC' .. utcoff .. ')_'
|
||||
local output = time:get_time(coords)
|
||||
if not output then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
end
|
||||
|
@ -2,20 +2,20 @@ local twitter = {}
|
||||
|
||||
function twitter:init(config)
|
||||
if not cred_data.tw_consumer_key then
|
||||
print('Missing config value: tw_consumer_key.')
|
||||
print('twitter.lua will not be enabled.')
|
||||
print('Fehlender Key: tw_consumer_key.')
|
||||
print('twitter.lua wird nicht aktiviert.')
|
||||
return
|
||||
elseif not cred_data.tw_consumer_secret then
|
||||
print('Missing config value: tw_consumer_secret.')
|
||||
print('twitter.lua will not be enabled.')
|
||||
print('Fehlender Key: tw_consumer_secret.')
|
||||
print('twitter.lua wird nicht aktiviert.')
|
||||
return
|
||||
elseif not cred_data.tw_access_token then
|
||||
print('Missing config value: tw_access_token.')
|
||||
print('twitter.lua will not be enabled.')
|
||||
print('Fehlender Key: tw_access_token.')
|
||||
print('twitter.lua wird nicht aktiviert.')
|
||||
return
|
||||
elseif not cred_data.tw_access_token_secret then
|
||||
print('Missing config value: tw_access_token_secret.')
|
||||
print('twitter.lua will not be enabled.')
|
||||
print('Fehlender Key: tw_access_token_secret.')
|
||||
print('twitter.lua wird nicht aktiviert.')
|
||||
return
|
||||
end
|
||||
|
||||
@ -104,14 +104,14 @@ function twitter:action(msg, config, matches)
|
||||
if v.video_info then
|
||||
if not v.video_info.variants[3] then
|
||||
local vid = v.video_info.variants[1].url
|
||||
table.insert(videos, vid)
|
||||
videos[#videos+1] = vid
|
||||
else
|
||||
local vid = v.video_info.variants[3].url
|
||||
table.insert(videos, vid)
|
||||
videos[#videos+1] = vid
|
||||
end
|
||||
end
|
||||
text = text:gsub(url, "")
|
||||
table.insert(images, pic)
|
||||
images[#images+1] = pic
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -14,12 +14,14 @@ function twitter_send:init(config)
|
||||
end
|
||||
|
||||
twitter_send.triggers = {
|
||||
"^/tw (auth) (%d+)",
|
||||
"^/tw (auth) (%d+)$",
|
||||
"^/tw (unauth)$",
|
||||
"^/tw (verify)$",
|
||||
"^/tw (.+)",
|
||||
"^/(twwhitelist add) (%d+)",
|
||||
"^/(twwhitelist del) (%d+)"
|
||||
"^/tw (.+)$",
|
||||
"^/(twwhitelist add) (%d+)$",
|
||||
"^/(twwhitelist del) (%d+)$",
|
||||
"^/(twwhitelist add)$",
|
||||
"^/(twwhitelist del)$"
|
||||
}
|
||||
twitter_send.doc = [[*
|
||||
]]..config.cmd_pat..[[tw* _<Text>_: Sendet einen Tweet an den Account, der im Chat angemeldet ist
|
||||
@ -91,16 +93,18 @@ function twitter_send:get_twitter_access_token(hash, oauth_verifier, oauth_token
|
||||
redis:hset(hash, 'oauth_token', values.oauth_token)
|
||||
redis:hset(hash, 'oauth_token_secret', values.oauth_token_secret)
|
||||
|
||||
return 'Erfolgreich eingeloggt als "@'..values.screen_name..'" (User-ID: '..values.user_id..')'
|
||||
local screen_name = values.screen_name
|
||||
|
||||
return 'Erfolgreich eingeloggt als <a href="https://twitter.com/'..screen_name..'">@'..screen_name..'</a> (User-ID: '..values.user_id..')'
|
||||
end
|
||||
|
||||
function twitter_send:reset_twitter_auth(hash, frominvalid)
|
||||
redis:hdel(hash, 'oauth_token')
|
||||
redis:hdel(hash, 'oauth_token_secret')
|
||||
if frominvalid then
|
||||
return '*Authentifizierung nicht erfolgreich, wird zurückgesetzt...*'
|
||||
return '<b>Authentifizierung nicht erfolgreich, wird zurückgesetzt...</b>'
|
||||
else
|
||||
return '*Erfolgreich abgemeldet!* Entziehe den Zugriff endgültig in deinen [Twitter-Einstellungen](https://twitter.com/settings/applications)!'
|
||||
return '<b>Erfolgreich abgemeldet!</b> Entziehe den Zugriff endgültig in deinen <a href="https://twitter.com/settings/applications">Twitter-Einstellungen</a>!'
|
||||
end
|
||||
end
|
||||
|
||||
@ -217,7 +221,7 @@ function twitter_send:send_tweet(tweet, oauth_token, oauth_token_secret, hash)
|
||||
local screen_name = data.user.screen_name
|
||||
local status_id = data.id_str
|
||||
|
||||
return '*Tweet #'..statusnumber..' gesendet!* [Auf Twitter ansehen](https://twitter.com/statuses/'..status_id..')'
|
||||
return '<a href="https://twitter.com/'..screen_name..'/status/'..status_id..'">Tweet #'..statusnumber..' gesendet!</a>'
|
||||
end
|
||||
|
||||
function twitter_send:add_to_twitter_whitelist(user_id)
|
||||
@ -245,22 +249,36 @@ function twitter_send:del_from_twitter_whitelist(user_id)
|
||||
end
|
||||
|
||||
function twitter_send:action(msg, config, matches)
|
||||
if matches[1] == "twwhitelist add" and matches[2] then
|
||||
if matches[1] == "twwhitelist add" then
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, twitter_send:add_to_twitter_whitelist(matches[2]), true)
|
||||
local user_id = matches[2]
|
||||
if not user_id then
|
||||
if not msg.reply_to_message then
|
||||
return
|
||||
end
|
||||
user_id = msg.reply_to_message.from.id
|
||||
end
|
||||
utilities.send_reply(self, msg, twitter_send:add_to_twitter_whitelist(user_id), true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if matches[1] == "twwhitelist del" and matches[2] then
|
||||
if matches[1] == "twwhitelist del" then
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, twitter_send:del_from_twitter_whitelist(matches[2]), true)
|
||||
local user_id = matches[2]
|
||||
if not user_id then
|
||||
if not msg.reply_to_message then
|
||||
return
|
||||
end
|
||||
user_id = msg.reply_to_message.from.id
|
||||
end
|
||||
utilities.send_reply(self, msg, twitter_send:del_from_twitter_whitelist(user_id), true)
|
||||
return
|
||||
end
|
||||
end
|
||||
@ -302,7 +320,7 @@ function twitter_send:action(msg, config, matches)
|
||||
end
|
||||
end
|
||||
if string.len(matches[2]) > 7 then utilities.send_reply(self, msg, 'Invalide PIN!') return end
|
||||
utilities.send_reply(self, msg, twitter_send:get_twitter_access_token(hash, matches[2], oauth_token, oauth_token_secret))
|
||||
utilities.send_reply(self, msg, twitter_send:get_twitter_access_token(hash, matches[2], oauth_token, oauth_token_secret), 'HTML')
|
||||
local message_id = redis:hget(hash, 'login_msg')
|
||||
utilities.edit_message(self, msg.chat.id, message_id, '*Anmeldung abgeschlossen!*', true, true)
|
||||
redis:hdel(hash, 'login_msg')
|
||||
@ -316,7 +334,7 @@ function twitter_send:action(msg, config, matches)
|
||||
return
|
||||
end
|
||||
end
|
||||
utilities.send_reply(self, msg, twitter_send:reset_twitter_auth(hash), true)
|
||||
utilities.send_reply(self, msg, twitter_send:reset_twitter_auth(hash), 'HTML')
|
||||
return
|
||||
end
|
||||
|
||||
@ -334,11 +352,11 @@ function twitter_send:action(msg, config, matches)
|
||||
utilities.send_reply(self, msg, '*Du darfst keine Tweets senden.* Entweder wurdest du noch gar nicht freigeschaltet oder ausgeschlossen.', true)
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, twitter_send:send_tweet(matches[1], oauth_token, oauth_token_secret, hash), true)
|
||||
utilities.send_reply(self, msg, twitter_send:send_tweet(matches[1], oauth_token, oauth_token_secret, hash), 'HTML')
|
||||
return
|
||||
end
|
||||
else
|
||||
utilities.send_reply(self, msg, twitter_send:send_tweet(matches[1], oauth_token, oauth_token_secret, hash), true)
|
||||
utilities.send_reply(self, msg, twitter_send:send_tweet(matches[1], oauth_token, oauth_token_secret, hash), 'HTML')
|
||||
return
|
||||
end
|
||||
end
|
||||
|
@ -1,4 +1,4 @@
|
||||
local twitter_user = {}
|
||||
local twitter_user = {}
|
||||
|
||||
require "./miku/encoding"
|
||||
|
||||
@ -58,7 +58,7 @@ function twitter_user:resolve_url(url)
|
||||
end
|
||||
end
|
||||
|
||||
function twitter_user:action(msg)
|
||||
function twitter_user:action(msg, config, matches)
|
||||
local twitter_url = "https://api.twitter.com/1.1/users/show/"..matches[1]..".json"
|
||||
local response_code, response_headers, response_status_line, response_body = client:PerformRequest("GET", twitter_url)
|
||||
local response = json.decode(response_body)
|
||||
|
@ -7,7 +7,7 @@ venue.triggers = {
|
||||
local apikey = cred_data.google_apikey
|
||||
|
||||
function venue:pre_process(msg, self)
|
||||
if not msg.venue then return end -- Ignore
|
||||
if not msg.venue then return msg end -- Ignore
|
||||
|
||||
local lat = msg.venue.location.latitude
|
||||
local lng = msg.venue.location.longitude
|
||||
|
@ -17,6 +17,10 @@ function weather:init(config)
|
||||
"^/w$",
|
||||
"^/w (.*)$"
|
||||
}
|
||||
weather.inline_triggers = {
|
||||
"^w (.+)$",
|
||||
"^w$"
|
||||
}
|
||||
weather.doc = [[*
|
||||
]]..config.cmd_pat..[[wetter*: Wetter für deinen Wohnort _(/location set [Ort])_
|
||||
*]]..config.cmd_pat..[[wetter* _<Ort>_: Wetter für diesen Ort
|
||||
@ -42,10 +46,43 @@ function get_city_name(lat, lng)
|
||||
return city
|
||||
end
|
||||
|
||||
function weather:get_weather(lat, lng)
|
||||
function get_city_coordinates(city, config)
|
||||
local lat = redis:hget('telegram:cache:weather:'..string.lower(city), 'lat')
|
||||
local lng = redis:hget('telegram:cache:weather:'..string.lower(city), 'lng')
|
||||
if not lat and not lng then
|
||||
print('Koordinaten nicht eingespeichert, frage Google...')
|
||||
coords = utilities.get_coords(city, config)
|
||||
lat = coords.lat
|
||||
lng = coords.lon
|
||||
end
|
||||
|
||||
if not lat and not lng then
|
||||
return nil
|
||||
end
|
||||
|
||||
redis:hset('telegram:cache:weather:'..string.lower(city), 'lat', lat)
|
||||
redis:hset('telegram:cache:weather:'..string.lower(city), 'lng', lng)
|
||||
return lat, lng
|
||||
end
|
||||
|
||||
function weather:get_weather(lat, lng, is_inline)
|
||||
print('Finde Wetter in '..lat..', '..lng)
|
||||
local text = redis:get('telegram:cache:weather:'..lat..','..lng)
|
||||
if text then print('...aus dem Cache') return text end
|
||||
local hash = 'telegram:cache:weather:'..lat..','..lng
|
||||
|
||||
local text = redis:hget(hash, 'text')
|
||||
if text then
|
||||
print('...aus dem Cache')
|
||||
if is_inline then
|
||||
local ttl = redis:ttl(hash)
|
||||
local city = redis:hget(hash, 'city')
|
||||
local temperature = redis:hget(hash, 'temperature')
|
||||
local weather_icon = redis:hget(hash, 'weather_icon')
|
||||
local condition = redis:hget(hash, 'condition')
|
||||
return city, condition..' bei '..temperature..' °C', weather_icon, text, ttl
|
||||
else
|
||||
return text
|
||||
end
|
||||
end
|
||||
|
||||
local url = BASE_URL..'/'..apikey..'/'..lat..','..lng..'?lang=de&units=si&exclude=minutely,hourly,daily,alerts,flags'
|
||||
|
||||
@ -55,10 +92,10 @@ function weather:get_weather(lat, lng)
|
||||
method = "GET",
|
||||
sink = ltn12.sink.table(response_body)
|
||||
}
|
||||
local ok, response_code, response_headers, response_status_line = https.request(request_constructor)
|
||||
local ok, response_code, response_headers = https.request(request_constructor)
|
||||
if not ok then return nil end
|
||||
local data = json.decode(table.concat(response_body))
|
||||
local ttl = string.sub(response_headers["cache-control"], 9)
|
||||
local ttl = tonumber(string.sub(response_headers["cache-control"], 9))
|
||||
|
||||
|
||||
local weather = data.currently
|
||||
@ -66,26 +103,28 @@ function weather:get_weather(lat, lng)
|
||||
local temperature = string.gsub(round(weather.temperature, 1), "%.", ",")
|
||||
local feelslike = string.gsub(round(weather.apparentTemperature, 1), "%.", ",")
|
||||
local temp = '*Wetter in '..city..':*\n'..temperature..' °C'
|
||||
local conditions = ' | '..weather.summary
|
||||
if weather.icon == 'clear-day' then
|
||||
local weather_summary = weather.summary
|
||||
local conditions = ' | '..weather_summary
|
||||
local weather_icon = weather.icon
|
||||
if weather_icon == 'clear-day' then
|
||||
conditions = conditions..' ☀️'
|
||||
elseif weather.icon == 'clear-night' then
|
||||
elseif weather_icon == 'clear-night' then
|
||||
conditions = conditions..' 🌙'
|
||||
elseif weather.icon == 'rain' then
|
||||
elseif weather_icon == 'rain' then
|
||||
conditions = conditions..' ☔️'
|
||||
elseif weather.icon == 'snow' then
|
||||
elseif weather_icon == 'snow' then
|
||||
conditions = conditions..' ❄️'
|
||||
elseif weather.icon == 'sleet' then
|
||||
elseif weather_icon == 'sleet' then
|
||||
conditions = conditions..' 🌨'
|
||||
elseif weather.icon == 'wind' then
|
||||
elseif weather_icon == 'wind' then
|
||||
conditions = conditions..' 💨'
|
||||
elseif weather.icon == 'fog' then
|
||||
conditions = conditions..' 🌫'
|
||||
elseif weather.icon == 'cloudy' then
|
||||
elseif weather_icon == 'cloudy' then
|
||||
conditions = conditions..' ☁️☁️'
|
||||
elseif weather.icon == 'partly-cloudy-day' then
|
||||
elseif weather_icon == 'partly-cloudy-day' then
|
||||
conditions = conditions..' 🌤'
|
||||
elseif weather.icon == 'partly-cloudy-night' then
|
||||
elseif weather_icon == 'partly-cloudy-night' then
|
||||
conditions = conditions..' 🌙☁️'
|
||||
else
|
||||
conditions = conditions..''
|
||||
@ -98,8 +137,56 @@ function weather:get_weather(lat, lng)
|
||||
text = text..'\n(gefühlt: '..feelslike..' °C)'
|
||||
end
|
||||
|
||||
cache_data('weather', lat..','..lng, text, tonumber(ttl), 'key')
|
||||
return text
|
||||
print('Caching data...')
|
||||
redis:hset(hash, 'city', city)
|
||||
redis:hset(hash, 'temperature', temperature)
|
||||
redis:hset(hash, 'weather_icon', weather_icon)
|
||||
redis:hset(hash, 'condition', weather_summary)
|
||||
redis:hset(hash, 'text', text)
|
||||
redis:expire(hash, ttl)
|
||||
|
||||
if is_inline then
|
||||
return city, weather_summary..' bei '..temperature..' °C', weather_icon, text, ttl
|
||||
else
|
||||
return text
|
||||
end
|
||||
end
|
||||
|
||||
function weather:inline_callback(inline_query, config, matches)
|
||||
local user_id = inline_query.from.id
|
||||
if matches[1] ~= 'w' then
|
||||
city = matches[1]
|
||||
is_personal = false
|
||||
else
|
||||
local set_location = get_location(user_id)
|
||||
is_personal = true
|
||||
if not set_location then
|
||||
city = 'Berlin, Deutschland'
|
||||
else
|
||||
city = set_location
|
||||
end
|
||||
end
|
||||
local lat, lng = get_city_coordinates(city, config)
|
||||
if not lat and not lng then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
local title, description, icon, text, ttl = weather:get_weather(lat, lng, true)
|
||||
if not title and not description and not icon and not text and not ttl then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
local text = text:gsub('\n', '\\n')
|
||||
local thumb_url = 'https://anditest.perseus.uberspace.de/inlineQuerys/weather/'
|
||||
if icon == 'clear-day' or icon == 'partly-cloudy-day' then
|
||||
thumb_url = thumb_url..'day.jpg'
|
||||
elseif icon == 'clear-night' or icon == 'partly-cloudy-night' then
|
||||
thumb_url = thumb_url..'night.jpg'
|
||||
elseif icon == 'rain' then
|
||||
thumb_url = thumb_url..'rain.jpg'
|
||||
elseif icon == 'snow' then
|
||||
thumb_url = thumb_url..'snow.jpg'
|
||||
else
|
||||
thumb_url = thumb_url..'cloudy.jpg'
|
||||
end
|
||||
local results = '[{"type":"article","id":"19122006","title":"'..title..'","description":"'..description..'","thumb_url":"'..thumb_url..'","thumb_width":80,"thumb_height":80,"input_message_content":{"message_text":"'..text..'", "parse_mode":"Markdown"}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, ttl, is_personal)
|
||||
end
|
||||
|
||||
function weather:action(msg, config, matches)
|
||||
@ -116,23 +203,12 @@ function weather:action(msg, config, matches)
|
||||
end
|
||||
end
|
||||
|
||||
local lat = redis:hget('telegram:cache:weather:'..string.lower(city), 'lat')
|
||||
local lng = redis:hget('telegram:cache:weather:'..string.lower(city), 'lng')
|
||||
local lat, lng = get_city_coordinates(city, config)
|
||||
if not lat and not lng then
|
||||
print('Koordinaten nicht eingespeichert, frage Google...')
|
||||
coords = utilities.get_coords(city, config)
|
||||
lat = coords.lat
|
||||
lng = coords.lon
|
||||
end
|
||||
|
||||
if not lat and not lng then
|
||||
utilities.send_reply(self, msg, '*Diesen Ort gibt es nicht!*', true)
|
||||
utilities.send_reply(self, msg, '*Diesen Ort gibt es nicht!*', true)
|
||||
return
|
||||
end
|
||||
|
||||
redis:hset('telegram:cache:weather:'..string.lower(city), 'lat', lat)
|
||||
redis:hset('telegram:cache:weather:'..string.lower(city), 'lng', lng)
|
||||
|
||||
local text = weather:get_weather(lat, lng)
|
||||
if not text then
|
||||
text = 'Konnte das Wetter von dieser Stadt nicht bekommen.'
|
||||
|
@ -57,7 +57,7 @@ function wikipedia:getWikiServer(lang)
|
||||
end
|
||||
|
||||
--[[
|
||||
-- return decoded json table from Wikipedia
|
||||
-- return decoded JSON table from Wikipedia
|
||||
--]]
|
||||
function wikipedia:loadPage(text, lang, intro, plain, is_search)
|
||||
local request, sink = {}, {}
|
||||
@ -107,7 +107,7 @@ function wikipedia:loadPage(text, lang, intro, plain, is_search)
|
||||
end
|
||||
|
||||
-- extract intro passage in wiki page
|
||||
function wikipedia:wikintro(text, lang)
|
||||
function wikipedia:wikintro(text, lang, is_inline)
|
||||
local text = decodetext(text)
|
||||
local result = self:loadPage(text, lang, true, true)
|
||||
|
||||
@ -124,13 +124,28 @@ function wikipedia:wikintro(text, lang)
|
||||
local lang = lang or "de"
|
||||
local title = page.title
|
||||
local title_enc = URL.escape(title)
|
||||
return '*'..title.."*:\n"..utilities.md_escape(page.extract), '{"inline_keyboard":[[{"text":"Artikel aufrufen","url":"https://'..lang..'.wikipedia.org/wiki/'..title_enc..'"}]]}'
|
||||
if is_inline then
|
||||
local result = '<b>'..title..'</b>:\n'..page.extract
|
||||
local result = result:gsub('\n', '\\n')
|
||||
local result = result:gsub('"', '\\"')
|
||||
return title, result, '{"inline_keyboard":[[{"text":"Wikipedia aufrufen","url":"https://'..lang..'.wikipedia.org/wiki/'..title_enc..'"}]]}'
|
||||
else
|
||||
return '*'..title..'*:\n'..utilities.md_escape(page.extract), '{"inline_keyboard":[[{"text":"Artikel aufrufen","url":"https://'..lang..'.wikipedia.org/wiki/'..title_enc..'"}]]}'
|
||||
end
|
||||
else
|
||||
local text = text.." nicht gefunden"
|
||||
return text
|
||||
if is_inline then
|
||||
return nil
|
||||
else
|
||||
local text = text.." nicht gefunden"
|
||||
return text
|
||||
end
|
||||
end
|
||||
else
|
||||
return "Ein Fehler ist aufgetreten."
|
||||
if is_inline then
|
||||
return nil
|
||||
else
|
||||
return "Ein Fehler ist aufgetreten."
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -165,17 +180,20 @@ function wikipedia:inline_callback(inline_query, config, matches)
|
||||
lang = 'de'
|
||||
query = matches[1]
|
||||
end
|
||||
local url = 'https://'..lang..'.wikipedia.org/w/api.php?action=query&list=search&srsearch='..URL.escape(query)..'&format=json&prop=extracts&srprop=snippet'
|
||||
local res, code = https.request(url)
|
||||
if code ~= 200 then return end
|
||||
|
||||
local search_url = 'https://'..lang..'.wikipedia.org/w/api.php?action=query&list=search&srsearch='..URL.escape(query)..'&format=json&prop=extracts&srprop=snippet&&srlimit=5'
|
||||
local res, code = https.request(search_url)
|
||||
if code ~= 200 then utilities.answer_inline_query(self, inline_query) return end
|
||||
local data = json.decode(res).query
|
||||
|
||||
if data.searchinfo.totalhits == 0 then return end
|
||||
|
||||
local results = '['
|
||||
local id = 700
|
||||
for num in pairs(data.search) do
|
||||
local title = data.search[num].title
|
||||
results = results..'{"type":"article","id":"'..math.random(100000000000000000)..'","title":"'..title..'","description":"'..wikipedia:snip_snippet(data.search[num].snippet)..'","url":"https://'..lang..'.wikipedia.org/wiki/'..URL.escape(title)..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/wiki/logo.jpg","thumb_width":95,"thumb_height":86,"input_message_content":{"message_text":"https://'..lang..'.wikipedia.org/wiki/'..URL.escape(title)..'","disable_web_page_preview":true}}'
|
||||
local title, result, keyboard = wikipedia:wikintro(data.search[num].title, lang, true)
|
||||
if not title or not result or not keyboard then utilities.answer_inline_query(self, inline_query) return end
|
||||
results = results..'{"type":"article","id":"'..id..'","title":"'..title..'","description":"'..wikipedia:snip_snippet(data.search[num].snippet)..'","url":"https://'..lang..'.wikipedia.org/wiki/'..URL.escape(title)..'","hide_url":true,"thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/wiki/logo.jpg","thumb_width":95,"thumb_height":86,"reply_markup":'..keyboard..',"input_message_content":{"message_text":"'..result..'","parse_mode":"HTML"}}'
|
||||
id = id+1
|
||||
if num < #data.search then
|
||||
results = results..','
|
||||
end
|
||||
|
@ -147,10 +147,10 @@ function youtube:inline_callback(inline_query, config, matches)
|
||||
local query = matches[1]
|
||||
local url = BASE_URL..'/search?part=snippet&key='..apikey..'&maxResults=10&type=video&q='..URL.escape(query)..'&fields=items(id(videoId),snippet(publishedAt,title,thumbnails,channelTitle))'
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return end
|
||||
if code ~= 200 then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
local data = json.decode(res)
|
||||
if not data.items[1] then return end
|
||||
if not data.items[1] then utilities.answer_inline_query(self, inline_query) return end
|
||||
|
||||
local video_ids = ""
|
||||
-- We get all videoIds from search...
|
||||
@ -170,6 +170,7 @@ function youtube:inline_callback(inline_query, config, matches)
|
||||
if not video_results.items[1] then return end
|
||||
|
||||
local results = '['
|
||||
local id = 800
|
||||
for num in pairs(video_results.items) do
|
||||
local video_url = 'https://www.youtube.com/watch?v='..video_results.items[num].id
|
||||
local thumb_url = get_yt_thumbnail(video_results.items[num])
|
||||
@ -195,7 +196,8 @@ function youtube:inline_callback(inline_query, config, matches)
|
||||
local uploader = video_results.items[num].snippet.channelTitle
|
||||
local description = uploader..', '..viewCount..' Views, '..readable_dur..likeCount..dislikeCount..commentCount
|
||||
|
||||
results = results..'{"type":"video","id":"'..math.random(100000000000000000)..'","video_url":"'..video_url..'","mime_type":"text/html","thumb_url":"'..thumb_url..'","title":"'..video_title..'","description":"'..description..'","video_duration":'..video_duration..',"input_message_content":{"message_text":"'..video_url..'"}}'
|
||||
results = results..'{"type":"video","id":"'..id..'","video_url":"'..video_url..'","mime_type":"text/html","thumb_url":"'..thumb_url..'","title":"'..video_title..'","description":"'..description..'","video_duration":'..video_duration..',"input_message_content":{"message_text":"'..video_url..'"}}'
|
||||
id = id+1
|
||||
if num < #video_results.items then
|
||||
results = results..','
|
||||
end
|
||||
@ -207,6 +209,10 @@ end
|
||||
function youtube:action(msg, config, matches)
|
||||
local yt_code = matches[1]
|
||||
local data = get_yt_data(yt_code)
|
||||
if not data then
|
||||
utilities.send_reply(self, msg, config.errors.results)
|
||||
return
|
||||
end
|
||||
send_youtube_data(data, msg, self)
|
||||
return
|
||||
end
|
||||
|
@ -4,34 +4,86 @@ local youtube_dl = {}
|
||||
|
||||
function youtube_dl:init(config)
|
||||
youtube_dl.triggers = {
|
||||
"^/(mp4) (https?://[%w-_%.%?%.:/%+=&]+)$",
|
||||
"^/(mp3) (https?://[%w-_%.%?%.:/%+=&]+)$"
|
||||
"^/(mp4) https?://w?w?w?%.?youtu.be/([A-Za-z0-9-_-]+)",
|
||||
"^/(mp4) https?://w?w?w?m?%.?youtube.com/embed/([A-Za-z0-9-_-]+)",
|
||||
"^/(mp4) https?://w?w?w?m?%.?youtube.com/watch%?v=([A-Za-z0-9-_-]+)",
|
||||
"^/(mp3) https?://w?w?w?m?%.?youtu.be/([A-Za-z0-9-_-]+)",
|
||||
"^/(mp3) https?://w?w?w?m?%.?youtube.com/embed/([A-Za-z0-9-_-]+)",
|
||||
"^/(mp3) https?://w?w?w?m?%.?youtube.com/watch%?v=([A-Za-z0-9-_-]+)"
|
||||
}
|
||||
|
||||
youtube_dl.doc = [[*
|
||||
]]..config.cmd_pat..[[mp3* _<URL>_: Lädt Audio von [untersützten Seiten](https://rg3.github.io/youtube-dl/supportedsites.html)
|
||||
*]]..config.cmd_pat..[[mp4* _<URL>_: Lädt Video von [untersützten Seiten](https://rg3.github.io/youtube-dl/supportedsites.html)
|
||||
]]..config.cmd_pat..[[mp3* _<URL>_: Lädt Audio von YouTube
|
||||
*]]..config.cmd_pat..[[mp4* _<URL>_: Lädt Video von YouTube
|
||||
]]
|
||||
end
|
||||
|
||||
youtube_dl.command = 'mp3 <URL>, /mp4 <URL>'
|
||||
|
||||
function youtube_dl:convert_video(link)
|
||||
local output = io.popen('youtube-dl -f mp4 --max-filesize 49m -o "/tmp/%(title)s.%(ext)s" '..link):read('*all')
|
||||
print(output)
|
||||
if string.match(output, '.* File is larger .*') then
|
||||
return 'TOOBIG'
|
||||
function youtube_dl:get_availabe_formats(id, hash)
|
||||
local ytdl_json = io.popen('youtube-dl -j https://www.youtube.com/watch/?v='..id):read('*all')
|
||||
if not ytdl_json then return end
|
||||
local data = json.decode(ytdl_json)
|
||||
if not data then return nil end
|
||||
|
||||
local available_formats = {}
|
||||
redis:hset(hash, 'duration', data.duration)
|
||||
|
||||
-- Building table with infos
|
||||
for n=1, #data.formats do
|
||||
local vid_format = data.formats[n].format
|
||||
local format_num = vid_format:match('^(%d+) ')
|
||||
local valid_nums = {['17'] = true, ['36'] = true, ['43'] = true, ['18'] = true, ['22'] = true}
|
||||
if not vid_format:match('DASH') and valid_nums[format_num] then -- We don't want DASH videos!
|
||||
local format_info = {}
|
||||
format_info.format = format_num
|
||||
local hash = hash..':'..format_num
|
||||
if format_num == '17' then
|
||||
format_info.pretty_format = '144p'
|
||||
elseif format_num == '36' then
|
||||
format_info.pretty_format = '180p'
|
||||
elseif format_num == '43' then
|
||||
format_info.pretty_format = '360p WebM'
|
||||
elseif format_num == '18' then
|
||||
format_info.pretty_format = '360p MP4'
|
||||
elseif format_num == '22' then
|
||||
format_info.pretty_format = '720p'
|
||||
end
|
||||
format_info.ext = data.formats[n].ext
|
||||
local url = data.formats[n].url
|
||||
local headers = get_http_header(url)
|
||||
local full_url = headers.location
|
||||
|
||||
if not full_url then return end
|
||||
local headers = get_http_header(full_url) -- first was for 302, this get's use the size
|
||||
if headers.location then -- There are some videos where there is a "chain" of 302... repeat this, until we get the LAST url!
|
||||
repeat
|
||||
headers = get_http_header(headers.location)
|
||||
until not headers.location
|
||||
end
|
||||
|
||||
|
||||
format_info.url = full_url
|
||||
local size = tonumber(headers["content-length"])
|
||||
format_info.size = size
|
||||
format_info.pretty_size = string.gsub(tostring(round(size / 1048576, 2)), '%.', ',')..' MB' -- 1048576 = 1024*1024
|
||||
available_formats[#available_formats+1] = format_info
|
||||
redis:hset(hash, 'ext', format_info.ext)
|
||||
redis:hset(hash, 'format', format_info.pretty_format)
|
||||
redis:hset(hash, 'url', full_url)
|
||||
redis:hset(hash, 'size', size)
|
||||
redis:hset(hash, 'height', data.formats[n].height)
|
||||
redis:hset(hash, 'width', data.formats[n].width)
|
||||
redis:hset(hash, 'pretty_size', format_info.pretty_size)
|
||||
redis:expire(hash, 7889400)
|
||||
end
|
||||
end
|
||||
local video = string.match(output, '%[download%] Destination: /tmp/(.*).mp4')
|
||||
if not video then
|
||||
video = string.match(output, '%[download%] /tmp/(.*).mp4 has already been downloaded')
|
||||
end
|
||||
return '/tmp/'..video..'.mp4'
|
||||
|
||||
return available_formats
|
||||
end
|
||||
|
||||
function youtube_dl:convert_audio(link)
|
||||
local output = io.popen('youtube-dl --max-filesize 49m -o "/tmp/%(title)s.%(ext)s" --extract-audio --audio-format mp3 '..link):read('*all')
|
||||
print(output)
|
||||
function youtube_dl:convert_audio(id)
|
||||
local output = io.popen('youtube-dl --max-filesize 49m -o "/tmp/%(title)s.%(ext)s" --extract-audio --audio-format mp3 https://www.youtube.com/watch/?v='..id):read('*all')
|
||||
if string.match(output, '.* File is larger .*') then
|
||||
return 'TOOBIG'
|
||||
end
|
||||
@ -39,25 +91,105 @@ function youtube_dl:convert_audio(link)
|
||||
return '/tmp/'..audio..'.mp3'
|
||||
end
|
||||
|
||||
function youtube_dl:action(msg, config)
|
||||
local link = matches[2]
|
||||
function youtube_dl:callback(callback, msg, self, config, input)
|
||||
utilities.answer_callback_query(self, callback, 'Informationen werden verarbeitet...')
|
||||
local video_id = input:match('(.+)@')
|
||||
local vid_format = input:match('@(%d+)')
|
||||
local hash = 'telegram:cache:youtube_dl:mp4:'..video_id
|
||||
local format_hash = hash..':'..vid_format
|
||||
if not redis:exists(format_hash) then
|
||||
youtube_dl:get_availabe_formats(video_id, hash)
|
||||
end
|
||||
|
||||
local keyboard = redis:hget(hash, 'keyboard')
|
||||
local duration = redis:hget(hash, 'duration')
|
||||
local format_info = redis:hgetall(format_hash)
|
||||
|
||||
local full_url = format_info.url
|
||||
|
||||
local width = format_info.width
|
||||
local height = format_info.height
|
||||
local ext = format_info.ext
|
||||
local pretty_size = format_info.pretty_size
|
||||
local size = tonumber(format_info.size)
|
||||
local format = format_info.format
|
||||
local file = format_info.file_id
|
||||
|
||||
if size > 52420000 then
|
||||
utilities.edit_message(self, msg.chat.id, msg.message_id, '<a href="'..full_url..'">Direktlink zum Video</a> ('..format..', '..pretty_size..')', nil, 'HTML', keyboard)
|
||||
return
|
||||
end
|
||||
|
||||
utilities.edit_message(self, msg.chat.id, msg.message_id, '<b>Video wird hochgeladen</b>', nil, 'HTML')
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_video')
|
||||
|
||||
if not file then
|
||||
file = download_to_file(full_url, video_id..'.'..ext)
|
||||
end
|
||||
if not file then return end
|
||||
local result = utilities.send_video(self, msg.chat.id, file, '('..format..')', msg.message_id, duration, width, height)
|
||||
utilities.edit_message(self, msg.chat.id, msg.message_id, '<a href="'..full_url..'">Direktlink zum Video</a> ('..format..', '..pretty_size..')', nil, 'HTML', keyboard)
|
||||
if not result then return end
|
||||
local file_id = result.result.video.file_id
|
||||
redis:hset(format_hash, 'file_id', file_id)
|
||||
end
|
||||
|
||||
function youtube_dl:action(msg, config, matches)
|
||||
if msg.chat.type ~= 'private' then
|
||||
utilities.send_reply(self, msg, 'Dieses Plugin kann nur im Privatchat benutzt werden')
|
||||
return
|
||||
end
|
||||
local id = matches[2]
|
||||
|
||||
if matches[1] == 'mp4' then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_video')
|
||||
local file = youtube_dl:convert_video(link)
|
||||
if file == 'TOOBIG' then
|
||||
utilities.send_reply(self, msg, 'Das Video überschreitet die Grenze von 50 MB!')
|
||||
return
|
||||
local hash = 'telegram:cache:youtube_dl:mp4:'..id
|
||||
local first_msg = utilities.send_reply(self, msg, '<b>Verfügbare Videoformate werden ausgelesen...</b>', 'HTML')
|
||||
local callback_keyboard = redis:hget(hash, 'keyboard')
|
||||
if not callback_keyboard then
|
||||
utilities.send_typing(self, msg.chat.id, 'typing')
|
||||
local available_formats = youtube_dl:get_availabe_formats(id, hash)
|
||||
if not available_formats then
|
||||
utilities.edit_message(self, msg.chat.id, first_msg.result.message_id, config.errors.results)
|
||||
return
|
||||
end
|
||||
|
||||
local callback_buttons = {}
|
||||
for n=1, #available_formats do
|
||||
local video = available_formats[n]
|
||||
local format = video.format
|
||||
local size = video.size
|
||||
local pretty_size = video.pretty_size
|
||||
if size > 52420000 then
|
||||
pretty_format = video.pretty_format..' ('..pretty_size..', nur Link)'
|
||||
else
|
||||
pretty_format = video.pretty_format..' ('..pretty_size..')'
|
||||
end
|
||||
local button = '{"text":"'..pretty_format..'","callback_data":"@'..self.info.username..' youtube_dl:'..id..'@'..format..'"}'
|
||||
callback_buttons[#callback_buttons+1] = button
|
||||
end
|
||||
|
||||
local keyboard = '{"inline_keyboard":['
|
||||
for button in pairs(callback_buttons) do
|
||||
keyboard = keyboard..'['..callback_buttons[button]..']'
|
||||
if button < #callback_buttons then
|
||||
keyboard = keyboard..','
|
||||
end
|
||||
end
|
||||
|
||||
callback_keyboard = keyboard..']}'
|
||||
redis:hset(hash, 'keyboard', callback_keyboard)
|
||||
redis:expire(hash, 7889400)
|
||||
end
|
||||
utilities.send_video(self, msg.chat.id, file, nil, msg.message_id)
|
||||
return
|
||||
utilities.edit_message(self, msg.chat.id, first_msg.result.message_id, 'Wähle die gewünschte Auflösung.', nil, nil, callback_keyboard)
|
||||
return
|
||||
end
|
||||
|
||||
if matches[1] == 'mp3' then
|
||||
local first_msg = utilities.send_reply(self, msg, '<b>Audio wird heruntergeladen...</b>', 'HTML')
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_audio')
|
||||
local file = youtube_dl:convert_audio(link)
|
||||
local file = youtube_dl:convert_audio(id)
|
||||
if file == 'TOOBIG' then
|
||||
utilities.send_reply(self, msg, 'Die MP3 überschreitet die Grenze von 50 MB!')
|
||||
utilities.edit_message(self, msg.chat.id, first_msg.result.message_id, '<b>Die MP3 überschreitet die Grenze von 50 MB!</b>', nil, 'HTML')
|
||||
return
|
||||
end
|
||||
utilities.send_audio(self, msg.chat.id, file, msg.message_id)
|
||||
|
@ -10,12 +10,11 @@ socket = require('socket')
|
||||
URL = require('socket.url')
|
||||
json = require('dkjson')
|
||||
pcall(json.use_lpeg)
|
||||
serpent = require("serpent")
|
||||
bindings = require('miku.bindings')
|
||||
redis = (loadfile "./miku/redis.lua")()
|
||||
mimetype = (loadfile "./miku/mimetype.lua")()
|
||||
OAuth = require "OAuth"
|
||||
helpers = require "OAuth.helpers"
|
||||
serpent = require('serpent')
|
||||
redis = (loadfile './miku/redis.lua')()
|
||||
mime = (loadfile './miku/mimetype.lua')()
|
||||
OAuth = require 'OAuth'
|
||||
helpers = require 'OAuth.helpers'
|
||||
|
||||
http.timeout = 5
|
||||
https.timeout = 5
|
||||
@ -23,52 +22,42 @@ https.timeout = 5
|
||||
-- For the sake of ease to new contributors and familiarity to old contributors,
|
||||
-- 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)
|
||||
if use_markdown == true then
|
||||
use_markdown = 'Markdown'
|
||||
elseif not use_markdown then
|
||||
use_markdown = nil
|
||||
local parse_mode
|
||||
if type(use_markdown) == 'string' then
|
||||
parse_mode = use_markdown
|
||||
elseif use_markdown == true then
|
||||
parse_mode = 'Markdown'
|
||||
end
|
||||
return bindings.request(self, 'sendMessage', {
|
||||
chat_id = chat_id,
|
||||
text = text,
|
||||
disable_web_page_preview = disable_web_page_preview,
|
||||
reply_to_message_id = reply_to_message_id,
|
||||
parse_mode = use_markdown,
|
||||
parse_mode = parse_mode,
|
||||
reply_markup = reply_markup
|
||||
} )
|
||||
end
|
||||
|
||||
-- https://core.telegram.org/bots/api#editmessagetext
|
||||
function utilities:edit_message(chat_id, message_id, text, disable_web_page_preview, use_markdown, reply_markup)
|
||||
if use_markdown == true then
|
||||
use_markdown = 'Markdown'
|
||||
elseif not use_markdown then
|
||||
use_markdown = nil
|
||||
local parse_mode
|
||||
if type(use_markdown) == 'string' then
|
||||
parse_mode = use_markdown
|
||||
elseif use_markdown == true then
|
||||
parse_mode = 'Markdown'
|
||||
end
|
||||
return bindings.request(self, 'editMessageText', {
|
||||
chat_id = chat_id,
|
||||
message_id = message_id,
|
||||
text = text,
|
||||
disable_web_page_preview = disable_web_page_preview,
|
||||
parse_mode = use_markdown,
|
||||
parse_mode = parse_mode,
|
||||
reply_markup = reply_markup
|
||||
} )
|
||||
end
|
||||
|
||||
function utilities:send_reply(old_msg, text, use_markdown, reply_markup)
|
||||
if use_markdown == true then
|
||||
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
|
||||
} )
|
||||
return utilities.send_message(self, old_msg.chat.id, text, true, old_msg.message_id, use_markdown, reply_markup)
|
||||
end
|
||||
|
||||
-- NOTE: Telegram currently only allows file uploads up to 50 MB
|
||||
@ -225,23 +214,14 @@ 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
|
||||
s = s or ''
|
||||
i = i or 1
|
||||
local n = 0
|
||||
for w in s:gmatch('%g+') do
|
||||
n = n + 1
|
||||
if n == i then return w end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- Returns the string after the first space.
|
||||
@ -252,6 +232,10 @@ function utilities.input(s)
|
||||
return s:sub(s:find(' ')+1)
|
||||
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
|
||||
function utilities.utf8_len(s)
|
||||
local chars = 0
|
||||
@ -341,19 +325,19 @@ function vardump(value)
|
||||
print(serpent.block(value, {comment=false}))
|
||||
end
|
||||
|
||||
-- Loads a json file as a table.
|
||||
-- Loads a JSON file as a table.
|
||||
function utilities.load_data(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 {}
|
||||
end
|
||||
local s = f:read('*all')
|
||||
f:close()
|
||||
local data = json.decode(s)
|
||||
return data
|
||||
end
|
||||
|
||||
-- Saves a table to a json file.
|
||||
-- Saves a table to a JSON file.
|
||||
function utilities.save_data(filename, data)
|
||||
local s = json.encode(data)
|
||||
local f = io.open(filename, 'w')
|
||||
@ -363,24 +347,22 @@ end
|
||||
|
||||
-- Gets coordinates for a location. Used by gMaps.lua, time.lua, weather.lua.
|
||||
function utilities.get_coords(input, config)
|
||||
local url = 'https://maps.googleapis.com/maps/api/geocode/json?address='..URL.escape(input)..'&language=de'
|
||||
local jstr, res = https.request(url)
|
||||
if res ~= 200 then
|
||||
return config.errors.connection
|
||||
end
|
||||
|
||||
local url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' .. URL.escape(input)
|
||||
|
||||
local jstr, res = https.request(url)
|
||||
if res ~= 200 then
|
||||
return config.errors.connection
|
||||
end
|
||||
|
||||
local jdat = json.decode(jstr)
|
||||
if jdat.status == 'ZERO_RESULTS' then
|
||||
return config.errors.results
|
||||
end
|
||||
|
||||
return {
|
||||
lat = jdat.results[1].geometry.location.lat,
|
||||
lon = jdat.results[1].geometry.location.lng
|
||||
}
|
||||
local jdat = json.decode(jstr)
|
||||
if jdat.status == 'ZERO_RESULTS' then
|
||||
return config.errors.results
|
||||
end
|
||||
|
||||
return {
|
||||
lat = jdat.results[1].geometry.location.lat,
|
||||
lon = jdat.results[1].geometry.location.lng,
|
||||
addr = jdat.results[1].formatted_address
|
||||
}
|
||||
end
|
||||
|
||||
-- Get the number of values in a key/value table.
|
||||
@ -415,91 +397,15 @@ function utilities:resolve_username(input)
|
||||
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)
|
||||
|
||||
if not err then err = '' end
|
||||
|
||||
local output = '\n[' .. os.date('%F %T', os.time()) .. ']\n' .. self.info.username .. ': ' .. err .. '\n' .. message .. '\n'
|
||||
|
||||
if config.log_chat then
|
||||
output = '```' .. output .. '```'
|
||||
utilities.send_message(self, config.log_chat, output, true, nil, true)
|
||||
else
|
||||
print(output)
|
||||
end
|
||||
|
||||
if not err then err = '' end
|
||||
local output = '\n[' .. os.date('%F %T', os.time()) .. ']\n' .. self.info.username .. ': ' .. err .. '\n' .. message .. '\n'
|
||||
if config.log_chat then
|
||||
output = '```' .. output .. '```'
|
||||
utilities.send_message(self, config.log_chat, output, true, nil, true)
|
||||
else
|
||||
print(output)
|
||||
end
|
||||
end
|
||||
|
||||
-- MOVED TO DOWNLOAD_TO_FILE
|
||||
@ -507,15 +413,17 @@ function utilities.download_file(url, filename)
|
||||
return download_to_file(url, filename)
|
||||
end
|
||||
|
||||
function utilities.markdown_escape(text)
|
||||
text = text:gsub('_', '\\_')
|
||||
text = text:gsub('%[', '\\[')
|
||||
text = text:gsub('%*', '\\*')
|
||||
text = text:gsub('`', '\\`')
|
||||
return text
|
||||
function utilities.md_escape(text)
|
||||
return text:gsub('_', '\\_')
|
||||
:gsub('%[', '\\['):gsub('%]', '\\]')
|
||||
:gsub('%*', '\\*'):gsub('`', '\\`')
|
||||
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.__index = utilities.triggers_meta
|
||||
@ -591,7 +499,8 @@ utilities.char = {
|
||||
arabic = '[\216-\219][\128-\191]',
|
||||
rtl_override = '',
|
||||
rtl_mark = '',
|
||||
em_dash = '—'
|
||||
em_dash = '—',
|
||||
utf_8 = '[%z\1-\127\194-\244][\128-\191]',
|
||||
}
|
||||
|
||||
-- taken from http://stackoverflow.com/a/11130774/3163199
|
||||
@ -610,7 +519,7 @@ function plugins_names()
|
||||
for k, v in pairs(scandir("miku/plugins")) do
|
||||
-- Ends with .lua
|
||||
if (v:match(".lua$")) then
|
||||
table.insert(files, v)
|
||||
files[#files+1] = v
|
||||
end
|
||||
end
|
||||
return files
|
||||
@ -723,6 +632,7 @@ function post_petition(url, arguments, headers)
|
||||
if type(arguments) == "table" then
|
||||
source = helpers.url_encode_arguments(arguments)
|
||||
end
|
||||
|
||||
if not headers then
|
||||
request_constructor.headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF8"
|
||||
request_constructor.headers["X-Accept"] = "application/json"
|
||||
@ -800,8 +710,8 @@ function get_location(user_id)
|
||||
end
|
||||
end
|
||||
|
||||
function cache_data(plugin, query, data, timeout, typ)
|
||||
-- How to: cache_data(pluginname, query_name, data_to_cache, expire_in_seconds)
|
||||
function cache_data(plugin, query, data, timeout, typ, hash_field)
|
||||
-- How to: cache_data(pluginname, query_name, data_to_cache, expire_in_seconds, type, hash_field (if hash))
|
||||
local hash = 'telegram:cache:'..plugin..':'..query
|
||||
if timeout then
|
||||
print('Caching "'..query..'" from plugin '..plugin..' (expires in '..timeout..' seconds)')
|
||||
@ -819,7 +729,7 @@ function cache_data(plugin, query, data, timeout, typ)
|
||||
redis:sadd(hash, str)
|
||||
end
|
||||
else
|
||||
redis:hmset(hash, data)
|
||||
redis:hset(hash, hash_field, data)
|
||||
end
|
||||
if timeout then
|
||||
redis:expire(hash, timeout)
|
||||
@ -841,6 +751,8 @@ function cache_file(result, url, last_modified)
|
||||
elseif result.result.photo then
|
||||
local lv = #result.result.photo
|
||||
file_id = result.result.photo[lv].file_id
|
||||
elseif result.result.sticker then
|
||||
file_id = result.result.sticker.file_id
|
||||
end
|
||||
print('Caching File...')
|
||||
redis:hset(hash..':'..url, 'file_id', file_id)
|
||||
|
Reference in New Issue
Block a user