Ü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]
|
[*.lua]
|
||||||
charset = utf-8
|
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.
|
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 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 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
|
##Anleitung
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ Brawlbot v2 ist freie Software; du darfst in modifizieren und weiterverbreiten,
|
|||||||
# Für User
|
# Für User
|
||||||
## Setup
|
## Setup
|
||||||
### Ubuntu und Debian
|
### 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
|
### Setup
|
||||||
Du benötigst **Lua 5.2+**, eine aktive **Redis-Instanz** und die folgenden **LuaRocks-Module**:
|
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
|
## Plugins
|
||||||
Brawlbot benutzt ein Plugin-System, ähnlich Yagops [Telegram-Bot](http://github.com/yagop/telegram-bot).
|
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? |
|
| Komponente | Beschreibung | Benötigt? |
|
||||||
|:------------------|:---------------------------------------------|:----------|
|
|:------------------|:---------------------------------------------|:----------|
|
||||||
| `plugin:action` | Hauptfunktion. Benötigt `msg` als Argument, empfohlen wird auch `matches` als drittes Argument nach `config` | J |
|
| `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:init` | Optionale Funkion, die beim Start geladen wird | N |
|
||||||
| `plugin:cron` | Wird jede Minute ausgeführt | N |
|
| `plugin:cron` | Wird jede Minute ausgeführt | N |
|
||||||
| `plugin.command` | Einfaches Kommando mit Syntax. Wird bei `/hilfe` gelistet | N |
|
| `plugin.command` | Einfaches Kommando mit Syntax. Wird bei `/hilfe` gelistet | N |
|
||||||
| `plugin.doc` | Plugin-Hilfe. Wird mit `/help $kommando` gelistet | N |
|
| `plugin.doc` | Plugin-Hilfe. Wird mit `/help $kommando` gelistet | N |
|
||||||
| `plugin.error` | Plugin-spezifische Fehlermeldung | 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`.
|
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.
|
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.
|
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.userdata` speichert Daten von verschiedenen Plugins, hierzu wird aber für Brawlbot-Plugins Redis verwendet.
|
||||||
|
|
||||||
`database.version` speichert die Bot-Version.
|
`database.version` speichert die Bot-Version.
|
||||||
|
|
||||||
* * *
|
|
@ -14,7 +14,7 @@ return {
|
|||||||
cli_port = 4567,
|
cli_port = 4567,
|
||||||
-- The block of text returned by /start.
|
-- The block of text returned by /start.
|
||||||
about_text = [[
|
about_text = [[
|
||||||
Dies ist die BETA-Version von Brawlbot v2.
|
Dies ist die BETA-Version von Mikubot v2.
|
||||||
|
|
||||||
Sende /hilfe, um zu starten
|
Sende /hilfe, um zu starten
|
||||||
]],
|
]],
|
||||||
@ -35,43 +35,20 @@ Sende /hilfe, um zu starten
|
|||||||
syntax = 'Invalide Syntax.',
|
syntax = 'Invalide Syntax.',
|
||||||
chatter_connection = 'Ich möchte gerade nicht reden',
|
chatter_connection = 'Ich möchte gerade nicht reden',
|
||||||
chatter_response = 'Ich weiß nicht, was ich darauf antworten soll.'
|
chatter_response = 'Ich weiß nicht, was ich darauf antworten soll.'
|
||||||
}
|
},
|
||||||
|
|
||||||
plugins = { -- To enable a plugin, add its name to the list.
|
remind = {
|
||||||
'control',
|
persist = true,
|
||||||
'blacklist',
|
max_length = 1000,
|
||||||
'about',
|
max_duration = 526000,
|
||||||
'ping',
|
max_reminders_group = 10,
|
||||||
'whoami',
|
max_reminders_private = 50
|
||||||
'nick',
|
},
|
||||||
'echo',
|
|
||||||
'imgblacklist',
|
chatter = {
|
||||||
'gImages',
|
cleverbot_api = 'https://brawlbot.tk/apis/chatter-bot-api/cleverbot.php?text=',
|
||||||
'gSearch',
|
connection = 'I don\'t feel like talking right now.',
|
||||||
'gMaps',
|
response = 'I don\'t know what to say to that.'
|
||||||
'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'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -3,7 +3,6 @@
|
|||||||
otouto's bindings for the Telegram bot API.
|
otouto's bindings for the Telegram bot API.
|
||||||
https://core.telegram.org/bots/api
|
https://core.telegram.org/bots/api
|
||||||
Copyright 2016 topkecleon. Published under the AGPLv3.
|
Copyright 2016 topkecleon. Published under the AGPLv3.
|
||||||
|
|
||||||
See the "Bindings" section of README.md for usage information.
|
See the "Bindings" section of README.md for usage information.
|
||||||
]]--
|
]]--
|
||||||
|
|
||||||
@ -48,7 +47,7 @@ function bindings:request(method, parameters, file)
|
|||||||
end
|
end
|
||||||
local response = {}
|
local response = {}
|
||||||
local body, boundary = MP_ENCODE(parameters)
|
local body, boundary = MP_ENCODE(parameters)
|
||||||
local success = HTTPS.request{
|
local success, code = HTTPS.request{
|
||||||
url = self.BASE_URL .. method,
|
url = self.BASE_URL .. method,
|
||||||
method = 'POST',
|
method = 'POST',
|
||||||
headers = {
|
headers = {
|
||||||
@ -60,7 +59,7 @@ function bindings:request(method, parameters, file)
|
|||||||
}
|
}
|
||||||
local data = table.concat(response)
|
local data = table.concat(response)
|
||||||
if not success then
|
if not success then
|
||||||
print(method .. ': Connection error.')
|
print(method .. ': Connection error. [' .. code .. ']')
|
||||||
return false, false
|
return false, false
|
||||||
else
|
else
|
||||||
local result = JSON.decode(data)
|
local result = JSON.decode(data)
|
||||||
|
154
miku/bot.lua
154
miku/bot.lua
@ -3,20 +3,20 @@ local bot = {}
|
|||||||
bindings = require('miku.bindings')
|
bindings = require('miku.bindings')
|
||||||
utilities = require('miku.utilities')
|
utilities = require('miku.utilities')
|
||||||
|
|
||||||
bot.version = '160801'
|
bot.version = '160815'
|
||||||
|
|
||||||
function bot:init(config) -- The function run when the bot is started or reloaded.
|
function bot:init(config) -- The function run when the bot is started or reloaded.
|
||||||
cred_data = load_cred()
|
cred_data = load_cred()
|
||||||
|
|
||||||
assert(
|
assert(
|
||||||
config.bot_api_key and config.bot_api_key ~= '',
|
config.bot_api_key,
|
||||||
'You did not set your bot token in the config!'
|
'You did not set your bot token in the config!'
|
||||||
)
|
)
|
||||||
self.BASE_URL = 'https://api.telegram.org/bot' .. config.bot_api_key .. '/'
|
self.BASE_URL = 'https://api.telegram.org/bot' .. config.bot_api_key .. '/'
|
||||||
|
|
||||||
-- Fetch bot information. Try until it succeeds.
|
-- Fetch bot information. Try until it succeeds.
|
||||||
repeat
|
repeat
|
||||||
print('Fetching bot information...')
|
print('Sammel Bot-Informationen...')
|
||||||
self.info = bindings.getMe(self)
|
self.info = bindings.getMe(self)
|
||||||
until self.info
|
until self.info
|
||||||
self.info = self.info.result
|
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')
|
self.database = utilities.load_data(self.info.username..'.db')
|
||||||
end
|
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.
|
self.plugins = {} -- Load plugins.
|
||||||
enabled_plugins = load_plugins()
|
enabled_plugins = load_plugins()
|
||||||
for k,v in pairs(enabled_plugins) do
|
for k,v in pairs(enabled_plugins) do
|
||||||
local p = require('miku.plugins.'..v)
|
local p = require('miku.plugins.'..v)
|
||||||
-- print('loading plugin',v)
|
-- print('loading plugin',v)
|
||||||
table.insert(self.plugins, p)
|
self.plugins[k] = p
|
||||||
self.plugins[k].name = v
|
self.plugins[k].name = v
|
||||||
if p.init then p.init(self, config) end
|
if p.init then p.init(self, config) end
|
||||||
end
|
end
|
||||||
|
|
||||||
print('Bot wurde erfolgreich gestartet!\n@' .. self.info.username .. ', AKA ' .. self.info.first_name ..' ('..self.info.id..')')
|
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,
|
-- Set loop variables
|
||||||
self.last_cron = self.last_cron or os.date('%M') -- the time of the last cron job,
|
self.last_update = self.last_update or 0 -- Update offset.
|
||||||
self.last_database_save = self.last_database_save or os.date('%H') -- the time of the last database save,
|
self.last_cron = self.last_cron or os.date('%M') -- Last cron job.
|
||||||
|
self.last_database_save = self.last_database_save or os.date('%H') -- Last db save.
|
||||||
self.is_started = true -- and whether or not the bot should be running.
|
self.is_started = true -- and whether or not the bot should be running.
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function bot:on_msg_receive(msg, config) -- The fn run whenever a message is received.
|
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.
|
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)
|
msg = utilities.enrich_message(msg)
|
||||||
|
|
||||||
if msg.reply_to_message then
|
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()
|
msg.text_lower = msg.text:lower()
|
||||||
end
|
end
|
||||||
msg = pre_process_msg(self, msg, config)
|
msg = pre_process_msg(self, msg, config)
|
||||||
|
if not msg then return end -- deleted by banning
|
||||||
|
|
||||||
if is_service_msg(msg) then
|
if is_service_msg(msg) then
|
||||||
msg = service_modify_msg(msg)
|
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
|
if not callback.data:find(':') or not callback.data:find('@'..self.info.username..' ') then
|
||||||
return
|
return
|
||||||
end
|
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..' ', "")
|
callback.data = string.gsub(callback.data, '@'..self.info.username..' ', "")
|
||||||
local called_plugin = callback.data:match('(.*):.*')
|
local called_plugin = callback.data:match('(.*):.*')
|
||||||
local param = callback.data:sub(callback.data:find(':')+1)
|
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)
|
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 plugin.name == called_plugin then
|
||||||
if is_plugin_disabled_on_chat(plugin.name, msg) then return end
|
if is_plugin_disabled_on_chat(plugin.name, msg) then return end
|
||||||
plugin:callback(callback, msg, self, config, param)
|
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
|
-- remove comment to enable debugging
|
||||||
-- vardump(inline_query)
|
-- 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
|
if not config.enable_inline_for_everyone then
|
||||||
local is_whitelisted = redis:get('whitelist:user#id'..inline_query.from.id)
|
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
|
end
|
||||||
|
|
||||||
if inline_query.query:match('"') then
|
if inline_query.query:match('"') then
|
||||||
inline_query.query = inline_query.query:gsub('"', '\\"')
|
inline_query.query = inline_query.query:gsub('"', '\\"')
|
||||||
end
|
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)
|
match_inline_plugins(self, inline_query, config, plugin)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Stop the spinning circle
|
||||||
|
utilities.answer_inline_query(self, inline_query, nil, 0, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
function bot:run(config)
|
function bot:run(config)
|
||||||
bot.init(self, config) -- Actually start the script.
|
bot.init(self, config)
|
||||||
|
|
||||||
while self.is_started do -- Start a loop while the bot should be running.
|
while self.is_started do
|
||||||
local res = bindings.getUpdates(self, { timeout=20, offset = self.last_update+1 } )
|
-- Update loop
|
||||||
|
local res = bindings.getUpdates(self, { timeout = 20, offset = self.last_update+1 } )
|
||||||
if res then
|
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
|
self.last_update = v.update_id
|
||||||
if v.inline_query then
|
if v.inline_query then
|
||||||
bot.process_inline_query(self, v.inline_query, config)
|
bot.process_inline_query(self, v.inline_query, config)
|
||||||
@ -169,10 +201,12 @@ function bot:run(config)
|
|||||||
print('Connection error while fetching updates.')
|
print('Connection error while fetching updates.')
|
||||||
end
|
end
|
||||||
|
|
||||||
if self.last_cron ~= os.date('%M') then -- Run cron jobs every minute.
|
-- Run cron jobs every minute.
|
||||||
|
if self.last_cron ~= os.date('%M') then
|
||||||
self.last_cron = os.date('%M')
|
self.last_cron = os.date('%M')
|
||||||
utilities.save_data(self.info.username..'.db', self.database) -- Save the database.
|
utilities.save_data(self.info.username..'.db', self.database) -- Save the database.
|
||||||
for 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.
|
if v.cron then -- Call each plugin's cron function, if it has one.
|
||||||
local result, err = pcall(function() v.cron(self, config) end)
|
local result, err = pcall(function() v.cron(self, config) end)
|
||||||
if not result then
|
if not result then
|
||||||
@ -194,7 +228,8 @@ end
|
|||||||
|
|
||||||
-- Apply plugin.pre_process function
|
-- Apply plugin.pre_process function
|
||||||
function pre_process_msg(self, msg, config)
|
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
|
if plugin.pre_process and msg then
|
||||||
-- print('Preprocess '..plugin.name) -- remove comment to restore old behaviour
|
-- print('Preprocess '..plugin.name) -- remove comment to restore old behaviour
|
||||||
new_msg = plugin:pre_process(msg, self, config)
|
new_msg = plugin:pre_process(msg, self, config)
|
||||||
@ -204,7 +239,9 @@ function pre_process_msg(self, msg, config)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function match_inline_plugins(self, inline_query, config, plugin)
|
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
|
if string.match(string.lower(inline_query.query), trigger) then
|
||||||
local success, result = pcall(function()
|
local success, result = pcall(function()
|
||||||
for k, pattern in pairs(plugin.inline_triggers) do
|
for k, pattern in pairs(plugin.inline_triggers) do
|
||||||
@ -216,51 +253,34 @@ function match_inline_plugins(self, inline_query, config, plugin)
|
|||||||
print('Inline: '..plugin.name..' ausgelöst')
|
print('Inline: '..plugin.name..' ausgelöst')
|
||||||
return plugin.inline_callback(self, inline_query, config, matches)
|
return plugin.inline_callback(self, inline_query, config, matches)
|
||||||
end)
|
end)
|
||||||
if not success then
|
|
||||||
print(result)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function match_plugins(self, msg, config, plugin)
|
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
|
if string.match(msg.text_lower, trigger) then
|
||||||
-- Check if Plugin is disabled
|
-- Check if Plugin is disabled
|
||||||
if is_plugin_disabled_on_chat(plugin.name, msg) then return end
|
if is_plugin_disabled_on_chat(plugin.name, msg) then return end
|
||||||
local success, result = pcall(function()
|
local success, result = pcall(function()
|
||||||
-- trying to port matches to miku
|
-- trying to port matches to miku
|
||||||
for k, pattern in pairs(plugin.triggers) do
|
local pattern = plugin.triggers[n]
|
||||||
matches = match_pattern(pattern, msg.text)
|
local matches = match_pattern(pattern, msg.text)
|
||||||
if matches then
|
if matches then
|
||||||
break;
|
print('msg matches: ', pattern, ' for "'..plugin.name..'"')
|
||||||
end
|
|
||||||
end
|
|
||||||
print(plugin.name..' ausgelöst')
|
|
||||||
return plugin.action(self, msg, config, matches)
|
return plugin.action(self, msg, config, matches)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
if not success then
|
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)
|
|
||||||
end
|
|
||||||
utilities.handle_exception(self, result, msg.from.id .. ': ' .. msg.text, config)
|
utilities.handle_exception(self, result, msg.from.id .. ': ' .. msg.text, config)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
-- if one pattern matches, 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
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function is_plugin_disabled_on_chat(plugin_name, msg)
|
function is_plugin_disabled_on_chat(plugin_name, msg)
|
||||||
@ -294,7 +314,7 @@ function create_plugin_set()
|
|||||||
'banhammer',
|
'banhammer',
|
||||||
'channels',
|
'channels',
|
||||||
'plugins',
|
'plugins',
|
||||||
'help',
|
'help'
|
||||||
}
|
}
|
||||||
print ('Aktiviere Plugins und speicher in telegram:enabled_plugins')
|
print ('Aktiviere Plugins und speicher in telegram:enabled_plugins')
|
||||||
for _,plugin in pairs(enabled_plugins) do
|
for _,plugin in pairs(enabled_plugins) do
|
||||||
|
@ -31,13 +31,15 @@ end
|
|||||||
|
|
||||||
function ninegag:inline_callback(inline_query, config)
|
function ninegag:inline_callback(inline_query, config)
|
||||||
local res, code = http.request(url)
|
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 gag = json.decode(res)
|
||||||
|
|
||||||
local results = '['
|
local results = '['
|
||||||
|
local id = 50
|
||||||
for n in pairs(gag) do
|
for n in pairs(gag) do
|
||||||
local title = gag[n].title:gsub('"', '\\"')
|
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
|
if n < #gag then
|
||||||
results = results..','
|
results = results..','
|
||||||
end
|
end
|
||||||
|
@ -5,33 +5,16 @@ local bot = require('miku.bot')
|
|||||||
about.command = 'about'
|
about.command = 'about'
|
||||||
about.doc = '`Sendet Informationen über den Bot.`'
|
about.doc = '`Sendet Informationen über den Bot.`'
|
||||||
|
|
||||||
about.triggers = {
|
function about:init(config)
|
||||||
|
about.text = config.about_text .. '\n[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]',
|
'/[Aa][Bb][Oo][Uu][Tt]',
|
||||||
'/[Ss][Tt][Aa][Rr][Tt]'
|
'/[Ss][Tt][Aa][Rr][Tt]'
|
||||||
}
|
}
|
||||||
|
end
|
||||||
|
|
||||||
function about:action(msg, config)
|
function about:action(msg, config)
|
||||||
|
utilities.send_message(self, msg.chat.id, about.text, true, nil, true)
|
||||||
-- Filthy hack, but here is where we'll stop forwarded messages from hitting
|
|
||||||
-- other plugins.
|
|
||||||
-- disabled to restore old behaviour
|
|
||||||
-- if msg.forward_from then return end
|
|
||||||
|
|
||||||
local output = config.about_text .. '\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
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return about
|
return about
|
@ -27,10 +27,10 @@ function adfly:inline_callback(inline_query, config, matches)
|
|||||||
url = redis:get(hash)
|
url = redis:get(hash)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not url then return end
|
if not url then utilities.answer_inline_query(self, inline_query) return end
|
||||||
if url == 'NOTFOUND' then 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)
|
utilities.answer_inline_query(self, inline_query, results, 3600, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ function afk:pre_process(msg, self)
|
|||||||
local user_id = msg.from.id
|
local user_id = msg.from.id
|
||||||
local chat_id = msg.chat.id
|
local chat_id = msg.chat.id
|
||||||
local hash = 'afk:'..chat_id..':'..user_id
|
local hash = 'afk:'..chat_id..':'..user_id
|
||||||
|
local uhash = 'user:'..user_id
|
||||||
|
|
||||||
if afk:is_offline(hash) then
|
if afk:is_offline(hash) then
|
||||||
local afk_text = afk:get_afk_text(hash)
|
local afk_text = afk:get_afk_text(hash)
|
||||||
@ -80,18 +80,27 @@ function afk:pre_process(msg, self)
|
|||||||
local duration = makeHumanTime(afk_time)
|
local duration = makeHumanTime(afk_time)
|
||||||
|
|
||||||
redis:hset(hash, 'afk', false)
|
redis:hset(hash, 'afk', false)
|
||||||
|
local show_afk_keyboard = redis:hget(uhash, 'afk_keyboard')
|
||||||
if afk_text then
|
if afk_text then
|
||||||
redis:hset(hash, 'afk_text', false)
|
redis:hset(hash, 'afk_text', false)
|
||||||
|
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}')
|
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
|
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
|
||||||
|
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}')
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
return msg
|
return msg
|
||||||
end
|
end
|
||||||
|
|
||||||
function afk:action(msg)
|
function afk:action(msg, config, matches)
|
||||||
if msg.chat.type == "private" then
|
if msg.chat.type == "private" then
|
||||||
utilities.send_reply(self, msg, "Mir ist's egal, ob du AFK bist.")
|
utilities.send_reply(self, msg, "Mir ist's egal, ob du AFK bist.")
|
||||||
return
|
return
|
||||||
|
@ -36,11 +36,13 @@ function bImages:getImages(query)
|
|||||||
|
|
||||||
|
|
||||||
local results = '['
|
local results = '['
|
||||||
|
local id = 300
|
||||||
for n in pairs(images) do
|
for n in pairs(images) do
|
||||||
if images[n].encodingFormat == 'jpeg' then -- Inline-Querys MUST use JPEG photos!
|
if images[n].encodingFormat == 'jpeg' then -- Inline-Querys MUST use JPEG photos!
|
||||||
local photo_url = images[n].contentUrl
|
local photo_url = images[n].contentUrl
|
||||||
local thumb_url = images[n].thumbnailUrl
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -57,7 +59,7 @@ function bImages:inline_callback(inline_query, config, matches)
|
|||||||
results = bImages:getImages(query)
|
results = bImages:getImages(query)
|
||||||
end
|
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)
|
utilities.answer_inline_query(self, inline_query, results, 3600)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -12,7 +12,17 @@ function banhammer:init(config)
|
|||||||
"^/(whitelist) (delete) (chat)$",
|
"^/(whitelist) (delete) (chat)$",
|
||||||
"^/(ban) (user) (%d+)$",
|
"^/(ban) (user) (%d+)$",
|
||||||
"^/(ban) (delete) (%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 = [[*
|
banhammer.doc = [[*
|
||||||
]]..config.cmd_pat..[[whitelist* _<enable>_/_<disable>_: Aktiviert/deaktiviert Whitelist
|
]]..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..[[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* 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..[[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
|
end
|
||||||
|
|
||||||
function banhammer:kick_user(user_id, chat_id, self, onlykick)
|
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)
|
function banhammer:unban_user(user_id, chat_id, self, chat_type)
|
||||||
local hash = 'banned:'..chat_id..':'..user_id
|
local hash = 'banned:'..chat_id..':'..user_id
|
||||||
redis:del(hash)
|
redis:del(hash)
|
||||||
if chat_type == 'supergroup' then -- how can bots be admins anyway?
|
if chat_type == 'supergroup' then
|
||||||
local request = bindings.request(self, 'unbanChatMember', {
|
bindings.request(self, 'unbanChatMember', {
|
||||||
chat_id = chat_id,
|
chat_id = chat_id,
|
||||||
user_id = user_id
|
user_id = user_id
|
||||||
} )
|
} )
|
||||||
@ -96,76 +110,94 @@ function banhammer:pre_process(msg, self, config)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- BANNED USER TALKING
|
-- BANNED USER TALKING
|
||||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
|
||||||
local user_id = msg.from.id
|
local user_id = msg.from.id
|
||||||
local chat_id = msg.chat.id
|
local chat_id = msg.chat.id
|
||||||
|
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||||
local banned = banhammer:is_banned(user_id, chat_id)
|
local banned = banhammer:is_banned(user_id, chat_id)
|
||||||
if banned then
|
if banned then
|
||||||
print('Banned user talking!')
|
print('Banned user talking!')
|
||||||
banhammer:ban_user(user_id, chat_id, self)
|
banhammer:ban_user(user_id, chat_id, self)
|
||||||
msg.text = ''
|
return
|
||||||
end
|
end
|
||||||
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 hash = 'whitelist:enabled'
|
||||||
local whitelist = redis:get(hash)
|
local whitelist = redis:get(hash)
|
||||||
local issudo = is_sudo(msg, config)
|
|
||||||
|
|
||||||
-- Allow all sudo users even if whitelist is allowed
|
-- Allow all sudo users even if whitelist is allowed
|
||||||
if whitelist and not issudo then
|
if whitelist and not issudo then
|
||||||
print('Whitelist enabled and not sudo')
|
print('Whitelist enabled and not sudo')
|
||||||
-- Check if user or chat is whitelisted
|
-- Check if user or chat is whitelisted
|
||||||
local allowed = banhammer:is_user_whitelisted(msg.from.id)
|
local allowed = banhammer:is_user_whitelisted(user_id)
|
||||||
local has_been_warned = redis:hget('user:'..msg.from.id, 'has_been_warned')
|
local has_been_warned = redis:hget('user:'..user_id, 'has_been_warned')
|
||||||
|
|
||||||
if not allowed then
|
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
|
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
|
if not allowed then
|
||||||
print ('Chat '..msg.chat.id..' not whitelisted')
|
print ('Chat '..chat_id..' not whitelisted')
|
||||||
else
|
else
|
||||||
print ('Chat '..msg.chat.id..' whitelisted :)')
|
print ('Chat '..chat_id..' whitelisted :)')
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if not has_been_warned then
|
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.")
|
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
|
else
|
||||||
print('User has already been warned!')
|
print('User has already been warned!')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
print('User '..msg.from.id..' allowed :)')
|
print('User '..user_id..' allowed :)')
|
||||||
end
|
end
|
||||||
|
|
||||||
if not allowed then
|
if not allowed then
|
||||||
msg.text = ''
|
return
|
||||||
msg.text_lower = ''
|
|
||||||
msg.entities = ''
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- else
|
|
||||||
-- print('Whitelist not enabled or is sudo')
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return msg
|
return msg
|
||||||
end
|
end
|
||||||
|
|
||||||
function banhammer:action(msg, config, matches)
|
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)
|
utilities.send_reply(self, msg, config.errors.sudo)
|
||||||
return
|
return
|
||||||
end
|
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
|
if matches[1] == 'ban' then
|
||||||
local user_id = matches[3]
|
local user_id = matches[3]
|
||||||
local chat_id = msg.chat.id
|
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 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)
|
local text = banhammer:ban_user(user_id, chat_id, self)
|
||||||
utilities.send_reply(self, msg, text)
|
utilities.send_reply(self, msg, text)
|
||||||
return
|
return
|
||||||
@ -183,7 +215,14 @@ function banhammer:action(msg, config, matches)
|
|||||||
|
|
||||||
if matches[1] == 'kick' then
|
if matches[1] == 'kick' then
|
||||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' 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
|
return
|
||||||
else
|
else
|
||||||
utilities.send_reply(self, msg, 'Das ist keine Chat-Gruppe')
|
utilities.send_reply(self, msg, 'Das ist keine Chat-Gruppe')
|
||||||
@ -206,6 +245,28 @@ function banhammer:action(msg, config, matches)
|
|||||||
return
|
return
|
||||||
end
|
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
|
if matches[2] == 'user' then
|
||||||
local hash = 'whitelist:user#id'..matches[3]
|
local hash = 'whitelist:user#id'..matches[3]
|
||||||
redis:set(hash, true)
|
redis:set(hash, true)
|
||||||
@ -244,6 +305,46 @@ function banhammer:action(msg, config, matches)
|
|||||||
end
|
end
|
||||||
end
|
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
|
end
|
||||||
|
|
||||||
return banhammer
|
return banhammer
|
@ -38,9 +38,9 @@ function bitly:inline_callback(inline_query, config, matches)
|
|||||||
url = data.long_url
|
url = data.long_url
|
||||||
end
|
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)
|
utilities.answer_inline_query(self, inline_query, results, 3600)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ cats.command = 'kitty [gif]'
|
|||||||
function cats:init(config)
|
function cats:init(config)
|
||||||
if not cred_data.cat_apikey then
|
if not cred_data.cat_apikey then
|
||||||
print('Fehlender Key: cat_apikey.')
|
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
|
end
|
||||||
|
|
||||||
cats.triggers = {
|
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)
|
function cats:inline_callback(inline_query, config, matches)
|
||||||
if matches[1] == 'gif' then
|
if matches[1] == 'gif' then
|
||||||
img_type = 'gif'
|
img_type = 'gif'
|
||||||
|
id = 100
|
||||||
else
|
else
|
||||||
img_type = 'jpg'
|
img_type = 'jpg'
|
||||||
|
id = 200
|
||||||
end
|
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 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)
|
local res, code = https.request(url)
|
||||||
@ -43,9 +45,11 @@ function cats:inline_callback(inline_query, config, matches)
|
|||||||
|
|
||||||
for n in pairs(data) do
|
for n in pairs(data) do
|
||||||
if img_type == 'gif' then
|
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
|
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
|
end
|
||||||
if n < #data then
|
if n < #data then
|
||||||
results = results..','
|
results = results..','
|
||||||
|
@ -2,22 +2,30 @@ local cleverbot = {}
|
|||||||
|
|
||||||
function cleverbot:init(config)
|
function cleverbot:init(config)
|
||||||
cleverbot.triggers = {
|
cleverbot.triggers = {
|
||||||
"^/[Cc][Bb][Oo][Tt] (.*)$"
|
"^/[Cc][Bb][Oo][Tt] (.*)$",
|
||||||
|
"^[Mm][Ii][Kk][Uu][Bb][Oo][Tt], (.+)$",
|
||||||
}
|
}
|
||||||
|
cleverbot.url = config.chatter.cleverbot_api
|
||||||
cleverbot.doc = [[*
|
|
||||||
]]..config.cmd_pat..[[cbot* _<Text>_*: Befragt den Cleverbot]]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
cleverbot.command = 'cbot <Text>'
|
cleverbot.command = 'cbot <Text>'
|
||||||
|
|
||||||
function cleverbot:action(msg, config)
|
function cleverbot:action(msg, config, matches)
|
||||||
local text = msg.text
|
utilities.send_typing(self, msg.chat.id, 'typing')
|
||||||
local url = "https://brawlbot.tk/apis/chatter-bot-api/cleverbot.php?text="..URL.escape(text)
|
local text = matches[1]
|
||||||
local query = https.request(url)
|
local query, code = https.request(cleverbot.url..URL.escape(text))
|
||||||
if query == nil then utilities.send_reply(self, msg, 'Ein Fehler ist aufgetreten :(') return end
|
if code ~= 200 then
|
||||||
local decode = json.decode(query)
|
utilities.send_reply(self, msg, 'Ich möchte jetzt nicht reden...')
|
||||||
local answer = string.gsub(decode.clever, "Ä", "Ä")
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local data = json.decode(query)
|
||||||
|
if not data.clever then
|
||||||
|
utilities.send_reply(self, msg, 'Ich möchte jetzt nicht reden...')
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local answer = string.gsub(data.clever, "Ä", "Ä")
|
||||||
local answer = string.gsub(answer, "ä", "ä")
|
local answer = string.gsub(answer, "ä", "ä")
|
||||||
local answer = string.gsub(answer, "Ö", "Ö")
|
local answer = string.gsub(answer, "Ö", "Ö")
|
||||||
local answer = string.gsub(answer, "ö", "ö")
|
local answer = string.gsub(answer, "ö", "ö")
|
||||||
|
@ -4,57 +4,119 @@ currency.command = 'cash [Menge] <von> <zu>'
|
|||||||
|
|
||||||
function currency:init(config)
|
function currency:init(config)
|
||||||
currency.triggers = {
|
currency.triggers = {
|
||||||
"^/[Cc][Aa][Ss][Hh] ([A-Za-z]+)$",
|
"^/cash ([A-Za-z]+)$",
|
||||||
"^/[Cc][Aa][Ss][Hh] ([A-Za-z]+) ([A-Za-z]+)$",
|
"^/cash ([A-Za-z]+) ([A-Za-z]+)$",
|
||||||
"^/[Cc][Aa][Ss][Hh] (%d+[%d%.,]*) ([A-Za-z]+) ([A-Za-z]+)$",
|
"^/cash (%d+[%d%.,]*) ([A-Za-z]+) ([A-Za-z]+)$",
|
||||||
"^(/[Ee][Uu][Rr])$"
|
"^(/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 = [[*
|
currency.doc = [[*
|
||||||
]]..config.cmd_pat..[[cash* _[Menge]_ _<von>_ _<zu>_
|
]]..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_]]
|
Beispiel: _]]..config.cmd_pat..[[cash 5 USD EUR_]]
|
||||||
end
|
end
|
||||||
|
|
||||||
function currency:action(msg, config)
|
local BASE_URL = 'https://api.fixer.io'
|
||||||
if not matches[2] then
|
|
||||||
from = string.upper(matches[1])
|
function currency:inline_callback(inline_query, config, matches)
|
||||||
to = 'EUR'
|
if not matches[2] then -- first pattern
|
||||||
|
base = 'EUR'
|
||||||
|
to = string.upper(matches[1])
|
||||||
amount = 1
|
amount = 1
|
||||||
elseif matches[3] then
|
elseif matches[3] then -- third pattern
|
||||||
from = string.upper(matches[2])
|
base = string.upper(matches[2])
|
||||||
to = string.upper(matches[3])
|
to = string.upper(matches[3])
|
||||||
amount = matches[1]
|
amount = matches[1]
|
||||||
else
|
else -- second pattern
|
||||||
from = string.upper(matches[1])
|
base = string.upper(matches[1])
|
||||||
to = string.upper(matches[2])
|
to = string.upper(matches[2])
|
||||||
amount = 1
|
amount = 1
|
||||||
end
|
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, ",", ".")
|
local amount = string.gsub(amount, ",", ".")
|
||||||
amount = tonumber(amount)
|
local amount = tonumber(amount)
|
||||||
local result = 1
|
local res, code = https.request(url)
|
||||||
local BASE_URL = 'https://www.google.com/finance/converter'
|
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
|
if from == to then
|
||||||
utilities.send_reply(self, msg, 'Jaja, sehr witzig...')
|
utilities.send_reply(self, msg, 'Jaja, sehr witzig...')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local url = BASE_URL..'?from='..from..'&to='..to..'&a='..amount
|
local value = currency:convert_money(base, to, amount)
|
||||||
local str, res = https.request(url)
|
if value == 'NOCONNECT' then
|
||||||
if res ~= 200 then
|
|
||||||
utilities.send_reply(self, msg, config.errors.connection)
|
utilities.send_reply(self, msg, config.errors.connection)
|
||||||
return
|
return
|
||||||
end
|
elseif value == 'WRONGBASE' then
|
||||||
|
utilities.send_reply(self, msg, 'Keine gültige Basiswährung.')
|
||||||
local str = str:match('<span class=bld>(.*) %u+</span>')
|
return
|
||||||
if not str then
|
elseif value == 'WRONGCONVERTRATE' 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)
|
utilities.send_reply(self, msg, 'Keine gültige Umwandlungswährung.')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local result = string.format('%.2f', str)
|
|
||||||
local result = string.gsub(result, "%.", ",")
|
|
||||||
|
|
||||||
local amount = tostring(string.gsub(amount, "%.", ","))
|
local output = amount..' '..base..' = *'..value..' '..to..'*'
|
||||||
local output = amount..' '..from..' = *'..result..' '..to..'*'
|
|
||||||
utilities.send_reply(self, msg, output, true)
|
utilities.send_reply(self, msg, output, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -18,15 +18,15 @@ function echo:inline_callback(inline_query, config, matches)
|
|||||||
|
|
||||||
-- enable custom markdown button
|
-- enable custom markdown button
|
||||||
if text:match('%[.*%]%(.*%)') or text:match('%*.*%*') or text:match('_.*_') or text:match('`.*`') then
|
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
|
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)
|
utilities.answer_inline_query(self, inline_query, results, 0)
|
||||||
end
|
end
|
||||||
|
|
||||||
function echo:action(msg)
|
function echo:action(msg)
|
||||||
local input = utilities.input(msg.text)
|
local input = utilities.input_from_msg(msg)
|
||||||
if not input then
|
if not input then
|
||||||
utilities.send_message(self, msg.chat.id, echo.doc, true, msg.message_id, true)
|
utilities.send_message(self, msg.chat.id, echo.doc, true, msg.message_id, true)
|
||||||
else
|
else
|
||||||
|
@ -26,7 +26,7 @@ function expand:inline_callback(inline_query, config, matches)
|
|||||||
description = url
|
description = url
|
||||||
end
|
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)
|
utilities.answer_inline_query(self, inline_query, results, 3600)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -8,13 +8,13 @@ function facebook:init(config)
|
|||||||
end
|
end
|
||||||
|
|
||||||
facebook.triggers = {
|
facebook.triggers = {
|
||||||
'facebook.com/([A-Za-z0-9-._-]+)/(posts)/(%d+)',
|
"facebook.com/([A-Za-z0-9-._-]+)/(posts)/(%d+)",
|
||||||
'facebook.com/(permalink).php%?(story_fbid)=(%d+)&id=(%d+)',
|
"facebook.com/(permalink).php%?(story_fbid)=(%d+)&id=(%d+)",
|
||||||
'facebook.com/(photo).php%?fbid=(%d+)',
|
"facebook.com/(photo).php%?fbid=(%d+)",
|
||||||
'facebook.com/([A-Za-z0-9-._-]+)/(photos)/a.(%d+[%d%.]*)/(%d+)',
|
"facebook.com/([A-Za-z0-9-._-]+)/(photos)/a.(%d+[%d%.]*)/(%d+)",
|
||||||
'facebook.com/(video).php%?v=(%d+)',
|
"facebook.com/(video).php%?v=(%d+)",
|
||||||
'facebook.com/([A-Za-z0-9-._-]+)/(videos)/(%d+[%d%.]*)',
|
"facebook.com/([A-Za-z0-9-._-]+)/(videos)/(%d+[%d%.]*)",
|
||||||
'facebook.com/([A-Za-z0-9-._-]+)'
|
"facebook.com/([A-Za-z0-9-._-]+)/?$"
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ local BASE_URL = 'https://graph.facebook.com/v2.5'
|
|||||||
local fb_access_token = cred_data.fb_access_token
|
local fb_access_token = cred_data.fb_access_token
|
||||||
|
|
||||||
local makeOurDate = function(dateString)
|
local makeOurDate = function(dateString)
|
||||||
local pattern = '(%d+)%/(%d+)%/(%d+)'
|
local pattern = "(%d+)%/(%d+)%/(%d+)"
|
||||||
local month, day, year = dateString:match(pattern)
|
local month, day, year = dateString:match(pattern)
|
||||||
return day..'.'..month..'.'..year
|
return day..'.'..month..'.'..year
|
||||||
end
|
end
|
||||||
@ -43,17 +43,18 @@ function facebook:fb_post (id, story_id)
|
|||||||
|
|
||||||
local from = data.from.name
|
local from = data.from.name
|
||||||
local message = data.message
|
local message = data.message
|
||||||
|
if not message then return nil end
|
||||||
local name = data.name
|
local name = data.name
|
||||||
if data.link then
|
if data.link then
|
||||||
link = '\n<a href="'..data.link..'">'..data.name..'</a>'
|
link = '\n<a href="'..data.link..'">'..data.name..'</a>'
|
||||||
else
|
else
|
||||||
link = ''
|
link = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
if data.story then
|
if data.story then
|
||||||
story = ' ('..data.story..')'
|
story = ' ('..data.story..')'
|
||||||
else
|
else
|
||||||
story = ''
|
story = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
local text = '<b>'..from..'</b>'..story..':\n'..message..'\n'..link
|
local text = '<b>'..from..'</b>'..story..':\n'..message..'\n'..link
|
||||||
@ -104,13 +105,13 @@ function facebook:facebook_info(name)
|
|||||||
if data.about then
|
if data.about then
|
||||||
about = '\n'..data.about
|
about = '\n'..data.about
|
||||||
else
|
else
|
||||||
about = ''
|
about = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
if data.general_info then
|
if data.general_info then
|
||||||
general_info = '\n'..data.general_info
|
general_info = '\n'..data.general_info
|
||||||
else
|
else
|
||||||
general_info = ''
|
general_info = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
if data.birthday and data.founded then
|
if data.birthday and data.founded then
|
||||||
@ -120,7 +121,7 @@ function facebook:facebook_info(name)
|
|||||||
elseif data.founded and not data.birthday then
|
elseif data.founded and not data.birthday then
|
||||||
birth = '\nGegründet: '..data.founded
|
birth = '\nGegründet: '..data.founded
|
||||||
else
|
else
|
||||||
birth = ''
|
birth = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
local text = '<b>'..name..'</b> ('..category..')<i>'..about..'</i>'..general_info..birth
|
local text = '<b>'..name..'</b> ('..category..')<i>'..about..'</i>'..general_info..birth
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
local forecast = {}
|
local forecast = {}
|
||||||
|
|
||||||
|
require("./miku/plugins/weather")
|
||||||
|
|
||||||
function forecast:init(config)
|
function forecast:init(config)
|
||||||
if not cred_data.forecastio_apikey then
|
if not cred_data.forecastio_apikey then
|
||||||
print('Fehlender Key: forecastio_apikey.')
|
print('Fehlender Key: forecastio_apikey.')
|
||||||
@ -21,6 +23,12 @@ function forecast:init(config)
|
|||||||
"^(/forecasth)$",
|
"^(/forecasth)$",
|
||||||
"^(/forecasth) (.*)$"
|
"^(/forecasth) (.*)$"
|
||||||
}
|
}
|
||||||
|
forecast.inline_triggers = {
|
||||||
|
"^(f) (.+)$",
|
||||||
|
"^(fh) (.+)$",
|
||||||
|
"^(fh)$",
|
||||||
|
"^(f)$"
|
||||||
|
}
|
||||||
forecast.doc = [[*
|
forecast.doc = [[*
|
||||||
]]..config.cmd_pat..[[f*: Wettervorhersage für deinen Wohnort _(/location set <Ort>)_
|
]]..config.cmd_pat..[[f*: Wettervorhersage für deinen Wohnort _(/location set <Ort>)_
|
||||||
*]]..config.cmd_pat..[[f* _<Ort>_: Wettervorhersage für diesen 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 apikey = cred_data.forecastio_apikey
|
||||||
local google_apikey = cred_data.google_apikey
|
local google_apikey = cred_data.google_apikey
|
||||||
|
|
||||||
function get_city_name(lat, lng)
|
function forecast:get_condition_symbol(weather_data)
|
||||||
local city = redis:hget('telegram:cache:weather:pretty_names', lat..','..lng)
|
if weather_data.icon == 'clear-day' then
|
||||||
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
|
|
||||||
return '☀️'
|
return '☀️'
|
||||||
elseif weather.data[n].icon == 'clear-night' then
|
elseif weather_data.icon == 'clear-night' then
|
||||||
return '🌙'
|
return '🌙'
|
||||||
elseif weather.data[n].icon == 'rain' then
|
elseif weather_data.icon == 'rain' then
|
||||||
return '☔️'
|
return '☔️'
|
||||||
elseif weather.data[n].icon == 'snow' then
|
elseif weather_data.icon == 'snow' then
|
||||||
return '❄️'
|
return '❄️'
|
||||||
elseif weather.data[n].icon == 'sleet' then
|
elseif weather_data.icon == 'sleet' then
|
||||||
return '🌨'
|
return '🌨'
|
||||||
elseif weather.data[n].icon == 'wind' then
|
elseif weather_data.icon == 'wind' then
|
||||||
return '💨'
|
return '💨'
|
||||||
elseif weather.data[n].icon == 'fog' then
|
elseif weather_data.icon == 'fog' then
|
||||||
return '🌫'
|
return '🌫'
|
||||||
elseif weather.data[n].icon == 'cloudy' then
|
elseif weather_data.icon == 'cloudy' then
|
||||||
return '☁️☁️'
|
return '☁️☁️'
|
||||||
elseif weather.data[n].icon == 'partly-cloudy-day' then
|
elseif weather_data.icon == 'partly-cloudy-day' then
|
||||||
return '🌤'
|
return '🌤'
|
||||||
elseif weather.data[n].icon == 'partly-cloudy-night' then
|
elseif weather_data.icon == 'partly-cloudy-night' then
|
||||||
return '🌙☁️'
|
return '🌙☁️'
|
||||||
else
|
else
|
||||||
return ''
|
return ''
|
||||||
@ -75,22 +70,34 @@ function get_condition_symbol(weather, n)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function get_temp(weather, n, hourly)
|
function get_temp(weather, n, hourly)
|
||||||
|
local weather_data = weather.data[n]
|
||||||
if hourly then
|
if hourly then
|
||||||
local temperature = string.gsub(round(weather.data[n].temperature, 1), "%.", ",")
|
local temperature = string.gsub(round(weather_data.temperature, 1), "%.", ",")
|
||||||
local condition = weather.data[n].summary
|
local condition = weather_data.summary
|
||||||
return temperature..'°C | '..get_condition_symbol(weather, n)..' '..condition
|
return temperature..'°C | '..forecast:get_condition_symbol(weather_data)..' '..condition
|
||||||
else
|
else
|
||||||
local day = string.gsub(round(weather.data[n].temperatureMax, 1), "%.", ",")
|
local day = string.gsub(round(weather_data.temperatureMax, 1), "%.", ",")
|
||||||
local night = string.gsub(round(weather.data[n].temperatureMin, 1), "%.", ",")
|
local night = string.gsub(round(weather_data.temperatureMin, 1), "%.", ",")
|
||||||
local condition = weather.data[n].summary
|
local condition = weather_data.summary
|
||||||
return '☀️ '..day..'°C | 🌙 '..night..'°C | '..get_condition_symbol(weather, n)..' '..condition
|
return '☀️ '..day..'°C | 🌙 '..night..'°C | '..forecast:get_condition_symbol(weather_data)..' '..condition
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function forecast:get_forecast(lat, lng)
|
function forecast:get_forecast(lat, lng, is_inline)
|
||||||
print('Finde Wetter in '..lat..', '..lng)
|
print('Finde Wetter in '..lat..', '..lng)
|
||||||
local text = redis:get('telegram:cache:forecast:'..lat..','..lng)
|
local hash = 'telegram:cache:forecast:'..lat..','..lng
|
||||||
if text then print('...aus dem Cache..') return text end
|
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'
|
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",
|
method = "GET",
|
||||||
sink = ltn12.sink.table(response_body)
|
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
|
if not ok then return nil end
|
||||||
local data = json.decode(table.concat(response_body))
|
local weather = json.decode(table.concat(response_body)).daily
|
||||||
local ttl = string.sub(response_headers["cache-control"], 9)
|
local ttl = tonumber(string.sub(response_headers["cache-control"], 9))
|
||||||
|
|
||||||
|
|
||||||
local weather = data.daily
|
|
||||||
local city = get_city_name(lat, lng)
|
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 = '*Heute:* '..get_temp(weather, 1)
|
||||||
local text = text..'\n*Morgen:* '..get_temp(weather, 2)
|
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
|
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
|
||||||
end
|
end
|
||||||
|
|
||||||
local text = string.gsub(text, "Mon", "Mo")
|
local text = text:gsub("Mon", "Mo")
|
||||||
local text = string.gsub(text, "Tue", "Di")
|
local text = text:gsub("Tue", "Di")
|
||||||
local text = string.gsub(text, "Wed", "Mi")
|
local text = text:gsub("Wed", "Mi")
|
||||||
local text = string.gsub(text, "Thu", "Do")
|
local text = text:gsub("Thu", "Do")
|
||||||
local text = string.gsub(text, "Fri", "Fr")
|
local text = text:gsub("Fri", "Fr")
|
||||||
local text = string.gsub(text, "Sat", "Sa")
|
local text = text:gsub("Sat", "Sa")
|
||||||
local text = string.gsub(text, "Sun", "So")
|
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)
|
||||||
|
|
||||||
|
if is_inline then
|
||||||
|
return city, weather_summary, header..text, ttl
|
||||||
|
else
|
||||||
return header..text
|
return header..text
|
||||||
|
end
|
||||||
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)
|
print('Finde stündliches Wetter in '..lat..', '..lng)
|
||||||
local text = redis:get('telegram:cache:forecast:'..lat..','..lng..':hourly')
|
local hash = 'telegram:cache:forecast:'..lat..','..lng..':hourly'
|
||||||
if text then print('...aus dem Cache..') return text end
|
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'
|
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",
|
method = "GET",
|
||||||
sink = ltn12.sink.table(response_body)
|
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
|
if not ok then return nil end
|
||||||
local data = json.decode(table.concat(response_body))
|
local weather = json.decode(table.concat(response_body)).hourly
|
||||||
local ttl = string.sub(response_headers["cache-control"], 9)
|
local ttl = tonumber(string.sub(response_headers["cache-control"], 9))
|
||||||
|
|
||||||
|
|
||||||
local weather = data.hourly
|
|
||||||
local city = get_city_name(lat, lng)
|
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 = ""
|
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
|
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
|
||||||
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)
|
||||||
|
|
||||||
|
if is_inline then
|
||||||
|
return city, weather_summary, header..text, ttl
|
||||||
|
else
|
||||||
return header..text
|
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
|
end
|
||||||
|
|
||||||
function forecast:action(msg, config, matches)
|
function forecast:action(msg, config, matches)
|
||||||
local user_id = msg.from.id
|
local user_id = msg.from.id
|
||||||
local city = get_location(user_id)
|
|
||||||
|
|
||||||
if matches[2] then
|
if matches[2] then
|
||||||
city = matches[2]
|
city = matches[2]
|
||||||
@ -184,23 +244,12 @@ function forecast:action(msg, config, matches)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local lat = redis:hget('telegram:cache:weather:'..string.lower(city), 'lat')
|
local lat, lng = get_city_coordinates(city, config)
|
||||||
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
|
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
|
return
|
||||||
end
|
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
|
if matches[1] == '/forecasth' or matches[1] == '/fh' then
|
||||||
text = forecast:get_forecast_hourly(lat, lng)
|
text = forecast:get_forecast_hourly(lat, lng)
|
||||||
else
|
else
|
||||||
|
@ -131,7 +131,7 @@ end
|
|||||||
function gImages:cache_result(results, text)
|
function gImages:cache_result(results, text)
|
||||||
local cache = {}
|
local cache = {}
|
||||||
for v in pairs(results) do
|
for v in pairs(results) do
|
||||||
table.insert(cache, results[v].link)
|
cache[v] = results[v].link
|
||||||
end
|
end
|
||||||
for n, link in pairs(cache) do
|
for n, link in pairs(cache) do
|
||||||
redis:hset('telegram:cache:gImages:'..link, 'mime', results[n].mime)
|
redis:hset('telegram:cache:gImages:'..link, 'mime', results[n].mime)
|
||||||
|
@ -131,7 +131,7 @@ end
|
|||||||
function gImages_nsfw:cache_result(results, text)
|
function gImages_nsfw:cache_result(results, text)
|
||||||
local cache = {}
|
local cache = {}
|
||||||
for v in pairs(results) do
|
for v in pairs(results) do
|
||||||
table.insert(cache, results[v].link)
|
cache[v] = results[v].link
|
||||||
end
|
end
|
||||||
for n, link in pairs(cache) do
|
for n, link in pairs(cache) do
|
||||||
redis:hset('telegram:cache:gImages_nsfw:'..link, 'mime', results[n].mime)
|
redis:hset('telegram:cache:gImages_nsfw:'..link, 'mime', results[n].mime)
|
||||||
|
@ -4,6 +4,9 @@ gMaps.command = 'loc <Ort>'
|
|||||||
|
|
||||||
function gMaps:init(config)
|
function gMaps:init(config)
|
||||||
gMaps.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('[Ll][Oo][Cc]', true).table
|
gMaps.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('[Ll][Oo][Cc]', true).table
|
||||||
|
gMaps.inline_triggers = {
|
||||||
|
"^[Ll][Oo][Cc] (.+)"
|
||||||
|
}
|
||||||
gMaps.doc = [[*
|
gMaps.doc = [[*
|
||||||
]]..config.cmd_pat..[[loc* _<Ort>_: Sendet Ort via Google Maps]]
|
]]..config.cmd_pat..[[loc* _<Ort>_: Sendet Ort via Google Maps]]
|
||||||
end
|
end
|
||||||
@ -16,16 +19,23 @@ function gMaps:get_staticmap(area, lat, lon)
|
|||||||
return file
|
return file
|
||||||
end
|
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)
|
function gMaps:action(msg, config)
|
||||||
local input = utilities.input(msg.text)
|
local input = utilities.input_from_msg(msg)
|
||||||
if not input then
|
if not input then
|
||||||
if msg.reply_to_message and msg.reply_to_message.text then
|
utilities.send_reply(self, msg, gMaps.doc, true)
|
||||||
input = msg.reply_to_message.text
|
|
||||||
else
|
|
||||||
utilities.send_message(self, msg.chat.id, gMaps.doc, true, msg.message_id, true)
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
|
||||||
utilities.send_typing(self, msg.chat.id, 'find_location')
|
utilities.send_typing(self, msg.chat.id, 'find_location')
|
||||||
local coords = utilities.get_coords(input, config)
|
local coords = utilities.get_coords(input, config)
|
||||||
if type(coords) == 'string' then
|
if type(coords) == 'string' then
|
||||||
|
@ -51,15 +51,11 @@ function gSearch:stringlinks(results, stats)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function gSearch:action(msg, config)
|
function gSearch:action(msg, config)
|
||||||
local input = utilities.input(msg.text)
|
local input = utilities.input_from_msg(msg)
|
||||||
if not input then
|
if not input then
|
||||||
if msg.reply_to_message and msg.reply_to_message.text then
|
utilities.send_reply(self, msg, gImages.doc, true)
|
||||||
input = msg.reply_to_message.text
|
|
||||||
else
|
|
||||||
utilities.send_message(self, msg.chat.id, gSearch.doc, true, msg.message_id, true)
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
local results, stats = gSearch:googlethat(input, onfig)
|
local results, stats = gSearch:googlethat(input, onfig)
|
||||||
if results == '403' then
|
if results == '403' then
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
-- YOU NEED THE FOLLOWING FOLDERS: photo, document, video, voice
|
-- YOU NEED THE FOLLOWING FOLDERS: photo, document, video, voice
|
||||||
-- PLEASE ADJUST YOUR PATH BELOW
|
-- PLEASE ADJUST YOUR PATH BELOW
|
||||||
-- Save your bot api key in redis set telegram:credentials!
|
|
||||||
|
|
||||||
local media_download = {}
|
local media_download = {}
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ function media_download:download_to_file_permanently(url, file_name)
|
|||||||
return true
|
return true
|
||||||
end
|
end
|
||||||
|
|
||||||
function media_download:pre_process(msg, self)
|
function media_download:pre_process(msg, self, config)
|
||||||
if msg.photo then
|
if msg.photo then
|
||||||
local lv = #msg.photo -- find biggest photo, always the last value
|
local lv = #msg.photo -- find biggest photo, always the last value
|
||||||
file_id = msg.photo[lv].file_id
|
file_id = msg.photo[lv].file_id
|
||||||
@ -89,7 +88,7 @@ function media_download:pre_process(msg, self)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Construct what we want
|
-- 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)
|
local ok = media_download:download_to_file_permanently(download_url, file_path)
|
||||||
if not ok then
|
if not ok then
|
||||||
print('Download fehlgeschlagen!')
|
print('Download fehlgeschlagen!')
|
||||||
|
@ -30,12 +30,14 @@ function giphy:inline_callback(inline_query, config, matches)
|
|||||||
else
|
else
|
||||||
data = giphy:get_gifs(matches[2])
|
data = giphy:get_gifs(matches[2])
|
||||||
end
|
end
|
||||||
if not data then return end
|
if not data then utilities.answer_inline_query(self, inline_query) return end
|
||||||
if not data[1] then return end
|
if not data[1] then utilities.answer_inline_query(self, inline_query) return end
|
||||||
local results = '['
|
local results = '['
|
||||||
|
local id = 450
|
||||||
|
|
||||||
for n in pairs(data) do
|
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
|
if n < #data then
|
||||||
results = results..','
|
results = results..','
|
||||||
end
|
end
|
||||||
|
@ -25,9 +25,9 @@ end
|
|||||||
function googl:inline_callback(inline_query, config, matches)
|
function googl:inline_callback(inline_query, config, matches)
|
||||||
local shorturl = matches[1]
|
local shorturl = matches[1]
|
||||||
local text, longUrl = googl:send_googl_info(shorturl)
|
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)
|
utilities.answer_inline_query(self, inline_query, results, 1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -5,6 +5,13 @@ gps.command = 'gps <Breitengrad>,<Längengrad>'
|
|||||||
function gps:init(config)
|
function gps:init(config)
|
||||||
gps.triggers = {
|
gps.triggers = {
|
||||||
"^/[Gg][Pp][Ss] ([^,]*)[,%s]([^,]*)$",
|
"^/[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.de/maps/@([^,]*)[,%s]([^,]*)",
|
||||||
"google.com/maps/@([^,]*)[,%s]([^,]*)",
|
"google.com/maps/@([^,]*)[,%s]([^,]*)",
|
||||||
"google.de/maps/place/@([^,]*)[,%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]]
|
]]..config.cmd_pat..[[gps* _<Breitengrad>_,_<Längengrad>_: Sendet Karte mit diesen Koordinaten]]
|
||||||
end
|
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)
|
function gps:action(msg, config, matches)
|
||||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||||
local lat = matches[1]
|
local lat = matches[1]
|
||||||
|
@ -5,40 +5,73 @@ local help = {}
|
|||||||
local help_text
|
local help_text
|
||||||
|
|
||||||
function help:init(config)
|
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
|
end
|
||||||
|
|
||||||
function help:action(msg, config)
|
function help:inline_callback(inline_query, config, matches)
|
||||||
local commandlist = {}
|
local query = matches[1]
|
||||||
help_text = '*Verfügbare Befehle:*\n• '..config.cmd_pat
|
|
||||||
|
|
||||||
for _,plugin in ipairs(self.plugins) do
|
for n=1, #self.plugins do
|
||||||
if plugin.command then
|
local plugin = self.plugins[n]
|
||||||
|
if plugin.command and utilities.get_word(plugin.command, 1) == query and plugin.doc then
|
||||||
table.insert(commandlist, plugin.command)
|
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
|
||||||
end
|
end
|
||||||
|
utilities.answer_inline_query(self, inline_query)
|
||||||
|
end
|
||||||
|
|
||||||
table.insert(commandlist, 'hilfe [Befehl]')
|
function help:action(msg, config, matches)
|
||||||
table.sort(commandlist)
|
if matches[2] then
|
||||||
help_text = help_text .. table.concat(commandlist, '\n• '..config.cmd_pat) .. '\nParameter: <benötigt> [optional]'
|
input = matches[2]
|
||||||
|
elseif matches[1] ~= '/hilfe' then
|
||||||
|
input = matches[1]
|
||||||
|
else
|
||||||
|
input = nil
|
||||||
|
end
|
||||||
|
|
||||||
help_text = help_text:gsub('%[', '\\[')
|
|
||||||
local input = utilities.input(msg.text_lower)
|
|
||||||
|
|
||||||
-- Attempts to send the help message via PM.
|
-- Attempts to send the help message via PM.
|
||||||
-- If msg is from a group, it tells the group whether the PM was successful.
|
-- If msg is from a group, it tells the group whether the PM was successful.
|
||||||
if not input then
|
if not input then
|
||||||
|
local commandlist = {}
|
||||||
|
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
|
||||||
|
|
||||||
|
commandlist[#commandlist+1] = 'hilfe [Befehl]'
|
||||||
|
table.sort(commandlist)
|
||||||
|
local help_text = help_text .. table.concat(commandlist, '\n• '..config.cmd_pat) .. '\nParameter: <benötigt> [optional]'
|
||||||
|
local help_text = help_text:gsub('%[', '\\[')
|
||||||
|
|
||||||
local res = utilities.send_message(self, msg.from.id, help_text, true, nil, true)
|
local res = utilities.send_message(self, msg.from.id, help_text, true, nil, true)
|
||||||
if not res then
|
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)
|
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
|
elseif msg.chat.type ~= 'private' then
|
||||||
utilities.send_reply(self, msg, 'Ich habe dir die Hilfe per PN gesendet!.')
|
utilities.send_reply(self, msg, 'Ich habe dir die Hilfe privat gesendet!.')
|
||||||
end
|
end
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
for _,plugin in ipairs(self.plugins) do
|
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
|
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
|
local output = '*Hilfe für* _' .. utilities.get_word(plugin.command, 1) .. '_ *:*' .. plugin.doc
|
||||||
utilities.send_message(self, msg.chat.id, output, true, nil, true)
|
utilities.send_message(self, msg.chat.id, output, true, nil, true)
|
||||||
|
@ -7,6 +7,11 @@ function id:init(config)
|
|||||||
"^/id$",
|
"^/id$",
|
||||||
"^/ids? (chat)$"
|
"^/ids? (chat)$"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
id.inline_triggers = {
|
||||||
|
"^id$"
|
||||||
|
}
|
||||||
|
|
||||||
id.doc = [[```Zeige dir deine ID und die IDs aller Gruppenmitglieder an.``]]
|
id.doc = [[```Zeige dir deine ID und die IDs aller Gruppenmitglieder an.``]]
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -41,7 +46,15 @@ function id:get_user(user_id, chat_id)
|
|||||||
return user_info
|
return user_info
|
||||||
end
|
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 matches[1] == "/id" then
|
||||||
if msg.reply_to_message then
|
if msg.reply_to_message then
|
||||||
@ -86,7 +99,7 @@ function id:action(msg)
|
|||||||
for i = 1, #users do
|
for i = 1, #users do
|
||||||
local user_id = users[i]
|
local user_id = users[i]
|
||||||
local user_info = id:get_user(user_id, chat_id)
|
local user_info = id:get_user(user_id, chat_id)
|
||||||
table.insert(users_info, user_info)
|
users_info[#users_info+1] = user_info
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get all administrators and the creator
|
-- get all administrators and the creator
|
||||||
@ -94,7 +107,7 @@ function id:action(msg)
|
|||||||
local admins = {}
|
local admins = {}
|
||||||
for num in pairs(administrators.result) do
|
for num in pairs(administrators.result) do
|
||||||
if administrators.result[num].status ~= 'creator' then
|
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
|
else
|
||||||
creator_id = administrators.result[num].user.id
|
creator_id = administrators.result[num].user.id
|
||||||
end
|
end
|
||||||
|
@ -5,7 +5,7 @@ images.triggers = {
|
|||||||
"(https?://[%w-_%%%.%?%.:,/%+=~&%[%]]+%.[Jj][Pp][Ee]?[Gg])$"
|
"(https?://[%w-_%%%.%?%.:,/%+=~&%[%]]+%.[Jj][Pp][Ee]?[Gg])$"
|
||||||
}
|
}
|
||||||
|
|
||||||
function images:action(msg)
|
function images:action(msg, config, matches)
|
||||||
local url = matches[1]
|
local url = matches[1]
|
||||||
local file, last_modified, nocache = get_cached_file(url, nil, msg.chat.id, 'upload_photo', self)
|
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)
|
local result = utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||||
|
@ -3,51 +3,99 @@ local imdb = {}
|
|||||||
imdb.command = 'imdb <query>'
|
imdb.command = 'imdb <query>'
|
||||||
|
|
||||||
function imdb:init(config)
|
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 = [[*
|
imdb.doc = [[*
|
||||||
]]..config.cmd_pat..[[imdb* _<Film>_
|
]]..config.cmd_pat..[[imdb* _<Film>_
|
||||||
Sucht einen _Film_ bei IMDb]]
|
Sucht einen _Film_ bei IMDb]]
|
||||||
end
|
end
|
||||||
|
|
||||||
function imdb:action(msg, config)
|
local BASE_URL = 'https://www.omdbapi.com'
|
||||||
|
|
||||||
local input = utilities.input(msg.text)
|
function imdb:get_imdb_info(id)
|
||||||
if not input then
|
local url = BASE_URL..'/?i='..id
|
||||||
if msg.reply_to_message and msg.reply_to_message.text then
|
local res, code = https.request(url)
|
||||||
input = msg.reply_to_message.text
|
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
|
else
|
||||||
utilities.send_message(self, msg.chat.id, imdb.doc, true, msg.message_id, true)
|
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
|
return
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
local url = 'http://www.omdbapi.com/?t=' .. URL.escape(input)
|
local url = BASE_URL..'/?t='..URL.escape(input)
|
||||||
|
local jstr, res = https.request(url)
|
||||||
local jstr, res = http.request(url)
|
|
||||||
if res ~= 200 then
|
if res ~= 200 then
|
||||||
utilities.send_reply(self, msg, config.errors.connection)
|
utilities.send_reply(self, msg, config.errors.connection)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local jdat = json.decode(jstr)
|
local jdat = json.decode(jstr)
|
||||||
|
|
||||||
if jdat.Response ~= 'True' then
|
if jdat.Response ~= 'True' then
|
||||||
utilities.send_reply(self, msg, config.errors.results)
|
utilities.send_reply(self, msg, config.errors.results)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
local output = '*' .. jdat.Title .. ' ('.. jdat.Year ..')* von '..jdat.Director..'\n'
|
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..string.gsub(jdat.imdbRating, '%.', ',')..'/10 | '..jdat.Runtime..' | '.. jdat.Genre..'\n'
|
||||||
output = output .. '_' .. jdat.Plot .. '_\n'
|
output = output..'<i>' .. jdat.Plot .. '</i>'
|
||||||
output = output .. '[IMDb-Seite besuchen](http://imdb.com/title/' .. jdat.imdbID .. ')'
|
|
||||||
|
|
||||||
utilities.send_message(self, msg.chat.id, output, true, nil, true)
|
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
|
if jdat.Poster ~= "N/A" then
|
||||||
local file = download_to_file(jdat.Poster)
|
local file = download_to_file(jdat.Poster)
|
||||||
utilities.send_photo(self, msg.chat.id, file)
|
utilities.send_photo(self, msg.chat.id, file)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return imdb
|
return imdb
|
@ -1,7 +1,5 @@
|
|||||||
local media = {}
|
local media = {}
|
||||||
|
|
||||||
mimetype = (loadfile "./miku/mimetype.lua")()
|
|
||||||
|
|
||||||
media.triggers = {
|
media.triggers = {
|
||||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(gif))$",
|
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(gif))$",
|
||||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(mp4))$",
|
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(mp4))$",
|
||||||
@ -23,10 +21,10 @@ media.triggers = {
|
|||||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(webp))$"
|
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(webp))$"
|
||||||
}
|
}
|
||||||
|
|
||||||
function media:action(msg)
|
function media:action(msg, config, matches)
|
||||||
local url = matches[1]
|
local url = matches[1]
|
||||||
local ext = matches[2]
|
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
|
local receiver = msg.chat.id
|
||||||
|
|
||||||
if mime_type == 'audio' then
|
if mime_type == 'audio' then
|
||||||
@ -41,19 +39,14 @@ function media:action(msg)
|
|||||||
if not file then return end
|
if not file then return end
|
||||||
|
|
||||||
if ext == 'gif' then
|
if ext == 'gif' then
|
||||||
print('Sende GIF')
|
|
||||||
result = utilities.send_document(self, receiver, file, nil, msg.message_id)
|
result = utilities.send_document(self, receiver, file, nil, msg.message_id)
|
||||||
elseif ext == 'ogg' then
|
elseif ext == 'ogg' then
|
||||||
print('Sende OGG')
|
|
||||||
result = utilities.send_voice(self, receiver, file, nil, msg.message_id)
|
result = utilities.send_voice(self, receiver, file, nil, msg.message_id)
|
||||||
elseif mime_type == 'audio' then
|
elseif mime_type == 'audio' then
|
||||||
print('Sende Audio')
|
|
||||||
result = utilities.send_audio(self, receiver, file, nil, msg.message_id)
|
result = utilities.send_audio(self, receiver, file, nil, msg.message_id)
|
||||||
elseif mime_type == 'video' then
|
elseif mime_type == 'video' then
|
||||||
print('Sende Video')
|
|
||||||
result = utilities.send_video(self, receiver, file, nil, msg.message_id)
|
result = utilities.send_video(self, receiver, file, nil, msg.message_id)
|
||||||
else
|
else
|
||||||
print('Sende Datei')
|
|
||||||
result = utilities.send_document(self, receiver, file, nil, msg.message_id)
|
result = utilities.send_document(self, receiver, file, nil, msg.message_id)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
local patterns = {}
|
local patterns = {}
|
||||||
|
|
||||||
patterns.triggers = {
|
function patterns:init(config)
|
||||||
'^/?s/.-/.-$'
|
patterns.command = 's/<Pattern>/<Ersetzung>'
|
||||||
}
|
patterns.triggers = {
|
||||||
|
config.cmd_pat .. '?s/.-/.-$'
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
function patterns:action(msg)
|
function patterns:action(msg)
|
||||||
if not msg.reply_to_message then return true end
|
if not msg.reply_to_message then return true end
|
||||||
|
@ -5,12 +5,12 @@ local bot = require('miku.bot')
|
|||||||
function plugin_manager:init(config)
|
function plugin_manager:init(config)
|
||||||
plugin_manager.triggers = {
|
plugin_manager.triggers = {
|
||||||
"^/plugins$",
|
"^/plugins$",
|
||||||
|
"^/plugins? (enable) ([%w_%.%-]+) (chat) (%d+)$",
|
||||||
|
"^/plugins? (enable) ([%w_%.%-]+) (chat)$",
|
||||||
|
"^/plugins? (disable) ([%w_%.%-]+) (chat) (%d+)$",
|
||||||
|
"^/plugins? (disable) ([%w_%.%-]+) (chat)$",
|
||||||
"^/plugins? (enable) ([%w_%.%-]+)$",
|
"^/plugins? (enable) ([%w_%.%-]+)$",
|
||||||
"^/plugins? (disable) ([%w_%.%-]+)$",
|
"^/plugins? (disable) ([%w_%.%-]+)$",
|
||||||
"^/plugins? (enable) ([%w_%.%-]+) (chat) (%d+)",
|
|
||||||
"^/plugins? (enable) ([%w_%.%-]+) (chat)",
|
|
||||||
"^/plugins? (disable) ([%w_%.%-]+) (chat) (%d+)",
|
|
||||||
"^/plugins? (disable) ([%w_%.%-]+) (chat)",
|
|
||||||
"^/plugins? (reload)$",
|
"^/plugins? (reload)$",
|
||||||
"^/(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,18 +4,51 @@ preview.command = 'preview <link>'
|
|||||||
|
|
||||||
function preview:init(config)
|
function preview:init(config)
|
||||||
preview.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('preview', true).table
|
preview.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('preview', true).table
|
||||||
preview.doc = [[```
|
preview.inline_triggers = {
|
||||||
]]..config.cmd_pat..[[preview <link>
|
"^pr (https?://[%w-_%.%?%.:/%+=&%~%%#]+)$"
|
||||||
Returns a full-message, "unlinked" preview.
|
}
|
||||||
```]]
|
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
|
end
|
||||||
|
|
||||||
function preview:action(msg)
|
function preview:action(msg)
|
||||||
|
local input = utilities.input_from_msg(msg)
|
||||||
local input = utilities.input(msg.text)
|
|
||||||
|
|
||||||
if not input then
|
if not input then
|
||||||
utilities.send_message(self, msg.chat.id, preview.doc, true, nil, true)
|
utilities.send_reply(self, msg, preview.doc, true)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -26,19 +59,18 @@ function preview:action(msg)
|
|||||||
|
|
||||||
local res = http.request(input)
|
local res = http.request(input)
|
||||||
if not res then
|
if not res then
|
||||||
utilities.send_reply(self, msg, 'Please provide a valid link.')
|
utilities.send_reply(self, msg, 'Bitte gebe einen validen Link an.')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if res:len() == 0 then
|
if res:len() == 0 then
|
||||||
utilities.send_reply(self, msg, 'Sorry, the link you provided is not letting us make a preview.')
|
utilities.send_reply(self, msg, 'Sorry, dieser Link lässt uns keine Vorschau erstellen.')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Invisible zero-width, non-joiner.
|
-- Invisible zero-width, non-joiner.
|
||||||
local output = '[](' .. input .. ')'
|
local output = '<a href="' .. input .. '">' .. utilities.char.zwnj .. '</a>'
|
||||||
utilities.send_message(self, msg.chat.id, output, false, nil, true)
|
utilities.send_message(self, msg.chat.id, output, false, nil, 'HTML')
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return preview
|
return preview
|
@ -71,11 +71,13 @@ end
|
|||||||
|
|
||||||
function qr:inline_callback(inline_query, config, matches)
|
function qr:inline_callback(inline_query, config, matches)
|
||||||
local text = matches[1]
|
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')
|
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
|
local i = 0
|
||||||
while i < 29 do
|
while i < 29 do
|
||||||
@ -83,7 +85,8 @@ function qr:inline_callback(inline_query, config, matches)
|
|||||||
local color = math.random(255)
|
local color = math.random(255)
|
||||||
local bgcolor = math.random(255)
|
local bgcolor = math.random(255)
|
||||||
local image_url = qr:qr(text, color, bgcolor, 'jpg')
|
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
|
if i < 29 then
|
||||||
results = results..','
|
results = results..','
|
||||||
end
|
end
|
||||||
|
@ -7,87 +7,78 @@ function remind:init(config)
|
|||||||
|
|
||||||
remind.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('remind', true).table
|
remind.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('remind', true).table
|
||||||
remind.doc = [[*
|
remind.doc = [[*
|
||||||
]]..config.cmd_pat..[[remind* _<Länge>_ _<Nachricht>_: Erinnert dich in X Minuten an die Nachricht]]
|
]]..config.cmd_pat..[[remind* _<Länge>_ _<Nachricht>_
|
||||||
|
Erinnert dich in der angegeben Länge in Minuten an eine Nachricht.
|
||||||
|
Die maximale Länge einer Erinnerung beträgt %s Buchstaben, die maximale Zeit beträgt %s Minuten, die maximale Anzahl an Erinnerung für eine Gruppe ist %s und für private Chats %s.]]
|
||||||
|
remind.doc = remind.doc:format(config.remind.max_length, config.remind.max_duration, config.remind.max_reminders_group, config.remind.max_reminders_private)
|
||||||
end
|
end
|
||||||
|
|
||||||
function remind:action(msg)
|
function remind:action(msg, config)
|
||||||
-- Ensure there are arguments. If not, send doc.
|
|
||||||
local input = utilities.input(msg.text)
|
local input = utilities.input(msg.text)
|
||||||
if not input then
|
if not input then
|
||||||
utilities.send_message(self, msg.chat.id, remind.doc, true, msg.message_id, true)
|
utilities.send_reply(self, msg, remind.doc, true)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Ensure first arg is a number. If not, send doc.
|
local duration = tonumber(utilities.get_word(input, 1))
|
||||||
local duration = utilities.get_word(input, 1)
|
if not duration then
|
||||||
if not tonumber(duration) then
|
utilities.send_reply(self, msg, remind.doc, true)
|
||||||
utilities.send_message(self, msg.chat.id, remind.doc, true, msg.message_id, true)
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Duration must be between one minute and one day (approximately).
|
|
||||||
duration = tonumber(duration)
|
|
||||||
if duration < 1 then
|
if duration < 1 then
|
||||||
duration = 1
|
duration = 1
|
||||||
elseif duration > 1440 then
|
elseif duration > config.remind.max_duration then
|
||||||
duration = 1440
|
duration = config.remind.max_duration
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Ensure there is a second arg.
|
|
||||||
local message = utilities.input(input)
|
local message = utilities.input(input)
|
||||||
if not message then
|
if not message then
|
||||||
utilities.send_message(self, msg.chat.id, remind.doc, true, msg.message_id, true)
|
utilities.send_reply(self, msg, remind.doc, true)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Make a database entry for the group/user if one does not exist.
|
if #message > config.remind.max_length then
|
||||||
self.database.reminders[msg.chat.id_str] = self.database.reminders[msg.chat.id_str] or {}
|
utilities.send_reply(self, msg, 'Die maximale Länge einer Erinnerung ist ' .. config.remind.max_length .. '.')
|
||||||
-- 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!')
|
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
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.
|
-- Put together the reminder with the expiration, message, and message to reply to.
|
||||||
local timestamp = os.time() + duration * 60
|
local timestamp = os.time() + duration * 60
|
||||||
local reminder = {
|
local reminder = {
|
||||||
time = timestamp,
|
time = timestamp,
|
||||||
message = message
|
message = message
|
||||||
}
|
}
|
||||||
table.insert(self.database.reminders[msg.chat.id_str], reminder)
|
table.insert(self.database.reminders[chat_id_str], reminder)
|
||||||
local human_readable_time = convert_timestamp(timestamp, '%H:%M:%S')
|
local human_readable_time = convert_timestamp(timestamp, '%H:%M:%S')
|
||||||
local output = 'Ich werde dich um *'..human_readable_time..' Uhr* erinnern.'
|
output = 'Ich werde dich um *'..human_readable_time..' Uhr* erinnern.'
|
||||||
|
end
|
||||||
utilities.send_reply(self, msg, output, true)
|
utilities.send_reply(self, msg, output, true)
|
||||||
end
|
end
|
||||||
|
|
||||||
function remind:cron()
|
function remind:cron(config)
|
||||||
local time = os.time()
|
local time = os.time()
|
||||||
-- Iterate over the group entries in the reminders database.
|
-- Iterate over the group entries in the reminders database.
|
||||||
for chat_id, group in pairs(self.database.reminders) do
|
for chat_id, group in pairs(self.database.reminders) do
|
||||||
local new_group = {}
|
|
||||||
-- Iterate over each reminder.
|
-- Iterate over each reminder.
|
||||||
for _, reminder in ipairs(group) do
|
for k, reminder in pairs(group) do
|
||||||
-- If the reminder is past-due, send it and nullify it.
|
-- If the reminder is past-due, send it and nullify it.
|
||||||
-- Otherwise, add it to the replacement table.
|
-- Otherwise, add it to the replacement table.
|
||||||
if time > reminder.time then
|
if time > reminder.time then
|
||||||
local output = '*ERINNERUNG:*\n"' .. utilities.md_escape(reminder.message) .. '"'
|
local output = '*ERINNERUNG:*\n"' .. utilities.md_escape(reminder.message) .. '"'
|
||||||
local res = utilities.send_message(self, chat_id, output, true, nil, true)
|
local res = utilities.send_message(self, chat_id, output, true, nil, true)
|
||||||
-- If the message fails to send, save it for later.
|
-- If the message fails to send, save it for later (if enabled in config).
|
||||||
if not res then
|
if res or not config.remind.persist then
|
||||||
table.insert(new_group, reminder)
|
group[k] = nil
|
||||||
end
|
|
||||||
else
|
|
||||||
table.insert(new_group, reminder)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Nullify the original table and replace it with the new one.
|
|
||||||
self.database.reminders[chat_id] = new_group
|
|
||||||
-- Nullify the table if it is empty.
|
|
||||||
if #new_group == 0 then
|
|
||||||
self.database.reminders[chat_id] = nil
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
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
|
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 = '¯\\\\\\_(ツ)_/¯'
|
face = '¯\\\\\\_(ツ)_/¯'
|
||||||
end
|
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)
|
utilities.answer_inline_query(self, inline_query, results, 9999)
|
||||||
end
|
end
|
||||||
|
|
||||||
function respond:action(msg, config, matches)
|
function respond:action(msg, config, matches)
|
||||||
local user_name = get_name(msg)
|
local user_name = get_name(msg)
|
||||||
local receiver = msg.chat.id
|
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 user_name == "DefenderX" then user_name = "Deffu" end
|
||||||
|
|
||||||
if string.match(msg.text, "[Ff][Gg][Tt].? [Ss][Ww][Ii][Ff][Tt]") then
|
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, '🐸🐸🐸')
|
utilities.send_message(self, receiver, '🐸🐸🐸')
|
||||||
return
|
return
|
||||||
elseif string.match(msg.text, "[Ii][Nn][Ll][Oo][Vv][Ee]") then
|
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)
|
utilities.send_document(self, receiver, file)
|
||||||
return
|
return
|
||||||
elseif string.match(msg.text, "[Ww][Aa][Tt]") then
|
elseif string.match(msg.text, "[Ww][Aa][Tt]") then
|
||||||
local WAT_URL = GDRIVE_URL..'/wat'
|
local WAT_URL = BASE_URL..'/wat'
|
||||||
local wats = {
|
local wats = {
|
||||||
"/wat1.jpg",
|
"/wat1.jpg",
|
||||||
"/wat2.jpg",
|
"/wat2.jpg",
|
||||||
|
@ -13,7 +13,7 @@ function rss:init(config)
|
|||||||
"^/rss (sub) (https?://[%w-_%.%?%.:/%+=&%~]+)$",
|
"^/rss (sub) (https?://[%w-_%.%?%.:/%+=&%~]+)$",
|
||||||
"^/rss (del) (%d+) @(.*)$",
|
"^/rss (del) (%d+) @(.*)$",
|
||||||
"^/rss (del) (%d+)$",
|
"^/rss (del) (%d+)$",
|
||||||
"^/rss (del)",
|
"^/rss (del)$",
|
||||||
"^/rss (sync)$"
|
"^/rss (sync)$"
|
||||||
}
|
}
|
||||||
rss.doc = [[*
|
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 = ''
|
local text = ''
|
||||||
for k,user in pairs(users_info) do
|
for k,user in pairs(users_info) do
|
||||||
text = text..user.name..': '..comma_value(user.msgs)..'\n'
|
local msg_num = user.msgs
|
||||||
text = string.gsub(text, "%_", " ") -- Bot API doesn't use underscores anymore! Yippie!
|
local percent = tostring(round(msg_num / all_msgs * 100, 1))
|
||||||
|
text = text..user.name..': '..comma_value(msg_num)..' <code>('..percent:gsub('%.', ',')..'%)</code>\n'
|
||||||
end
|
end
|
||||||
if text:isempty() then return 'Keine Stats für diesen Chat verfügbar!'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
|
return text
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -129,7 +130,7 @@ function stats:action(msg, config, matches)
|
|||||||
return
|
return
|
||||||
else
|
else
|
||||||
local chat_id = msg.chat.id
|
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
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -139,7 +140,7 @@ function stats:action(msg, config, matches)
|
|||||||
utilities.send_reply(self, msg, config.errors.sudo)
|
utilities.send_reply(self, msg, config.errors.sudo)
|
||||||
return
|
return
|
||||||
else
|
else
|
||||||
utilities.send_reply(self, msg, stats:chat_stats(matches[3]), true)
|
utilities.send_reply(self, msg, stats:chat_stats(matches[3]), 'HTML')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -42,7 +42,7 @@ function tagesschau:inline_callback(inline_query, config, matches)
|
|||||||
local article = matches[1]
|
local article = matches[1]
|
||||||
local full_url = 'http://www.tagesschau.de/'..article..'.html'
|
local full_url = 'http://www.tagesschau.de/'..article..'.html'
|
||||||
local text, img_url, headline, shorttext = tagesschau:get_tagesschau_article(article)
|
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
|
if text:match('"') then
|
||||||
text = text:gsub('"', '\\"')
|
text = text:gsub('"', '\\"')
|
||||||
@ -55,7 +55,7 @@ function tagesschau:inline_callback(inline_query, config, matches)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local text = text:gsub('\n', '\\n')
|
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)
|
utilities.answer_inline_query(self, inline_query, results, 7200)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -4,6 +4,10 @@ time.command = 'time <Ort>'
|
|||||||
|
|
||||||
function time:init(config)
|
function time:init(config)
|
||||||
time.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('time', true).table
|
time.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('time', true).table
|
||||||
|
time.inline_triggers = {
|
||||||
|
"^time (.+)",
|
||||||
|
"^time"
|
||||||
|
}
|
||||||
time.doc = [[*
|
time.doc = [[*
|
||||||
]]..config.cmd_pat..[[time*: Aktuelle Zeit in Deutschland
|
]]..config.cmd_pat..[[time*: Aktuelle Zeit in Deutschland
|
||||||
*]]..config.cmd_pat..[[time* _<Ort>_: Gibt Zeit an diesem Ort aus]]
|
*]]..config.cmd_pat..[[time* _<Ort>_: Gibt Zeit an diesem Ort aus]]
|
||||||
@ -45,8 +49,49 @@ function time:localize(output)
|
|||||||
return output
|
return output
|
||||||
end
|
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)
|
function time:action(msg, config)
|
||||||
local input = utilities.input(msg.text)
|
local input = utilities.input_from_msg(msg)
|
||||||
if not input then
|
if not input then
|
||||||
local output = os.date("%A, %d. %B %Y, *%H:%M:%S Uhr*")
|
local output = os.date("%A, %d. %B %Y, *%H:%M:%S Uhr*")
|
||||||
utilities.send_reply(self, msg, time:localize(output), true)
|
utilities.send_reply(self, msg, time:localize(output), true)
|
||||||
@ -58,31 +103,8 @@ function time:action(msg, config)
|
|||||||
utilities.send_reply(self, msg, coords)
|
utilities.send_reply(self, msg, coords)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
local output = time:get_time(coords)
|
||||||
local now = os.time()
|
if not output then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||||
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 .. ')_'
|
|
||||||
|
|
||||||
utilities.send_reply(self, msg, output, true)
|
utilities.send_reply(self, msg, output, true)
|
||||||
end
|
end
|
||||||
|
@ -2,20 +2,20 @@ local twitter = {}
|
|||||||
|
|
||||||
function twitter:init(config)
|
function twitter:init(config)
|
||||||
if not cred_data.tw_consumer_key then
|
if not cred_data.tw_consumer_key then
|
||||||
print('Missing config value: tw_consumer_key.')
|
print('Fehlender Key: tw_consumer_key.')
|
||||||
print('twitter.lua will not be enabled.')
|
print('twitter.lua wird nicht aktiviert.')
|
||||||
return
|
return
|
||||||
elseif not cred_data.tw_consumer_secret then
|
elseif not cred_data.tw_consumer_secret then
|
||||||
print('Missing config value: tw_consumer_secret.')
|
print('Fehlender Key: tw_consumer_secret.')
|
||||||
print('twitter.lua will not be enabled.')
|
print('twitter.lua wird nicht aktiviert.')
|
||||||
return
|
return
|
||||||
elseif not cred_data.tw_access_token then
|
elseif not cred_data.tw_access_token then
|
||||||
print('Missing config value: tw_access_token.')
|
print('Fehlender Key: tw_access_token.')
|
||||||
print('twitter.lua will not be enabled.')
|
print('twitter.lua wird nicht aktiviert.')
|
||||||
return
|
return
|
||||||
elseif not cred_data.tw_access_token_secret then
|
elseif not cred_data.tw_access_token_secret then
|
||||||
print('Missing config value: tw_access_token_secret.')
|
print('Fehlender Key: tw_access_token_secret.')
|
||||||
print('twitter.lua will not be enabled.')
|
print('twitter.lua wird nicht aktiviert.')
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -104,14 +104,14 @@ function twitter:action(msg, config, matches)
|
|||||||
if v.video_info then
|
if v.video_info then
|
||||||
if not v.video_info.variants[3] then
|
if not v.video_info.variants[3] then
|
||||||
local vid = v.video_info.variants[1].url
|
local vid = v.video_info.variants[1].url
|
||||||
table.insert(videos, vid)
|
videos[#videos+1] = vid
|
||||||
else
|
else
|
||||||
local vid = v.video_info.variants[3].url
|
local vid = v.video_info.variants[3].url
|
||||||
table.insert(videos, vid)
|
videos[#videos+1] = vid
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
text = text:gsub(url, "")
|
text = text:gsub(url, "")
|
||||||
table.insert(images, pic)
|
images[#images+1] = pic
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -14,12 +14,14 @@ function twitter_send:init(config)
|
|||||||
end
|
end
|
||||||
|
|
||||||
twitter_send.triggers = {
|
twitter_send.triggers = {
|
||||||
"^/tw (auth) (%d+)",
|
"^/tw (auth) (%d+)$",
|
||||||
"^/tw (unauth)$",
|
"^/tw (unauth)$",
|
||||||
"^/tw (verify)$",
|
"^/tw (verify)$",
|
||||||
"^/tw (.+)",
|
"^/tw (.+)$",
|
||||||
"^/(twwhitelist add) (%d+)",
|
"^/(twwhitelist add) (%d+)$",
|
||||||
"^/(twwhitelist del) (%d+)"
|
"^/(twwhitelist del) (%d+)$",
|
||||||
|
"^/(twwhitelist add)$",
|
||||||
|
"^/(twwhitelist del)$"
|
||||||
}
|
}
|
||||||
twitter_send.doc = [[*
|
twitter_send.doc = [[*
|
||||||
]]..config.cmd_pat..[[tw* _<Text>_: Sendet einen Tweet an den Account, der im Chat angemeldet ist
|
]]..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', values.oauth_token)
|
||||||
redis:hset(hash, 'oauth_token_secret', values.oauth_token_secret)
|
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
|
end
|
||||||
|
|
||||||
function twitter_send:reset_twitter_auth(hash, frominvalid)
|
function twitter_send:reset_twitter_auth(hash, frominvalid)
|
||||||
redis:hdel(hash, 'oauth_token')
|
redis:hdel(hash, 'oauth_token')
|
||||||
redis:hdel(hash, 'oauth_token_secret')
|
redis:hdel(hash, 'oauth_token_secret')
|
||||||
if frominvalid then
|
if frominvalid then
|
||||||
return '*Authentifizierung nicht erfolgreich, wird zurückgesetzt...*'
|
return '<b>Authentifizierung nicht erfolgreich, wird zurückgesetzt...</b>'
|
||||||
else
|
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
|
||||||
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 screen_name = data.user.screen_name
|
||||||
local status_id = data.id_str
|
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
|
end
|
||||||
|
|
||||||
function twitter_send:add_to_twitter_whitelist(user_id)
|
function twitter_send:add_to_twitter_whitelist(user_id)
|
||||||
@ -245,22 +249,36 @@ function twitter_send:del_from_twitter_whitelist(user_id)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function twitter_send:action(msg, config, matches)
|
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
|
if msg.from.id ~= config.admin then
|
||||||
utilities.send_reply(self, msg, config.errors.sudo)
|
utilities.send_reply(self, msg, config.errors.sudo)
|
||||||
return
|
return
|
||||||
else
|
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
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if matches[1] == "twwhitelist del" and matches[2] then
|
if matches[1] == "twwhitelist del" then
|
||||||
if msg.from.id ~= config.admin then
|
if msg.from.id ~= config.admin then
|
||||||
utilities.send_reply(self, msg, config.errors.sudo)
|
utilities.send_reply(self, msg, config.errors.sudo)
|
||||||
return
|
return
|
||||||
else
|
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
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -302,7 +320,7 @@ function twitter_send:action(msg, config, matches)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
if string.len(matches[2]) > 7 then utilities.send_reply(self, msg, 'Invalide PIN!') return 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')
|
local message_id = redis:hget(hash, 'login_msg')
|
||||||
utilities.edit_message(self, msg.chat.id, message_id, '*Anmeldung abgeschlossen!*', true, true)
|
utilities.edit_message(self, msg.chat.id, message_id, '*Anmeldung abgeschlossen!*', true, true)
|
||||||
redis:hdel(hash, 'login_msg')
|
redis:hdel(hash, 'login_msg')
|
||||||
@ -316,7 +334,7 @@ function twitter_send:action(msg, config, matches)
|
|||||||
return
|
return
|
||||||
end
|
end
|
||||||
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
|
return
|
||||||
end
|
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)
|
utilities.send_reply(self, msg, '*Du darfst keine Tweets senden.* Entweder wurdest du noch gar nicht freigeschaltet oder ausgeschlossen.', true)
|
||||||
return
|
return
|
||||||
else
|
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
|
return
|
||||||
end
|
end
|
||||||
else
|
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
|
return
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
local twitter_user = {}
|
local twitter_user = {}
|
||||||
|
|
||||||
require "./miku/encoding"
|
require "./miku/encoding"
|
||||||
|
|
||||||
@ -58,7 +58,7 @@ function twitter_user:resolve_url(url)
|
|||||||
end
|
end
|
||||||
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 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_code, response_headers, response_status_line, response_body = client:PerformRequest("GET", twitter_url)
|
||||||
local response = json.decode(response_body)
|
local response = json.decode(response_body)
|
||||||
|
@ -7,7 +7,7 @@ venue.triggers = {
|
|||||||
local apikey = cred_data.google_apikey
|
local apikey = cred_data.google_apikey
|
||||||
|
|
||||||
function venue:pre_process(msg, self)
|
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 lat = msg.venue.location.latitude
|
||||||
local lng = msg.venue.location.longitude
|
local lng = msg.venue.location.longitude
|
||||||
|
@ -17,6 +17,10 @@ function weather:init(config)
|
|||||||
"^/w$",
|
"^/w$",
|
||||||
"^/w (.*)$"
|
"^/w (.*)$"
|
||||||
}
|
}
|
||||||
|
weather.inline_triggers = {
|
||||||
|
"^w (.+)$",
|
||||||
|
"^w$"
|
||||||
|
}
|
||||||
weather.doc = [[*
|
weather.doc = [[*
|
||||||
]]..config.cmd_pat..[[wetter*: Wetter für deinen Wohnort _(/location set [Ort])_
|
]]..config.cmd_pat..[[wetter*: Wetter für deinen Wohnort _(/location set [Ort])_
|
||||||
*]]..config.cmd_pat..[[wetter* _<Ort>_: Wetter für diesen Ort
|
*]]..config.cmd_pat..[[wetter* _<Ort>_: Wetter für diesen Ort
|
||||||
@ -42,10 +46,43 @@ function get_city_name(lat, lng)
|
|||||||
return city
|
return city
|
||||||
end
|
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)
|
print('Finde Wetter in '..lat..', '..lng)
|
||||||
local text = redis:get('telegram:cache:weather:'..lat..','..lng)
|
local hash = 'telegram:cache:weather:'..lat..','..lng
|
||||||
if text then print('...aus dem Cache') return text end
|
|
||||||
|
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'
|
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",
|
method = "GET",
|
||||||
sink = ltn12.sink.table(response_body)
|
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
|
if not ok then return nil end
|
||||||
local data = json.decode(table.concat(response_body))
|
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
|
local weather = data.currently
|
||||||
@ -66,26 +103,28 @@ function weather:get_weather(lat, lng)
|
|||||||
local temperature = string.gsub(round(weather.temperature, 1), "%.", ",")
|
local temperature = string.gsub(round(weather.temperature, 1), "%.", ",")
|
||||||
local feelslike = string.gsub(round(weather.apparentTemperature, 1), "%.", ",")
|
local feelslike = string.gsub(round(weather.apparentTemperature, 1), "%.", ",")
|
||||||
local temp = '*Wetter in '..city..':*\n'..temperature..' °C'
|
local temp = '*Wetter in '..city..':*\n'..temperature..' °C'
|
||||||
local conditions = ' | '..weather.summary
|
local weather_summary = weather.summary
|
||||||
if weather.icon == 'clear-day' then
|
local conditions = ' | '..weather_summary
|
||||||
|
local weather_icon = weather.icon
|
||||||
|
if weather_icon == 'clear-day' then
|
||||||
conditions = conditions..' ☀️'
|
conditions = conditions..' ☀️'
|
||||||
elseif weather.icon == 'clear-night' then
|
elseif weather_icon == 'clear-night' then
|
||||||
conditions = conditions..' 🌙'
|
conditions = conditions..' 🌙'
|
||||||
elseif weather.icon == 'rain' then
|
elseif weather_icon == 'rain' then
|
||||||
conditions = conditions..' ☔️'
|
conditions = conditions..' ☔️'
|
||||||
elseif weather.icon == 'snow' then
|
elseif weather_icon == 'snow' then
|
||||||
conditions = conditions..' ❄️'
|
conditions = conditions..' ❄️'
|
||||||
elseif weather.icon == 'sleet' then
|
elseif weather_icon == 'sleet' then
|
||||||
conditions = conditions..' 🌨'
|
conditions = conditions..' 🌨'
|
||||||
elseif weather.icon == 'wind' then
|
elseif weather_icon == 'wind' then
|
||||||
conditions = conditions..' 💨'
|
conditions = conditions..' 💨'
|
||||||
elseif weather.icon == 'fog' then
|
elseif weather.icon == 'fog' then
|
||||||
conditions = conditions..' 🌫'
|
conditions = conditions..' 🌫'
|
||||||
elseif weather.icon == 'cloudy' then
|
elseif weather_icon == 'cloudy' then
|
||||||
conditions = conditions..' ☁️☁️'
|
conditions = conditions..' ☁️☁️'
|
||||||
elseif weather.icon == 'partly-cloudy-day' then
|
elseif weather_icon == 'partly-cloudy-day' then
|
||||||
conditions = conditions..' 🌤'
|
conditions = conditions..' 🌤'
|
||||||
elseif weather.icon == 'partly-cloudy-night' then
|
elseif weather_icon == 'partly-cloudy-night' then
|
||||||
conditions = conditions..' 🌙☁️'
|
conditions = conditions..' 🌙☁️'
|
||||||
else
|
else
|
||||||
conditions = conditions..''
|
conditions = conditions..''
|
||||||
@ -98,8 +137,56 @@ function weather:get_weather(lat, lng)
|
|||||||
text = text..'\n(gefühlt: '..feelslike..' °C)'
|
text = text..'\n(gefühlt: '..feelslike..' °C)'
|
||||||
end
|
end
|
||||||
|
|
||||||
cache_data('weather', lat..','..lng, text, tonumber(ttl), 'key')
|
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
|
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
|
end
|
||||||
|
|
||||||
function weather:action(msg, config, matches)
|
function weather:action(msg, config, matches)
|
||||||
@ -116,23 +203,12 @@ function weather:action(msg, config, matches)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
local lat = redis:hget('telegram:cache:weather:'..string.lower(city), 'lat')
|
local lat, lng = get_city_coordinates(city, config)
|
||||||
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
|
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
|
return
|
||||||
end
|
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)
|
local text = weather:get_weather(lat, lng)
|
||||||
if not text then
|
if not text then
|
||||||
text = 'Konnte das Wetter von dieser Stadt nicht bekommen.'
|
text = 'Konnte das Wetter von dieser Stadt nicht bekommen.'
|
||||||
|
@ -57,7 +57,7 @@ function wikipedia:getWikiServer(lang)
|
|||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
-- return decoded json table from Wikipedia
|
-- return decoded JSON table from Wikipedia
|
||||||
--]]
|
--]]
|
||||||
function wikipedia:loadPage(text, lang, intro, plain, is_search)
|
function wikipedia:loadPage(text, lang, intro, plain, is_search)
|
||||||
local request, sink = {}, {}
|
local request, sink = {}, {}
|
||||||
@ -107,7 +107,7 @@ function wikipedia:loadPage(text, lang, intro, plain, is_search)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- extract intro passage in wiki page
|
-- extract intro passage in wiki page
|
||||||
function wikipedia:wikintro(text, lang)
|
function wikipedia:wikintro(text, lang, is_inline)
|
||||||
local text = decodetext(text)
|
local text = decodetext(text)
|
||||||
local result = self:loadPage(text, lang, true, true)
|
local result = self:loadPage(text, lang, true, true)
|
||||||
|
|
||||||
@ -124,14 +124,29 @@ function wikipedia:wikintro(text, lang)
|
|||||||
local lang = lang or "de"
|
local lang = lang or "de"
|
||||||
local title = page.title
|
local title = page.title
|
||||||
local title_enc = URL.escape(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
|
||||||
|
if is_inline then
|
||||||
|
return nil
|
||||||
else
|
else
|
||||||
local text = text.." nicht gefunden"
|
local text = text.." nicht gefunden"
|
||||||
return text
|
return text
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if is_inline then
|
||||||
|
return nil
|
||||||
else
|
else
|
||||||
return "Ein Fehler ist aufgetreten."
|
return "Ein Fehler ist aufgetreten."
|
||||||
end
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- search for term in wiki
|
-- search for term in wiki
|
||||||
@ -165,17 +180,20 @@ function wikipedia:inline_callback(inline_query, config, matches)
|
|||||||
lang = 'de'
|
lang = 'de'
|
||||||
query = matches[1]
|
query = matches[1]
|
||||||
end
|
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)
|
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'
|
||||||
if code ~= 200 then return end
|
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
|
local data = json.decode(res).query
|
||||||
|
|
||||||
if data.searchinfo.totalhits == 0 then return end
|
|
||||||
|
|
||||||
local results = '['
|
local results = '['
|
||||||
|
local id = 700
|
||||||
for num in pairs(data.search) do
|
for num in pairs(data.search) do
|
||||||
local title = data.search[num].title
|
local title, result, keyboard = wikipedia:wikintro(data.search[num].title, lang, true)
|
||||||
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}}'
|
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
|
if num < #data.search then
|
||||||
results = results..','
|
results = results..','
|
||||||
end
|
end
|
||||||
|
@ -147,10 +147,10 @@ function youtube:inline_callback(inline_query, config, matches)
|
|||||||
local query = matches[1]
|
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 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)
|
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)
|
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 = ""
|
local video_ids = ""
|
||||||
-- We get all videoIds from search...
|
-- 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
|
if not video_results.items[1] then return end
|
||||||
|
|
||||||
local results = '['
|
local results = '['
|
||||||
|
local id = 800
|
||||||
for num in pairs(video_results.items) do
|
for num in pairs(video_results.items) do
|
||||||
local video_url = 'https://www.youtube.com/watch?v='..video_results.items[num].id
|
local video_url = 'https://www.youtube.com/watch?v='..video_results.items[num].id
|
||||||
local thumb_url = get_yt_thumbnail(video_results.items[num])
|
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 uploader = video_results.items[num].snippet.channelTitle
|
||||||
local description = uploader..', '..viewCount..' Views, '..readable_dur..likeCount..dislikeCount..commentCount
|
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
|
if num < #video_results.items then
|
||||||
results = results..','
|
results = results..','
|
||||||
end
|
end
|
||||||
@ -207,6 +209,10 @@ end
|
|||||||
function youtube:action(msg, config, matches)
|
function youtube:action(msg, config, matches)
|
||||||
local yt_code = matches[1]
|
local yt_code = matches[1]
|
||||||
local data = get_yt_data(yt_code)
|
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)
|
send_youtube_data(data, msg, self)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
@ -4,34 +4,86 @@ local youtube_dl = {}
|
|||||||
|
|
||||||
function youtube_dl:init(config)
|
function youtube_dl:init(config)
|
||||||
youtube_dl.triggers = {
|
youtube_dl.triggers = {
|
||||||
"^/(mp4) (https?://[%w-_%.%?%.:/%+=&]+)$",
|
"^/(mp4) https?://w?w?w?%.?youtu.be/([A-Za-z0-9-_-]+)",
|
||||||
"^/(mp3) (https?://[%w-_%.%?%.:/%+=&]+)$"
|
"^/(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 = [[*
|
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..[[mp3* _<URL>_: Lädt Audio von YouTube
|
||||||
*]]..config.cmd_pat..[[mp4* _<URL>_: Lädt Video von [untersützten Seiten](https://rg3.github.io/youtube-dl/supportedsites.html)
|
*]]..config.cmd_pat..[[mp4* _<URL>_: Lädt Video von YouTube
|
||||||
]]
|
]]
|
||||||
end
|
end
|
||||||
|
|
||||||
youtube_dl.command = 'mp3 <URL>, /mp4 <URL>'
|
youtube_dl.command = 'mp3 <URL>, /mp4 <URL>'
|
||||||
|
|
||||||
function youtube_dl:convert_video(link)
|
function youtube_dl:get_availabe_formats(id, hash)
|
||||||
local output = io.popen('youtube-dl -f mp4 --max-filesize 49m -o "/tmp/%(title)s.%(ext)s" '..link):read('*all')
|
local ytdl_json = io.popen('youtube-dl -j https://www.youtube.com/watch/?v='..id):read('*all')
|
||||||
print(output)
|
if not ytdl_json then return end
|
||||||
if string.match(output, '.* File is larger .*') then
|
local data = json.decode(ytdl_json)
|
||||||
return 'TOOBIG'
|
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
|
end
|
||||||
local video = string.match(output, '%[download%] Destination: /tmp/(.*).mp4')
|
format_info.ext = data.formats[n].ext
|
||||||
if not video then
|
local url = data.formats[n].url
|
||||||
video = string.match(output, '%[download%] /tmp/(.*).mp4 has already been downloaded')
|
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
|
end
|
||||||
return '/tmp/'..video..'.mp4'
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
return available_formats
|
||||||
end
|
end
|
||||||
|
|
||||||
function youtube_dl:convert_audio(link)
|
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 '..link):read('*all')
|
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')
|
||||||
print(output)
|
|
||||||
if string.match(output, '.* File is larger .*') then
|
if string.match(output, '.* File is larger .*') then
|
||||||
return 'TOOBIG'
|
return 'TOOBIG'
|
||||||
end
|
end
|
||||||
@ -39,25 +91,105 @@ function youtube_dl:convert_audio(link)
|
|||||||
return '/tmp/'..audio..'.mp3'
|
return '/tmp/'..audio..'.mp3'
|
||||||
end
|
end
|
||||||
|
|
||||||
function youtube_dl:action(msg, config)
|
function youtube_dl:callback(callback, msg, self, config, input)
|
||||||
local link = matches[2]
|
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
|
||||||
|
|
||||||
if matches[1] == 'mp4' then
|
local keyboard = redis:hget(hash, 'keyboard')
|
||||||
utilities.send_typing(self, msg.chat.id, 'upload_video')
|
local duration = redis:hget(hash, 'duration')
|
||||||
local file = youtube_dl:convert_video(link)
|
local format_info = redis:hgetall(format_hash)
|
||||||
if file == 'TOOBIG' then
|
|
||||||
utilities.send_reply(self, msg, 'Das Video überschreitet die Grenze von 50 MB!')
|
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
|
return
|
||||||
end
|
end
|
||||||
utilities.send_video(self, msg.chat.id, file, nil, msg.message_id)
|
|
||||||
|
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
|
||||||
|
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.edit_message(self, msg.chat.id, first_msg.result.message_id, 'Wähle die gewünschte Auflösung.', nil, nil, callback_keyboard)
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
if matches[1] == 'mp3' then
|
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')
|
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
|
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
|
return
|
||||||
end
|
end
|
||||||
utilities.send_audio(self, msg.chat.id, file, msg.message_id)
|
utilities.send_audio(self, msg.chat.id, file, msg.message_id)
|
||||||
|
@ -10,12 +10,11 @@ socket = require('socket')
|
|||||||
URL = require('socket.url')
|
URL = require('socket.url')
|
||||||
json = require('dkjson')
|
json = require('dkjson')
|
||||||
pcall(json.use_lpeg)
|
pcall(json.use_lpeg)
|
||||||
serpent = require("serpent")
|
serpent = require('serpent')
|
||||||
bindings = require('miku.bindings')
|
redis = (loadfile './miku/redis.lua')()
|
||||||
redis = (loadfile "./miku/redis.lua")()
|
mime = (loadfile './miku/mimetype.lua')()
|
||||||
mimetype = (loadfile "./miku/mimetype.lua")()
|
OAuth = require 'OAuth'
|
||||||
OAuth = require "OAuth"
|
helpers = require 'OAuth.helpers'
|
||||||
helpers = require "OAuth.helpers"
|
|
||||||
|
|
||||||
http.timeout = 5
|
http.timeout = 5
|
||||||
https.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,
|
-- For the sake of ease to new contributors and familiarity to old contributors,
|
||||||
-- we'll provide a couple of aliases to real bindings here.
|
-- we'll provide a couple of aliases to real bindings here.
|
||||||
function utilities:send_message(chat_id, text, disable_web_page_preview, reply_to_message_id, use_markdown, reply_markup)
|
function utilities:send_message(chat_id, text, disable_web_page_preview, reply_to_message_id, use_markdown, reply_markup)
|
||||||
if use_markdown == true then
|
local parse_mode
|
||||||
use_markdown = 'Markdown'
|
if type(use_markdown) == 'string' then
|
||||||
elseif not use_markdown then
|
parse_mode = use_markdown
|
||||||
use_markdown = nil
|
elseif use_markdown == true then
|
||||||
|
parse_mode = 'Markdown'
|
||||||
end
|
end
|
||||||
return bindings.request(self, 'sendMessage', {
|
return bindings.request(self, 'sendMessage', {
|
||||||
chat_id = chat_id,
|
chat_id = chat_id,
|
||||||
text = text,
|
text = text,
|
||||||
disable_web_page_preview = disable_web_page_preview,
|
disable_web_page_preview = disable_web_page_preview,
|
||||||
reply_to_message_id = reply_to_message_id,
|
reply_to_message_id = reply_to_message_id,
|
||||||
parse_mode = use_markdown,
|
parse_mode = parse_mode,
|
||||||
reply_markup = reply_markup
|
reply_markup = reply_markup
|
||||||
} )
|
} )
|
||||||
end
|
end
|
||||||
|
|
||||||
-- https://core.telegram.org/bots/api#editmessagetext
|
-- https://core.telegram.org/bots/api#editmessagetext
|
||||||
function utilities:edit_message(chat_id, message_id, text, disable_web_page_preview, use_markdown, reply_markup)
|
function utilities:edit_message(chat_id, message_id, text, disable_web_page_preview, use_markdown, reply_markup)
|
||||||
if use_markdown == true then
|
local parse_mode
|
||||||
use_markdown = 'Markdown'
|
if type(use_markdown) == 'string' then
|
||||||
elseif not use_markdown then
|
parse_mode = use_markdown
|
||||||
use_markdown = nil
|
elseif use_markdown == true then
|
||||||
|
parse_mode = 'Markdown'
|
||||||
end
|
end
|
||||||
return bindings.request(self, 'editMessageText', {
|
return bindings.request(self, 'editMessageText', {
|
||||||
chat_id = chat_id,
|
chat_id = chat_id,
|
||||||
message_id = message_id,
|
message_id = message_id,
|
||||||
text = text,
|
text = text,
|
||||||
disable_web_page_preview = disable_web_page_preview,
|
disable_web_page_preview = disable_web_page_preview,
|
||||||
parse_mode = use_markdown,
|
parse_mode = parse_mode,
|
||||||
reply_markup = reply_markup
|
reply_markup = reply_markup
|
||||||
} )
|
} )
|
||||||
end
|
end
|
||||||
|
|
||||||
function utilities:send_reply(old_msg, text, use_markdown, reply_markup)
|
function utilities:send_reply(old_msg, text, use_markdown, reply_markup)
|
||||||
if use_markdown == true then
|
return utilities.send_message(self, old_msg.chat.id, text, true, old_msg.message_id, use_markdown, reply_markup)
|
||||||
use_markdown = 'Markdown'
|
|
||||||
elseif not use_markdown then
|
|
||||||
use_markdown = nil
|
|
||||||
end
|
|
||||||
return bindings.request(self, 'sendMessage', {
|
|
||||||
chat_id = old_msg.chat.id,
|
|
||||||
text = text,
|
|
||||||
disable_web_page_preview = true,
|
|
||||||
reply_to_message_id = old_msg.message_id,
|
|
||||||
parse_mode = use_markdown,
|
|
||||||
reply_markup = reply_markup
|
|
||||||
} )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- NOTE: Telegram currently only allows file uploads up to 50 MB
|
-- NOTE: Telegram currently only allows file uploads up to 50 MB
|
||||||
@ -227,21 +216,12 @@ end
|
|||||||
function utilities.get_word(s, i)
|
function utilities.get_word(s, i)
|
||||||
s = s or ''
|
s = s or ''
|
||||||
i = i or 1
|
i = i or 1
|
||||||
local t = {}
|
local n = 0
|
||||||
for w in s:gmatch('%g+') do
|
for w in s:gmatch('%g+') do
|
||||||
table.insert(t, w)
|
n = n + 1
|
||||||
|
if n == i then return w end
|
||||||
end
|
end
|
||||||
return t[i] or false
|
return false
|
||||||
end
|
|
||||||
|
|
||||||
-- Like get_word(), but better.
|
|
||||||
-- Returns the actual index.
|
|
||||||
function utilities.index(s)
|
|
||||||
local t = {}
|
|
||||||
for w in s:gmatch('%g+') do
|
|
||||||
table.insert(t, w)
|
|
||||||
end
|
|
||||||
return t
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Returns the string after the first space.
|
-- Returns the string after the first space.
|
||||||
@ -252,6 +232,10 @@ function utilities.input(s)
|
|||||||
return s:sub(s:find(' ')+1)
|
return s:sub(s:find(' ')+1)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function utilities.input_from_msg(msg)
|
||||||
|
return utilities.input(msg.text) or (msg.reply_to_message and #msg.reply_to_message.text > 0 and msg.reply_to_message.text) or false
|
||||||
|
end
|
||||||
|
|
||||||
-- Calculates the length of the given string as UTF-8 characters
|
-- Calculates the length of the given string as UTF-8 characters
|
||||||
function utilities.utf8_len(s)
|
function utilities.utf8_len(s)
|
||||||
local chars = 0
|
local chars = 0
|
||||||
@ -341,19 +325,19 @@ function vardump(value)
|
|||||||
print(serpent.block(value, {comment=false}))
|
print(serpent.block(value, {comment=false}))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Loads a json file as a table.
|
-- Loads a JSON file as a table.
|
||||||
function utilities.load_data(filename)
|
function utilities.load_data(filename)
|
||||||
local f = io.open(filename)
|
local f = io.open(filename)
|
||||||
if not f then
|
if f then
|
||||||
return {}
|
|
||||||
end
|
|
||||||
local s = f:read('*all')
|
local s = f:read('*all')
|
||||||
f:close()
|
f:close()
|
||||||
local data = json.decode(s)
|
return json.decode(s)
|
||||||
return data
|
else
|
||||||
|
return {}
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Saves a table to a json file.
|
-- Saves a table to a JSON file.
|
||||||
function utilities.save_data(filename, data)
|
function utilities.save_data(filename, data)
|
||||||
local s = json.encode(data)
|
local s = json.encode(data)
|
||||||
local f = io.open(filename, 'w')
|
local f = io.open(filename, 'w')
|
||||||
@ -363,9 +347,7 @@ end
|
|||||||
|
|
||||||
-- Gets coordinates for a location. Used by gMaps.lua, time.lua, weather.lua.
|
-- Gets coordinates for a location. Used by gMaps.lua, time.lua, weather.lua.
|
||||||
function utilities.get_coords(input, config)
|
function utilities.get_coords(input, config)
|
||||||
|
local url = 'https://maps.googleapis.com/maps/api/geocode/json?address='..URL.escape(input)..'&language=de'
|
||||||
local url = 'https://maps.googleapis.com/maps/api/geocode/json?address=' .. URL.escape(input)
|
|
||||||
|
|
||||||
local jstr, res = https.request(url)
|
local jstr, res = https.request(url)
|
||||||
if res ~= 200 then
|
if res ~= 200 then
|
||||||
return config.errors.connection
|
return config.errors.connection
|
||||||
@ -378,9 +360,9 @@ function utilities.get_coords(input, config)
|
|||||||
|
|
||||||
return {
|
return {
|
||||||
lat = jdat.results[1].geometry.location.lat,
|
lat = jdat.results[1].geometry.location.lat,
|
||||||
lon = jdat.results[1].geometry.location.lng
|
lon = jdat.results[1].geometry.location.lng,
|
||||||
|
addr = jdat.results[1].formatted_address
|
||||||
}
|
}
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Get the number of values in a key/value table.
|
-- Get the number of values in a key/value table.
|
||||||
@ -415,91 +397,15 @@ function utilities:resolve_username(input)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Simpler than above function; only returns an ID.
|
|
||||||
-- Returns nil if no ID is available.
|
|
||||||
function utilities:id_from_username(input)
|
|
||||||
input = input:gsub('^@', '')
|
|
||||||
for _, user in pairs(self.database.users) do
|
|
||||||
if user.username and user.username:lower() == input:lower() then
|
|
||||||
return user.id
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Simpler than below function; only returns an ID.
|
|
||||||
-- Returns nil if no ID is available.
|
|
||||||
function utilities:id_from_message(msg)
|
|
||||||
if msg.reply_to_message then
|
|
||||||
return msg.reply_to_message.from.id
|
|
||||||
else
|
|
||||||
local input = utilities.input(msg.text)
|
|
||||||
if input then
|
|
||||||
if tonumber(input) then
|
|
||||||
return tonumber(input)
|
|
||||||
elseif input:match('^@') then
|
|
||||||
return utilities.id_from_username(self, input)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function utilities:user_from_message(msg, no_extra)
|
|
||||||
local input = utilities.input(msg.text_lower)
|
|
||||||
local target = {}
|
|
||||||
if msg.reply_to_message then
|
|
||||||
for k,v in pairs(self.database.users[msg.reply_to_message.from.id_str]) do
|
|
||||||
target[k] = v
|
|
||||||
end
|
|
||||||
elseif input and tonumber(input) then
|
|
||||||
target.id = tonumber(input)
|
|
||||||
if self.database.users[input] then
|
|
||||||
for k,v in pairs(self.database.users[input]) do
|
|
||||||
target[k] = v
|
|
||||||
end
|
|
||||||
end
|
|
||||||
elseif input and input:match('^@') then
|
|
||||||
local uname = input:gsub('^@', '')
|
|
||||||
for _,v in pairs(self.database.users) do
|
|
||||||
if v.username and uname == v.username:lower() then
|
|
||||||
for key, val in pairs(v) do
|
|
||||||
target[key] = val
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not target.id then
|
|
||||||
target.err = 'Sorry, I don\'t recognize that username.'
|
|
||||||
end
|
|
||||||
else
|
|
||||||
target.err = 'Please specify a user via reply, ID, or username.'
|
|
||||||
end
|
|
||||||
|
|
||||||
if not no_extra then
|
|
||||||
if target.id then
|
|
||||||
target.id_str = tostring(target.id)
|
|
||||||
end
|
|
||||||
if not target.first_name then
|
|
||||||
target.first_name = 'User'
|
|
||||||
end
|
|
||||||
target.name = utilities.build_name(target.first_name, target.last_name)
|
|
||||||
end
|
|
||||||
|
|
||||||
return target
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
function utilities:handle_exception(err, message, config)
|
function utilities:handle_exception(err, message, config)
|
||||||
|
|
||||||
if not err then err = '' end
|
if not err then err = '' end
|
||||||
|
|
||||||
local output = '\n[' .. os.date('%F %T', os.time()) .. ']\n' .. self.info.username .. ': ' .. err .. '\n' .. message .. '\n'
|
local output = '\n[' .. os.date('%F %T', os.time()) .. ']\n' .. self.info.username .. ': ' .. err .. '\n' .. message .. '\n'
|
||||||
|
|
||||||
if config.log_chat then
|
if config.log_chat then
|
||||||
output = '```' .. output .. '```'
|
output = '```' .. output .. '```'
|
||||||
utilities.send_message(self, config.log_chat, output, true, nil, true)
|
utilities.send_message(self, config.log_chat, output, true, nil, true)
|
||||||
else
|
else
|
||||||
print(output)
|
print(output)
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
-- MOVED TO DOWNLOAD_TO_FILE
|
-- MOVED TO DOWNLOAD_TO_FILE
|
||||||
@ -507,15 +413,17 @@ function utilities.download_file(url, filename)
|
|||||||
return download_to_file(url, filename)
|
return download_to_file(url, filename)
|
||||||
end
|
end
|
||||||
|
|
||||||
function utilities.markdown_escape(text)
|
function utilities.md_escape(text)
|
||||||
text = text:gsub('_', '\\_')
|
return text:gsub('_', '\\_')
|
||||||
text = text:gsub('%[', '\\[')
|
:gsub('%[', '\\['):gsub('%]', '\\]')
|
||||||
text = text:gsub('%*', '\\*')
|
:gsub('%*', '\\*'):gsub('`', '\\`')
|
||||||
text = text:gsub('`', '\\`')
|
|
||||||
return text
|
|
||||||
end
|
end
|
||||||
|
|
||||||
utilities.md_escape = utilities.markdown_escape
|
utilities.markdown_escape = utilities.md_escape
|
||||||
|
|
||||||
|
function utilities.html_escape(text)
|
||||||
|
return text:gsub('&', '&'):gsub('<', '<'):gsub('>', '>')
|
||||||
|
end
|
||||||
|
|
||||||
utilities.triggers_meta = {}
|
utilities.triggers_meta = {}
|
||||||
utilities.triggers_meta.__index = utilities.triggers_meta
|
utilities.triggers_meta.__index = utilities.triggers_meta
|
||||||
@ -591,7 +499,8 @@ utilities.char = {
|
|||||||
arabic = '[\216-\219][\128-\191]',
|
arabic = '[\216-\219][\128-\191]',
|
||||||
rtl_override = '',
|
rtl_override = '',
|
||||||
rtl_mark = '',
|
rtl_mark = '',
|
||||||
em_dash = '—'
|
em_dash = '—',
|
||||||
|
utf_8 = '[%z\1-\127\194-\244][\128-\191]',
|
||||||
}
|
}
|
||||||
|
|
||||||
-- taken from http://stackoverflow.com/a/11130774/3163199
|
-- taken from http://stackoverflow.com/a/11130774/3163199
|
||||||
@ -610,7 +519,7 @@ function plugins_names()
|
|||||||
for k, v in pairs(scandir("miku/plugins")) do
|
for k, v in pairs(scandir("miku/plugins")) do
|
||||||
-- Ends with .lua
|
-- Ends with .lua
|
||||||
if (v:match(".lua$")) then
|
if (v:match(".lua$")) then
|
||||||
table.insert(files, v)
|
files[#files+1] = v
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
return files
|
return files
|
||||||
@ -723,6 +632,7 @@ function post_petition(url, arguments, headers)
|
|||||||
if type(arguments) == "table" then
|
if type(arguments) == "table" then
|
||||||
source = helpers.url_encode_arguments(arguments)
|
source = helpers.url_encode_arguments(arguments)
|
||||||
end
|
end
|
||||||
|
|
||||||
if not headers then
|
if not headers then
|
||||||
request_constructor.headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF8"
|
request_constructor.headers["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF8"
|
||||||
request_constructor.headers["X-Accept"] = "application/json"
|
request_constructor.headers["X-Accept"] = "application/json"
|
||||||
@ -800,8 +710,8 @@ function get_location(user_id)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function cache_data(plugin, query, data, timeout, typ)
|
function cache_data(plugin, query, data, timeout, typ, hash_field)
|
||||||
-- How to: cache_data(pluginname, query_name, data_to_cache, expire_in_seconds)
|
-- How to: cache_data(pluginname, query_name, data_to_cache, expire_in_seconds, type, hash_field (if hash))
|
||||||
local hash = 'telegram:cache:'..plugin..':'..query
|
local hash = 'telegram:cache:'..plugin..':'..query
|
||||||
if timeout then
|
if timeout then
|
||||||
print('Caching "'..query..'" from plugin '..plugin..' (expires in '..timeout..' seconds)')
|
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)
|
redis:sadd(hash, str)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
redis:hmset(hash, data)
|
redis:hset(hash, hash_field, data)
|
||||||
end
|
end
|
||||||
if timeout then
|
if timeout then
|
||||||
redis:expire(hash, timeout)
|
redis:expire(hash, timeout)
|
||||||
@ -841,6 +751,8 @@ function cache_file(result, url, last_modified)
|
|||||||
elseif result.result.photo then
|
elseif result.result.photo then
|
||||||
local lv = #result.result.photo
|
local lv = #result.result.photo
|
||||||
file_id = result.result.photo[lv].file_id
|
file_id = result.result.photo[lv].file_id
|
||||||
|
elseif result.result.sticker then
|
||||||
|
file_id = result.result.sticker.file_id
|
||||||
end
|
end
|
||||||
print('Caching File...')
|
print('Caching File...')
|
||||||
redis:hset(hash..':'..url, 'file_id', file_id)
|
redis:hset(hash..':'..url, 'file_id', file_id)
|
||||||
|
Reference in New Issue
Block a user