Alles miku
Erste Anpassungen für Mikudayobot
This commit is contained in:
41
miku/plugins/9gag.lua
Normal file
41
miku/plugins/9gag.lua
Normal file
@ -0,0 +1,41 @@
|
||||
local ninegag = {}
|
||||
|
||||
local HTTP = require('socket.http')
|
||||
local URL = require('socket.url')
|
||||
local JSON = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
ninegag.command = '9gag'
|
||||
|
||||
function ninegag:init(config)
|
||||
ninegag.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('9gag', true):t('9fag', true).table
|
||||
ninegag.doc = [[*
|
||||
]]..config.cmd_pat..[[9gag*: Gibt ein zufälliges Bild von den momentan populärsten 9GAG-Posts aus]]
|
||||
end
|
||||
|
||||
function ninegag:get_9GAG()
|
||||
local url = "http://api-9gag.herokuapp.com/"
|
||||
local b,c = HTTP.request(url)
|
||||
if c ~= 200 then return nil end
|
||||
local gag = JSON.decode(b)
|
||||
-- random max json table size
|
||||
local i = math.random(#gag) local link_image = gag[i].src
|
||||
local title = gag[i].title
|
||||
local post_url = gag[i].url
|
||||
return link_image, title, post_url
|
||||
end
|
||||
|
||||
function ninegag:action(msg, config)
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local url, title, post_url = ninegag:get_9GAG()
|
||||
if not url then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
return
|
||||
end
|
||||
|
||||
local file = download_to_file(url)
|
||||
utilities.send_photo(self, msg.chat.id, file, title, msg.message_id, '{"inline_keyboard":[[{"text":"Post aufrufen","url":"'..post_url..'"}]]}')
|
||||
end
|
||||
|
||||
return ninegag
|
38
miku/plugins/about.lua
Normal file
38
miku/plugins/about.lua
Normal file
@ -0,0 +1,38 @@
|
||||
local about = {}
|
||||
|
||||
local bot = require('miku.bot')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
about.command = 'about'
|
||||
about.doc = '`Sendet Informationen über den Bot.`'
|
||||
|
||||
about.triggers = {
|
||||
'/about',
|
||||
'/start'
|
||||
}
|
||||
|
||||
function about:action(msg, config)
|
||||
|
||||
-- Filthy hack, but here is where we'll stop forwarded messages from hitting
|
||||
-- other plugins.
|
||||
-- disabled to restore old behaviour
|
||||
-- if msg.forward_from then return end
|
||||
|
||||
local output = config.about_text .. '\nBrawlbot v'..bot.version..', basierend auf miku 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
|
||||
|
||||
return about
|
49
miku/plugins/adfly.lua
Normal file
49
miku/plugins/adfly.lua
Normal file
@ -0,0 +1,49 @@
|
||||
local adfly = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local HTTPS = require('ssl.https')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
function adfly:init(config)
|
||||
adfly.triggers = {
|
||||
'adf.ly/([A-Za-z0-9-_-]+)'
|
||||
}
|
||||
adfly.doc = [[*adf.ly-Link*: Postet vollen Link]]
|
||||
end
|
||||
|
||||
function adfly:expand_adfly_link(adfly_code)
|
||||
local BASE_URL = 'https://andibi.tk/dl/adfly.php'
|
||||
local url = BASE_URL..'/?url=http://adf.ly/'..adfly_code
|
||||
local res,code = HTTPS.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
if res == 'Fehler: Keine Adf.ly-URL gefunden!' then return 'NOTFOUND' end
|
||||
cache_data('adfly', adfly_code, res, 31536000, 'key')
|
||||
return res
|
||||
end
|
||||
|
||||
function adfly:action(msg)
|
||||
local input = msg.text
|
||||
if not input:match('adf.ly/([A-Za-z0-9-_-]+)') then
|
||||
return
|
||||
end
|
||||
|
||||
local adfly_code = input:match('adf.ly/([A-Za-z0-9-_-]+)')
|
||||
local hash = 'telegram:cache:adfly:'..adfly_code
|
||||
if redis:exists(hash) == false then
|
||||
local expanded_url = adfly:expand_adfly_link(adfly_code)
|
||||
if not expanded_url then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
return
|
||||
end
|
||||
if expanded_url == 'NOTFOUND' then
|
||||
utilities.send_reply(self, msg, 'Fehler: Keine Adf.ly-URL gefunden!')
|
||||
return
|
||||
end
|
||||
utilities.send_reply(self, msg, expanded_url)
|
||||
else
|
||||
local data = redis:get(hash)
|
||||
utilities.send_reply(self, msg, data)
|
||||
end
|
||||
end
|
||||
|
||||
return adfly
|
123
miku/plugins/afk.lua
Normal file
123
miku/plugins/afk.lua
Normal file
@ -0,0 +1,123 @@
|
||||
-- original plugin by Akamaru [https://ponywave.de]
|
||||
-- I added Redis and automatic online switching back in 2015
|
||||
|
||||
local afk = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
function afk:init(config)
|
||||
afk.triggers = {
|
||||
"^/([A|a][F|f][K|k])$",
|
||||
"^/([A|a][F|f][K|k]) (.*)$"
|
||||
}
|
||||
afk.doc = [[*
|
||||
]]..config.cmd_pat..[[afk* _[Text]_: Setzt Status auf AFK mit optionalem Text]]
|
||||
end
|
||||
|
||||
afk.command = 'afk [Text]'
|
||||
|
||||
function afk:is_offline(hash)
|
||||
local afk = redis:hget(hash, 'afk')
|
||||
if afk == "true" then
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function afk:get_afk_text(hash)
|
||||
local afk_text = redis:hget(hash, 'afk_text')
|
||||
if afk_text ~= nil and afk_text ~= "" and afk_text ~= "false" then
|
||||
return afk_text
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
function afk:switch_afk(user_name, user_id, chat_id, timestamp, text)
|
||||
local hash = 'afk:'..chat_id..':'..user_id
|
||||
|
||||
if afk:is_offline(hash) then
|
||||
local afk_text = afk:get_afk_text(hash)
|
||||
if afk_text then
|
||||
return 'Du bist bereits AFK ('..afk_text..')!'
|
||||
else
|
||||
return 'Du bist bereits AFK!'
|
||||
end
|
||||
end
|
||||
|
||||
print('Setting redis hash afk in '..hash..' to true')
|
||||
redis:hset(hash, 'afk', true)
|
||||
print('Setting redis hash timestamp in '..hash..' to '..timestamp)
|
||||
redis:hset(hash, 'time', timestamp)
|
||||
|
||||
if text then
|
||||
print('Setting redis hash afk_text in '..hash..' to '..text)
|
||||
redis:hset(hash, 'afk_text', text)
|
||||
return user_name..' ist AFK ('..text..')'
|
||||
else
|
||||
return user_name..' ist AFK'
|
||||
end
|
||||
end
|
||||
|
||||
function afk:pre_process(msg, self)
|
||||
if msg.chat.type == "private" then
|
||||
-- Ignore
|
||||
return
|
||||
end
|
||||
|
||||
local user_name = get_name(msg)
|
||||
local user_id = msg.from.id
|
||||
local chat_id = msg.chat.id
|
||||
local hash = 'afk:'..chat_id..':'..user_id
|
||||
|
||||
|
||||
if afk:is_offline(hash) then
|
||||
local afk_text = afk:get_afk_text(hash)
|
||||
|
||||
-- calculate afk time
|
||||
local timestamp = redis:hget(hash, 'time')
|
||||
local current_timestamp = msg.date
|
||||
local afk_time = current_timestamp - timestamp
|
||||
local seconds = afk_time % 60
|
||||
local minutes = math.floor(afk_time / 60)
|
||||
local minutes = minutes % 60
|
||||
local hours = math.floor(afk_time / 3600)
|
||||
if minutes == 00 and hours == 00 then
|
||||
duration = seconds..' Sekunden'
|
||||
elseif hours == 00 and minutes ~= 00 then
|
||||
duration = string.format("%02d:%02d", minutes, seconds)..' Minuten'
|
||||
elseif hours ~= 00 then
|
||||
duration = string.format("%02d:%02d:%02d", hours, minutes, seconds)..' Stunden'
|
||||
end
|
||||
|
||||
redis:hset(hash, 'afk', false)
|
||||
if afk_text then
|
||||
redis:hset(hash, 'afk_text', false)
|
||||
local afk_text = afk_text:gsub("%*","")
|
||||
local afk_text = afk_text:gsub("_","")
|
||||
utilities.send_message(self, msg.chat.id, user_name..' ist wieder da (war: *'..afk_text..'* für '..duration..')!', true, nil, true)
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, user_name..' ist wieder da (war '..duration..' weg)!')
|
||||
end
|
||||
end
|
||||
|
||||
return msg
|
||||
end
|
||||
|
||||
function afk:action(msg)
|
||||
if msg.chat.type == "private" then
|
||||
utilities.send_reply(self, msg, "Mir ist's egal, ob du AFK bist ._.")
|
||||
return
|
||||
end
|
||||
|
||||
local user_id = msg.from.id
|
||||
local chat_id = msg.chat.id
|
||||
local user_name = get_name(msg)
|
||||
local timestamp = msg.date
|
||||
|
||||
utilities.send_reply(self, msg, afk:switch_afk(user_name, user_id, chat_id, timestamp, matches[2]))
|
||||
end
|
||||
|
||||
return afk
|
117
miku/plugins/app_store.lua
Normal file
117
miku/plugins/app_store.lua
Normal file
@ -0,0 +1,117 @@
|
||||
local app_store = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
app_store.triggers = {
|
||||
"itunes.apple.com/(.*)/app/(.*)/id(%d+)",
|
||||
"^/itunes (%d+)$",
|
||||
"itunes.apple.com/app/id(%d+)"
|
||||
}
|
||||
|
||||
local BASE_URL = 'https://itunes.apple.com/lookup'
|
||||
|
||||
local makeOurDate = function(dateString)
|
||||
local pattern = "(%d+)%-(%d+)%-(%d+)T"
|
||||
local year, month, day = dateString:match(pattern)
|
||||
return day..'.'..month..'.'..year
|
||||
end
|
||||
|
||||
function app_store:get_appstore_data()
|
||||
local url = BASE_URL..'/?id='..appid..'&country=de'
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return "HTTP-FEHLER" end
|
||||
local data = json.decode(res).results[1]
|
||||
|
||||
if data == nil then return 'NOTFOUND' end
|
||||
if data.wrapperType ~= 'software' then return nil end
|
||||
|
||||
return data
|
||||
end
|
||||
|
||||
function app_store:send_appstore_data(data)
|
||||
-- Header
|
||||
local name = data.trackName
|
||||
local author = data.sellerName
|
||||
local price = data.formattedPrice
|
||||
local version = data.version
|
||||
|
||||
-- Body
|
||||
local description = string.sub(unescape(data.description), 1, 150) .. '...'
|
||||
local min_ios_ver = data.minimumOsVersion
|
||||
local size = string.gsub(round(data.fileSizeBytes / 1000000, 2), "%.", ",") -- wtf Apple, it's 1024, not 1000!
|
||||
local release = makeOurDate(data.releaseDate)
|
||||
if data.isGameCenterEnabled then
|
||||
game_center = '\nUnterstützt Game Center'
|
||||
else
|
||||
game_center = ''
|
||||
end
|
||||
local category_count = tablelength(data.genres)
|
||||
if category_count == 1 then
|
||||
category = '\nKategorie: '..data.genres[1]
|
||||
else
|
||||
local category_loop = '\nKategorien: '
|
||||
for v in pairs(data.genres) do
|
||||
if v < category_count then
|
||||
category_loop = category_loop..data.genres[v]..', '
|
||||
else
|
||||
category_loop = category_loop..data.genres[v]
|
||||
end
|
||||
end
|
||||
category = category_loop
|
||||
end
|
||||
|
||||
-- Footer
|
||||
if data.averageUserRating and data.userRatingCount then
|
||||
avg_rating = 'Bewertung: '..string.gsub(data.averageUserRating, "%.", ",")..' Sterne '
|
||||
ratings = 'von '..comma_value(data.userRatingCount)..' Bewertungen'
|
||||
else
|
||||
avg_rating = ""
|
||||
ratings = ""
|
||||
end
|
||||
|
||||
|
||||
local header = '*'..name..'* v'..version..' von *'..author..'* ('..price..'):'
|
||||
local body = '\n'..description..'\n_Benötigt mind. iOS '..min_ios_ver..'_\nGröße: '..size..' MB\nErstveröffentlicht am '..release..game_center..category
|
||||
local footer = '\n'..avg_rating..ratings
|
||||
local text = header..body..footer
|
||||
|
||||
-- Picture
|
||||
if data.screenshotUrls[1] and data.ipadScreenshotUrls[1] then
|
||||
image_url = data.screenshotUrls[1]
|
||||
elseif data.screenshotUrls[1] and not data.ipadScreenshotUrls[1] then
|
||||
image_url = data.screenshotUrls[1]
|
||||
elseif not data.screenshotUrls[1] and data.ipadScreenshotUrls[1] then
|
||||
image_url = data.ipadScreenshotUrls[1]
|
||||
else
|
||||
image_url = nil
|
||||
end
|
||||
|
||||
return text, image_url
|
||||
end
|
||||
|
||||
function app_store:action(msg, config, matches)
|
||||
if not matches[3] then
|
||||
appid = matches[1]
|
||||
else
|
||||
appid = matches[3]
|
||||
end
|
||||
local data = app_store:get_appstore_data()
|
||||
if data == nil then print('Das Appstore-Plugin unterstützt nur Apps!') end
|
||||
if data == 'HTTP-FEHLER' or data == 'NOTFOUND' then
|
||||
utilities.send_reply(self, msg, '*App nicht gefunden!*', true)
|
||||
return
|
||||
else
|
||||
local output, image_url = app_store:send_appstore_data(data)
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
if image_url then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(image_url)
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return app_store
|
75
miku/plugins/bImages.lua
Normal file
75
miku/plugins/bImages.lua
Normal file
@ -0,0 +1,75 @@
|
||||
local bImages = {}
|
||||
|
||||
local HTTPS = require('ssl.https')
|
||||
HTTPS.timeout = 10
|
||||
local URL = require('socket.url')
|
||||
local JSON = require('dkjson')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
function bImages:init(config)
|
||||
if not cred_data.bing_search_key then
|
||||
print('Missing config value: bing_search_key.')
|
||||
print('bImages.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
bImages.triggers = {"^/nil$"}
|
||||
bImages.inline_triggers = {
|
||||
"^b (.*)"
|
||||
}
|
||||
end
|
||||
|
||||
local apikey = cred_data.bing_search_key
|
||||
local BASE_URL = 'https://api.cognitive.microsoft.com/bing/v5.0'
|
||||
|
||||
function bImages:getImages(query)
|
||||
local url = BASE_URL..'/images/search?q='..URL.escape(query)..'&count=50&mkt=de-de'
|
||||
local response_body = {}
|
||||
local request_constructor = {
|
||||
url = url,
|
||||
method = "GET",
|
||||
sink = ltn12.sink.table(response_body),
|
||||
redirect = false,
|
||||
headers = {
|
||||
["Ocp-Apim-Subscription-Key"] = apikey
|
||||
}
|
||||
}
|
||||
local ok, response_code, response_headers = HTTPS.request(request_constructor)
|
||||
if not ok then return end
|
||||
local images = JSON.decode(table.concat(response_body)).value
|
||||
if not images[1] then return end
|
||||
|
||||
|
||||
|
||||
local results = '['
|
||||
for n in pairs(images) do
|
||||
if images[n].encodingFormat == 'jpeg' then -- Inline-Querys MUST use JPEG photos!
|
||||
local photo_url = images[n].contentUrl
|
||||
local thumb_url = images[n].thumbnailUrl
|
||||
results = results..'{"type":"photo","id":"'..math.random(100000000000000000)..'","photo_url":"'..photo_url..'","thumb_url":"'..thumb_url..'","photo_width":'..images[n].width..',"photo_height":'..images[n].height..',"reply_markup":{"inline_keyboard":[[{"text":"Bing aufrufen","url":"'..images[n].webSearchUrl..'"},{"text":"Bild aufrufen","url":"'..photo_url..'"}]]}},'
|
||||
end
|
||||
end
|
||||
|
||||
local results = results:sub(0, -2)
|
||||
local results = results..']'
|
||||
cache_data('bImages', string.lower(query), results, 1209600, 'key')
|
||||
return results
|
||||
end
|
||||
|
||||
function bImages:inline_callback(inline_query, config, matches)
|
||||
local query = matches[1]
|
||||
local results = redis:get('telegram:cache:bImages:'..string.lower(query))
|
||||
if not results then
|
||||
results = bImages:getImages(query)
|
||||
end
|
||||
|
||||
if not results then return end
|
||||
utilities.answer_inline_query(self, inline_query, results, 3600)
|
||||
end
|
||||
|
||||
function bImages:action()
|
||||
end
|
||||
|
||||
return bImages
|
253
miku/plugins/banhammer.lua
Normal file
253
miku/plugins/banhammer.lua
Normal file
@ -0,0 +1,253 @@
|
||||
local banhammer = {}
|
||||
|
||||
local bindings = require('miku.bindings')
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
banhammer.command = 'banhammer <nur für Superuser>'
|
||||
|
||||
function banhammer:init(config)
|
||||
banhammer.triggers = {
|
||||
"^/(whitelist) (enable)$",
|
||||
"^/(whitelist) (disable)$",
|
||||
"^/(whitelist) (user) (%d+)$",
|
||||
"^/(whitelist) (chat)$",
|
||||
"^/(whitelist) (delete) (user) (%d+)$",
|
||||
"^/(whitelist) (delete) (chat)$",
|
||||
"^/(ban) (user) (%d+)$",
|
||||
"^/(ban) (delete) (%d+)$",
|
||||
"^/(kick) (%d+)$"
|
||||
}
|
||||
banhammer.doc = [[*
|
||||
]]..config.cmd_pat..[[whitelist* _<enable>_/_<disable>_: Aktiviert/deaktiviert Whitelist
|
||||
*]]..config.cmd_pat..[[whitelist* user _<user#id>_: Whiteliste User
|
||||
*]]..config.cmd_pat..[[whitelist* chat: Whiteliste ganze Gruppe
|
||||
*]]..config.cmd_pat..[[whitelist* delete user _<user#id>_: Lösche User 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* delete _<user#id>_: Entbanne User
|
||||
*]]..config.cmd_pat..[[kick* _<user#id>_: Kicke User aus dem Chat]]
|
||||
end
|
||||
|
||||
function banhammer:kick_user(user_id, chat_id, self, onlykick)
|
||||
if user_id == tostring(our_id) then
|
||||
return "Ich werde mich nicht selbst kicken!"
|
||||
else
|
||||
local request = bindings.request(self, 'kickChatMember', {
|
||||
chat_id = chat_id,
|
||||
user_id = user_id
|
||||
} )
|
||||
if onlykick then return end
|
||||
if not request then return 'User gebannt, aber kicken war nicht erfolgreich. Bin ich Administrator oder ist der User hier überhaupt?' end
|
||||
return 'User '..user_id..' gebannt!'
|
||||
end
|
||||
end
|
||||
|
||||
function banhammer:ban_user(user_id, chat_id, self)
|
||||
if user_id == tostring(our_id) then
|
||||
return "Ich werde mich nicht selbst kicken!"
|
||||
else
|
||||
-- Save to redis
|
||||
local hash = 'banned:'..chat_id..':'..user_id
|
||||
redis:set(hash, true)
|
||||
-- Kick from chat
|
||||
return banhammer:kick_user(user_id, chat_id, self)
|
||||
end
|
||||
end
|
||||
|
||||
function banhammer:unban_user(user_id, chat_id, self, chat_type)
|
||||
local hash = 'banned:'..chat_id..':'..user_id
|
||||
redis:del(hash)
|
||||
if chat_type == 'supergroup' then -- how can bots be admins anyway?
|
||||
local request = bindings.request(self, 'unbanChatMember', {
|
||||
chat_id = chat_id,
|
||||
user_id = user_id
|
||||
} )
|
||||
end
|
||||
return 'User '..user_id..' wurde entbannt.'
|
||||
end
|
||||
|
||||
function banhammer:is_banned(user_id, chat_id)
|
||||
local hash = 'banned:'..chat_id..':'..user_id
|
||||
local banned = redis:get(hash)
|
||||
return banned or false
|
||||
end
|
||||
|
||||
function banhammer:is_user_whitelisted(id)
|
||||
local hash = 'whitelist:user#id'..id
|
||||
local white = redis:get(hash) or false
|
||||
return white
|
||||
end
|
||||
|
||||
function banhammer:is_chat_whitelisted(id)
|
||||
local hash = 'whitelist:chat#id'..id
|
||||
local white = redis:get(hash) or false
|
||||
return white
|
||||
end
|
||||
|
||||
function banhammer:pre_process(msg, self, config)
|
||||
-- SERVICE MESSAGE
|
||||
if msg.new_chat_member then
|
||||
local user_id = msg.new_chat_member.id
|
||||
print('Checking invited user '..user_id)
|
||||
local banned = banhammer:is_banned(user_id, msg.chat.id)
|
||||
if banned then
|
||||
print('User is banned!')
|
||||
banhammer:kick_user(user_id, msg.chat.id, self, true)
|
||||
end
|
||||
-- No further checks
|
||||
return msg
|
||||
end
|
||||
|
||||
-- BANNED USER TALKING
|
||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||
local user_id = msg.from.id
|
||||
local chat_id = msg.chat.id
|
||||
local banned = banhammer:is_banned(user_id, chat_id)
|
||||
if banned then
|
||||
print('Banned user talking!')
|
||||
banhammer:ban_user(user_id, chat_id, self)
|
||||
msg.text = ''
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- WHITELIST
|
||||
local hash = 'whitelist:enabled'
|
||||
local whitelist = redis:get(hash)
|
||||
local issudo = is_sudo(msg, config)
|
||||
|
||||
-- Allow all sudo users even if whitelist is allowed
|
||||
if whitelist and not issudo then
|
||||
print('Whitelist enabled and not sudo')
|
||||
-- Check if user or chat is whitelisted
|
||||
local allowed = banhammer:is_user_whitelisted(msg.from.id)
|
||||
local has_been_warned = redis:hget('user:'..msg.from.id, 'has_been_warned')
|
||||
|
||||
if not allowed then
|
||||
print('User '..msg.from.id..' not whitelisted')
|
||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||
allowed = banhammer:is_chat_whitelisted(msg.chat.id)
|
||||
if not allowed then
|
||||
print ('Chat '..msg.chat.id..' not whitelisted')
|
||||
else
|
||||
print ('Chat '..msg.chat.id..' whitelisted :)')
|
||||
end
|
||||
else
|
||||
if not has_been_warned then
|
||||
utilities.send_reply(self, msg, "Dies ist ein privater Bot, der erst nach einer Freischaltung benutzt werden kann.\nThis is a private bot, which can only be after an approval.")
|
||||
redis:hset('user:'..msg.from.id, 'has_been_warned', true)
|
||||
else
|
||||
print('User has already been warned!')
|
||||
end
|
||||
end
|
||||
else
|
||||
print('User '..msg.from.id..' allowed :)')
|
||||
end
|
||||
|
||||
if not allowed then
|
||||
msg.text = ''
|
||||
msg.text_lower = ''
|
||||
msg.entities = ''
|
||||
end
|
||||
|
||||
-- else
|
||||
-- print('Whitelist not enabled or is sudo')
|
||||
end
|
||||
|
||||
return msg
|
||||
end
|
||||
|
||||
function banhammer:action(msg, config, matches)
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
|
||||
if matches[1] == 'ban' then
|
||||
local user_id = matches[3]
|
||||
local chat_id = msg.chat.id
|
||||
|
||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||
if matches[2] == 'user' then
|
||||
local text = banhammer:ban_user(user_id, chat_id, self)
|
||||
utilities.send_reply(self, msg, text)
|
||||
return
|
||||
end
|
||||
if matches[2] == 'delete' then
|
||||
local text = banhammer:unban_user(user_id, chat_id, self, msg.chat.type)
|
||||
utilities.send_reply(self, msg, text)
|
||||
return
|
||||
end
|
||||
else
|
||||
utilities.send_reply(self, msg, 'Das ist keine Chat-Gruppe')
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if matches[1] == 'kick' then
|
||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||
banhammer:kick_user(matches[2], msg.chat.id, self, true)
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, 'Das ist keine Chat-Gruppe')
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if matches[1] == 'whitelist' then
|
||||
if matches[2] == 'enable' then
|
||||
local hash = 'whitelist:enabled'
|
||||
redis:set(hash, true)
|
||||
utilities.send_reply(self, msg, 'Whitelist aktiviert')
|
||||
return
|
||||
end
|
||||
|
||||
if matches[2] == 'disable' then
|
||||
local hash = 'whitelist:enabled'
|
||||
redis:del(hash)
|
||||
utilities.send_reply(self, msg, 'Whitelist deaktiviert')
|
||||
return
|
||||
end
|
||||
|
||||
if matches[2] == 'user' then
|
||||
local hash = 'whitelist:user#id'..matches[3]
|
||||
redis:set(hash, true)
|
||||
utilities.send_reply(self, msg, 'User '..matches[3]..' whitelisted')
|
||||
return
|
||||
end
|
||||
|
||||
if matches[2] == 'chat' then
|
||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||
local hash = 'whitelist:chat#id'..msg.chat.id
|
||||
redis:set(hash, true)
|
||||
utilities.send_reply(self, msg, 'Chat '..msg.chat.id..' whitelisted')
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, 'Das ist keine Chat-Gruppe!')
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if matches[2] == 'delete' and matches[3] == 'user' then
|
||||
local hash = 'whitelist:user#id'..matches[4]
|
||||
redis:del(hash)
|
||||
utilities.send_reply(self, msg, 'User '..matches[4]..' von der Whitelist entfernt!')
|
||||
return
|
||||
end
|
||||
|
||||
if matches[2] == 'delete' and matches[3] == 'chat' then
|
||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||
local hash = 'whitelist:chat#id'..msg.chat.id
|
||||
redis:del(hash)
|
||||
utilities.send_reply(self, msg, 'Chat '..msg.chat.id..' von der Whitelist entfernt')
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, 'Das ist keine Chat-Gruppe!')
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return banhammer
|
48
miku/plugins/bitly.lua
Normal file
48
miku/plugins/bitly.lua
Normal file
@ -0,0 +1,48 @@
|
||||
local bitly = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
function bitly:init(config)
|
||||
if not cred_data.bitly_access_token then
|
||||
print('Missing config value: bitly_access_token.')
|
||||
print('bitly.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
bitly.triggers = {
|
||||
"bit.ly/([A-Za-z0-9-_-]+)",
|
||||
"bitly.com/([A-Za-z0-9-_-]+)",
|
||||
"j.mp/([A-Za-z0-9-_-]+)",
|
||||
"andib.tk/([A-Za-z0-9-_-]+)"
|
||||
}
|
||||
end
|
||||
|
||||
local BASE_URL = 'https://api-ssl.bitly.com/v3/expand'
|
||||
|
||||
function bitly:expand_bitly_link (shorturl)
|
||||
local access_token = cred_data.bitly_access_token
|
||||
local url = BASE_URL..'?access_token='..access_token..'&shortUrl=https://bit.ly/'..shorturl
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return "HTTP-FEHLER" end
|
||||
local data = json.decode(res).data.expand[1]
|
||||
cache_data('bitly', shorturl, data)
|
||||
return data.long_url
|
||||
end
|
||||
|
||||
function bitly:action(msg, config, matches)
|
||||
local shorturl = matches[1]
|
||||
local hash = 'telegram:cache:bitly:'..shorturl
|
||||
if redis:exists(hash) == false then
|
||||
utilities.send_reply(self, msg, bitly:expand_bitly_link(shorturl))
|
||||
return
|
||||
else
|
||||
local data = redis:hgetall(hash)
|
||||
utilities.send_reply(self, msg, data.long_url)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return bitly
|
146
miku/plugins/bitly_create.lua
Normal file
146
miku/plugins/bitly_create.lua
Normal file
@ -0,0 +1,146 @@
|
||||
local bitly_create = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local https = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
local OAuth = require "OAuth"
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
function bitly_create:init(config)
|
||||
if not cred_data.bitly_client_id then
|
||||
print('Missing config value: bitly_client_id.')
|
||||
print('bitly_create.lua will not be enabled.')
|
||||
return
|
||||
elseif not cred_data.bitly_client_secret then
|
||||
print('Missing config value: bitly_client_secret.')
|
||||
print('bitly_create.lua will not be enabled.')
|
||||
return
|
||||
elseif not cred_data.bitly_redirect_uri then
|
||||
print('Missing config value: bitly_redirect_uri.')
|
||||
print('bitly_create.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
bitly_create.triggers = {
|
||||
"^/short(auth)(.+)$",
|
||||
"^/short (auth)$",
|
||||
"^/short (unauth)$",
|
||||
"^/short (me)$",
|
||||
"^/short (j.mp) (https?://[%w-_%.%?%.:/%+=&]+)$",
|
||||
"^/short (bit.ly) (https?://[%w-_%.%?%.:/%+=&]+)$",
|
||||
"^/short (bitly.com) (https?://[%w-_%.%?%.:/%+=&]+)$",
|
||||
"^/short (https?://[%w-_%.%?%.:/%+=&]+)$"
|
||||
}
|
||||
bitly_create.doc = [[*
|
||||
]]..config.cmd_pat..[[short* _<Link>_: Kürzt einen Link mit der Standard Bitly-Adresse
|
||||
*]]..config.cmd_pat..[[short* _<j.mp|bit.ly|bitly.com>_ _[Link]_: Kürzt einen Link mit der ausgewählten Kurz-URL
|
||||
*]]..config.cmd_pat..[[short* _auth_: Loggt deinen Account ein und nutzt ihn für deine Links (empfohlen!)
|
||||
*]]..config.cmd_pat..[[short* _me_: Gibt den eingeloggten Account aus
|
||||
*]]..config.cmd_pat..[[short* _unauth_: Loggt deinen Account aus
|
||||
]]
|
||||
end
|
||||
|
||||
bitly_create.command = 'short <URL>'
|
||||
|
||||
local BASE_URL = 'https://api-ssl.bitly.com'
|
||||
|
||||
local client_id = cred_data.bitly_client_id
|
||||
local client_secret = cred_data.bitly_client_secret
|
||||
local redirect_uri = cred_data.bitly_redirect_uri
|
||||
|
||||
function bitly_create:get_bitly_access_token(hash, code)
|
||||
local req = post_petition(BASE_URL..'/oauth/access_token', 'client_id='..client_id..'&client_secret='..client_secret..'&code='..code..'&redirect_uri='..redirect_uri)
|
||||
if not req.access_token then return '*Fehler beim Einloggen!*' end
|
||||
|
||||
local access_token = req.access_token
|
||||
local login_name = req.login
|
||||
redis:hset(hash, 'bitly', access_token)
|
||||
return 'Erfolgreich als `'..login_name..'` eingeloggt!'
|
||||
end
|
||||
|
||||
function bitly_create:get_bitly_user_info(bitly_access_token)
|
||||
local url = BASE_URL..'/v3/user/info?access_token='..bitly_access_token..'&format=json'
|
||||
local res,code = https.request(url)
|
||||
if code == 401 then return 'Login fehlgeschlagen!' end
|
||||
if code ~= 200 then return 'HTTP-Fehler!' end
|
||||
|
||||
local data = json.decode(res).data
|
||||
|
||||
if data.full_name then
|
||||
name = '*'..data.full_name..'* (`'..data.login..'`)'
|
||||
else
|
||||
name = '`'..data.login..'`'
|
||||
end
|
||||
|
||||
local text = 'Eingeloggt als '..name
|
||||
|
||||
return text
|
||||
end
|
||||
|
||||
function bitly_create:create_bitlink (long_url, domain, bitly_access_atoken)
|
||||
local url = BASE_URL..'/v3/shorten?access_token='..bitly_access_token..'&domain='..domain..'&longUrl='..long_url..'&format=txt'
|
||||
local text,code = https.request(url)
|
||||
if code ~= 200 then return 'FEHLER: '..text end
|
||||
return text
|
||||
end
|
||||
|
||||
function bitly_create:action(msg, config, matches)
|
||||
local hash = 'user:'..msg.from.id
|
||||
bitly_access_token = redis:hget(hash, 'bitly')
|
||||
|
||||
if matches[1] == 'auth' and matches[2] then
|
||||
utilities.send_reply(self, msg, bitly_create:get_bitly_access_token(hash, matches[2]), true)
|
||||
local message_id = redis:hget(hash, 'bitly_login_msg')
|
||||
utilities.edit_message(self, msg.chat.id, message_id, '*Anmeldung abgeschlossen!*', true, true)
|
||||
redis:hdel(hash, 'bitly_login_msg')
|
||||
return
|
||||
end
|
||||
|
||||
if matches[1] == 'auth' then
|
||||
local result = utilities.send_reply(self, msg, '*Bitte logge dich ein und folge den Anweisungen.*', true, '{"inline_keyboard":[[{"text":"Bei Bitly anmelden","url":"https://bitly.com/oauth/authorize?client_id='..client_id..'&redirect_uri='..redirect_uri..'&state='..self.info.username..'"}]]}')
|
||||
redis:hset(hash, 'bitly_login_msg', result.result.message_id)
|
||||
return
|
||||
end
|
||||
|
||||
if matches[1] == 'unauth' and bitly_access_token then
|
||||
redis:hdel(hash, 'bitly')
|
||||
utilities.send_reply(self, msg, '*Erfolgreich ausgeloggt!* Du kannst den Zugriff [in deinen Kontoeinstellungen](https://bitly.com/a/settings/connected) endgültig entziehen.', true)
|
||||
return
|
||||
elseif matches[1] == 'unauth' and not bitly_access_token then
|
||||
utilities.send_reply(self, msg, 'Wie willst du dich ausloggen, wenn du gar nicht eingeloggt bist?', true)
|
||||
return
|
||||
end
|
||||
|
||||
if matches[1] == 'me' and bitly_access_token then
|
||||
local text = bitly_create:get_bitly_user_info(bitly_access_token)
|
||||
if text then
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
return
|
||||
else
|
||||
return
|
||||
end
|
||||
elseif matches[1] == 'me' and not bitly_access_token then
|
||||
utilities.send_reply(self, msg, 'Du bist nicht eingeloggt! Logge dich ein mit\n/short auth', true)
|
||||
return
|
||||
end
|
||||
|
||||
if not bitly_access_token then
|
||||
print('Not signed in, will use global bitly access_token')
|
||||
bitly_access_token = cred_data.bitly_access_token
|
||||
end
|
||||
|
||||
if matches[2] == nil then
|
||||
long_url = url_encode(matches[1])
|
||||
domain = 'bit.ly'
|
||||
else
|
||||
long_url = url_encode(matches[2])
|
||||
domain = matches[1]
|
||||
end
|
||||
utilities.send_reply(self, msg, bitly_create:create_bitlink(long_url, domain, bitly_access_token))
|
||||
return
|
||||
end
|
||||
|
||||
return bitly_create
|
51
miku/plugins/br.lua
Normal file
51
miku/plugins/br.lua
Normal file
@ -0,0 +1,51 @@
|
||||
local br = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
br.triggers = {
|
||||
"br.de/nachrichten/(.*).html$"
|
||||
}
|
||||
|
||||
function br:get_br_article(article)
|
||||
local url = 'https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20html%20where%20url=%22http://www.br.de/nachrichten/'..article..'.html%22%20and%20xpath=%22//div[@id=%27content%27]/div[1]/div[2]/div[1]|//div[@class=%27lead_picture%27]/img%22&format=json'
|
||||
local res,code = https.request(url)
|
||||
local data = json.decode(res).query.results
|
||||
if code ~= 200 then return "HTTP-Fehler" end
|
||||
if not data then return "HTTP-Fehler" end
|
||||
|
||||
local subtitle = data.div.h1.em
|
||||
local title = string.sub(data.div.h1.content, 3)
|
||||
local teaser = string.sub(data.div.p[1].content, 2)
|
||||
if data.div.p[3] then
|
||||
updated = data.div.p[3].content
|
||||
else
|
||||
updated = data.div.p[2].content
|
||||
end
|
||||
if data.img then
|
||||
image_url = 'https://www.br.de'..data.img.src
|
||||
end
|
||||
local text = '*'..subtitle..' - '..title..'*'..teaser..'\n_'..updated..'_'
|
||||
|
||||
if data.img then
|
||||
return text, image_url
|
||||
else
|
||||
return text
|
||||
end
|
||||
end
|
||||
|
||||
function br:action(msg, config, matches)
|
||||
local article = URL.escape(matches[1])
|
||||
local text, image_url = br:get_br_article(article)
|
||||
if image_url then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(image_url, 'br_teaser.jpg')
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
|
||||
return br
|
40
miku/plugins/btc.lua
Normal file
40
miku/plugins/btc.lua
Normal file
@ -0,0 +1,40 @@
|
||||
local btc = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
function btc:init(config)
|
||||
btc.triggers = {
|
||||
"^/btc$"
|
||||
}
|
||||
btc.doc = [[*
|
||||
]]..config.cmd_pat..[[btc*: Zeigt aktuellen Bitcoin-Kurs an]]
|
||||
end
|
||||
|
||||
btc.command = 'btc'
|
||||
|
||||
-- See https://bitcoinaverage.com/api
|
||||
function btc:getBTCX()
|
||||
local base_url = 'https://api.bitcoinaverage.com/ticker/global/'
|
||||
-- Do request on bitcoinaverage, the final / is critical!
|
||||
local res,code = https.request(base_url.."EUR/")
|
||||
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)
|
||||
local ask = string.gsub(data.ask, "%.", ",")
|
||||
local bid = string.gsub(data.bid, "%.", ",")
|
||||
|
||||
-- Easy, it's right there
|
||||
text = 'BTC/EUR\n'..'*Kaufen:* '..ask..'\n'..'*Verkaufen:* '..bid
|
||||
return text
|
||||
end
|
||||
|
||||
|
||||
function btc:action(msg, config, matches)
|
||||
utilities.send_reply(self, msg, btc:getBTCX(cur), true)
|
||||
end
|
||||
|
||||
return btc
|
39
miku/plugins/calc.lua
Normal file
39
miku/plugins/calc.lua
Normal file
@ -0,0 +1,39 @@
|
||||
local calc = {}
|
||||
|
||||
local URL = require('socket.url')
|
||||
local http = require('socket.http')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
calc.command = 'calc <Ausdruck>'
|
||||
|
||||
function calc:init(config)
|
||||
calc.triggers = {
|
||||
"^/calc (.*)$"
|
||||
}
|
||||
calc.doc = [[*
|
||||
]]..config.cmd_pat..[[calc* _[Ausdruck]_: Rechnet]]
|
||||
end
|
||||
|
||||
function calc:mathjs(exp)
|
||||
local exp = string.gsub(exp, ",", "%.")
|
||||
local url = 'http://api.mathjs.org/v1/'
|
||||
url = url..'?expr='..URL.escape(exp)
|
||||
local b,c = http.request(url)
|
||||
local text = nil
|
||||
if c == 200 then
|
||||
text = '= '..string.gsub(b, "%.", ",")
|
||||
|
||||
elseif c == 400 then
|
||||
text = b
|
||||
else
|
||||
text = 'Unerwarteter Fehler\n'
|
||||
..'Ist api.mathjs.org erreichbar?'
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
function calc:action(msg, config, matches)
|
||||
utilities.send_reply(self, msg, calc:mathjs(matches[1]))
|
||||
end
|
||||
|
||||
return calc
|
39
miku/plugins/cats.lua
Normal file
39
miku/plugins/cats.lua
Normal file
@ -0,0 +1,39 @@
|
||||
local cats = {}
|
||||
|
||||
local HTTP = require('socket.http')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
cats.command = 'cat [gif]'
|
||||
|
||||
function cats:init(config)
|
||||
if not cred_data.cat_apikey then
|
||||
print('Missing config value: cat_apikey.')
|
||||
print('cats.lua will be enabled, but there are more features with a key.')
|
||||
end
|
||||
|
||||
cats.triggers = {
|
||||
"^/cat$",
|
||||
"^/cat (gif)$"
|
||||
}
|
||||
|
||||
cats.doc = [[*
|
||||
]]..config.cmd_pat..[[cat*: Postet eine zufällige Katze
|
||||
*]]..config.cmd_pat..[[cat* _gif_: Postet eine zufällige, animierte Katze]]
|
||||
end
|
||||
|
||||
|
||||
local apikey = cred_data.cat_apikey or "" -- apply for one here: http://thecatapi.com/api-key-registration.html
|
||||
|
||||
function cats:action(msg, config)
|
||||
if matches[1] == 'gif' then
|
||||
local url = 'http://thecatapi.com/api/images/get?type=gif&apikey='..apikey
|
||||
local file = download_to_file(url, 'miau.gif')
|
||||
utilities.send_document(self, msg.chat.id, file, nil, msg.message_id)
|
||||
else
|
||||
local url = 'http://thecatapi.com/api/images/get?type=jpg,png&apikey='..apikey
|
||||
local file = download_to_file(url, 'miau.png')
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
end
|
||||
|
||||
return cats
|
63
miku/plugins/channel.lua
Normal file
63
miku/plugins/channel.lua
Normal file
@ -0,0 +1,63 @@
|
||||
local channel = {}
|
||||
|
||||
local bindings = require('miku.bindings')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
channel.command = 'ch <Kanal> \\n <Nachricht>'
|
||||
channel.doc = [[*
|
||||
/ch*_ <Kanal>_
|
||||
_<Nachricht>_
|
||||
|
||||
Sendet eine Nachricht in den Kanal. Der Kanal kann per Username oder ID bestimmt werden, Markdown wird unterstützt. Du musst Administrator oder Besitzer des Kanals sein.
|
||||
|
||||
Markdown-Syntax:
|
||||
*Fetter Text*
|
||||
_Kursiver Text_
|
||||
[Text](URL)
|
||||
`Inline-Codeblock`
|
||||
```Größere Code-Block über mehrere Zeilen```
|
||||
|
||||
*Der Kanalname muss mit einem @ beginnen!*]]
|
||||
|
||||
function channel:init(config)
|
||||
channel.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('ch', true).table
|
||||
end
|
||||
|
||||
function channel:action(msg, config)
|
||||
local input = utilities.input(msg.text)
|
||||
local output
|
||||
if input then
|
||||
local chat_id = utilities.get_word(input, 1)
|
||||
local admin_list, t = bindings.getChatAdministrators(self, { chat_id = chat_id } )
|
||||
if admin_list then
|
||||
local is_admin = false
|
||||
for _, admin in ipairs(admin_list.result) do
|
||||
if admin.user.id == msg.from.id then
|
||||
is_admin = true
|
||||
end
|
||||
end
|
||||
if is_admin then
|
||||
local text = input:match('\n(.+)')
|
||||
if text then
|
||||
local success, result = utilities.send_message(self, chat_id, text, true, nil, true)
|
||||
if success then
|
||||
output = 'Deine Nachricht wurde versendet!'
|
||||
else
|
||||
output = 'Sorry, ich konnte deine Nachricht nicht senden.\n`' .. result.description .. '`'
|
||||
end
|
||||
else
|
||||
output = 'Bitte gebe deine Nachricht ein. Markdown wird unterstützt.'
|
||||
end
|
||||
else
|
||||
output = 'Es sieht nicht so aus, als wärst du der Administrator dieses Kanals.'
|
||||
end
|
||||
else
|
||||
output = 'Sorry, ich konnte die Administratorenliste nicht abrufen. Falls du den Kanalnamen benutzt: Beginnt er mit einem @?\n`' .. t.description .. '`'
|
||||
end
|
||||
else
|
||||
output = channel.doc
|
||||
end
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
end
|
||||
|
||||
return channel
|
90
miku/plugins/channels.lua
Normal file
90
miku/plugins/channels.lua
Normal file
@ -0,0 +1,90 @@
|
||||
local channels = {}
|
||||
|
||||
local bindings = require('miku.bindings')
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
channels.command = 'channel <nur für Superuser>'
|
||||
|
||||
function channels:init(config)
|
||||
channels.triggers = {
|
||||
"^/channel? (enable)",
|
||||
"^/channel? (disable)"
|
||||
}
|
||||
channels.doc = [[*
|
||||
]]..config.cmd_pat..[[channel* _<enable>_/_<disable>_: Aktiviert/deaktiviert den Bot im Chat]]
|
||||
end
|
||||
|
||||
-- Checks if bot was disabled on specific chat
|
||||
function channels:is_channel_disabled(msg)
|
||||
local hash = 'chat:'..msg.chat.id..':disabled'
|
||||
local disabled = redis:get(hash)
|
||||
|
||||
if not disabled or disabled == "false" then
|
||||
return false
|
||||
end
|
||||
|
||||
return disabled
|
||||
end
|
||||
|
||||
function channels:enable_channel(msg)
|
||||
local hash = 'chat:'..msg.chat.id..':disabled'
|
||||
local disabled = redis:get(hash)
|
||||
if disabled then
|
||||
print('Setting redis variable '..hash..' to false')
|
||||
redis:set(hash, false)
|
||||
return 'Channel aktiviert'
|
||||
else
|
||||
return 'Channel ist nicht deaktiviert!'
|
||||
end
|
||||
end
|
||||
|
||||
function channels:disable_channel(msg)
|
||||
local hash = 'chat:'..msg.chat.id..':disabled'
|
||||
local disabled = redis:get(hash)
|
||||
if disabled ~= "true" then
|
||||
print('Setting redis variable '..hash..' to true')
|
||||
redis:set(hash, true)
|
||||
return 'Channel deaktiviert'
|
||||
else
|
||||
return 'Channel ist bereits deaktiviert!'
|
||||
end
|
||||
end
|
||||
|
||||
function channels:pre_process(msg, self, config)
|
||||
-- If is sudo can reeanble the channel
|
||||
if is_sudo(msg, config) then
|
||||
if msg.text == "/channel enable" then
|
||||
channels:enable_channel(msg)
|
||||
end
|
||||
end
|
||||
|
||||
if channels:is_channel_disabled(msg) then
|
||||
print('Channel wurde deaktiviert')
|
||||
msg.text = ''
|
||||
msg.text_lower = ''
|
||||
msg.entities = ''
|
||||
end
|
||||
|
||||
return msg
|
||||
end
|
||||
|
||||
function channels:action(msg, config, matches)
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
|
||||
-- Enable a channel
|
||||
if matches[1] == 'enable' then
|
||||
utilities.send_reply(self, msg, channels:enable_channel(msg))
|
||||
return
|
||||
end
|
||||
-- Disable a channel
|
||||
if matches[1] == 'disable' then
|
||||
utilities.send_reply(self, msg, channels:disable_channel(msg))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return channels
|
35
miku/plugins/cleverbot.lua
Normal file
35
miku/plugins/cleverbot.lua
Normal file
@ -0,0 +1,35 @@
|
||||
local cleverbot = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local utilities = require('miku.utilities')
|
||||
local json = require('dkjson')
|
||||
|
||||
function cleverbot:init(config)
|
||||
cleverbot.triggers = {
|
||||
"^/cbot (.*)$"
|
||||
}
|
||||
|
||||
cleverbot.doc = [[*
|
||||
]]..config.cmd_pat..[[cbot* _<Text>_*: Befragt den Cleverbot]]
|
||||
end
|
||||
|
||||
cleverbot.command = 'cbot <Text>'
|
||||
|
||||
function cleverbot:action(msg, config)
|
||||
local text = msg.text
|
||||
local url = "https://brawlbot.tk/apis/chatter-bot-api/cleverbot.php?text="..URL.escape(text)
|
||||
local query = https.request(url)
|
||||
if query == nil then utilities.send_reply(self, msg, 'Ein Fehler ist aufgetreten :(') return end
|
||||
local decode = json.decode(query)
|
||||
local answer = string.gsub(decode.clever, "Ä", "Ä")
|
||||
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, "ß", "ß")
|
||||
utilities.send_reply(self, msg, answer)
|
||||
end
|
||||
|
||||
return cleverbot
|
33
miku/plugins/clypit.lua
Normal file
33
miku/plugins/clypit.lua
Normal file
@ -0,0 +1,33 @@
|
||||
local clypit = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
clypit.triggers = {
|
||||
"clyp.it/([A-Za-z0-9-_-]+)"
|
||||
}
|
||||
|
||||
function clypit:get_clypit_details(shortcode)
|
||||
local BASE_URL = "http://api.clyp.it"
|
||||
local url = BASE_URL..'/'..shortcode
|
||||
local res,code = http.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)
|
||||
|
||||
local title = data.Title
|
||||
local duration = data.Duration
|
||||
|
||||
local audio = download_to_file(data.Mp3Url)
|
||||
return audio, title, duration
|
||||
end
|
||||
|
||||
function clypit:action(msg, config, matches)
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_audio')
|
||||
local audio, title, duration = clypit:get_clypit_details(matches[1])
|
||||
if not audio then return utilities.send_reply(self, msg, config.errors.connection) end
|
||||
utilities.send_audio(self, msg.chat.id, audio, nil, msg.message_id, duration, nil, title)
|
||||
end
|
||||
|
||||
return clypit
|
56
miku/plugins/control.lua
Normal file
56
miku/plugins/control.lua
Normal file
@ -0,0 +1,56 @@
|
||||
local control = {}
|
||||
|
||||
local bot = require('miku.bot')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
local cmd_pat -- Prevents the command from being uncallable.
|
||||
|
||||
function control:init(config)
|
||||
cmd_pat = config.cmd_pat
|
||||
control.triggers = utilities.triggers(self.info.username, cmd_pat,
|
||||
{'^'..cmd_pat..'script'}):t('restart', true):t('halt').table
|
||||
end
|
||||
|
||||
function control:action(msg, config)
|
||||
|
||||
if msg.from.id ~= config.admin then
|
||||
return
|
||||
end
|
||||
|
||||
if msg.date < os.time() - 2 then return end
|
||||
|
||||
if msg.text_lower:match('^'..cmd_pat..'restart') then
|
||||
for pac, _ in pairs(package.loaded) do
|
||||
if pac:match('^miku%.plugins%.') then
|
||||
package.loaded[pac] = nil
|
||||
end
|
||||
end
|
||||
package.loaded['miku.bindings'] = nil
|
||||
package.loaded['miku.utilities'] = nil
|
||||
package.loaded['config'] = nil
|
||||
if msg.text_lower:match('%+config') then for k, v in pairs(require('config')) do
|
||||
config[k] = v
|
||||
end end
|
||||
bot.init(self, config)
|
||||
utilities.send_reply(self, msg, 'Bot neu gestartet!')
|
||||
elseif msg.text_lower:match('^'..cmd_pat..'halt') then
|
||||
self.is_started = false
|
||||
utilities.send_reply(self, msg, 'Stoppe Bot!')
|
||||
elseif msg.text_lower:match('^'..cmd_pat..'script') then
|
||||
local input = msg.text_lower:match('^'..cmd_pat..'script\n(.+)')
|
||||
if not input then
|
||||
utilities.send_reply(self, msg, 'usage: ```\n'..cmd_pat..'script\n'..cmd_pat..'command <arg>\n...\n```', true)
|
||||
return
|
||||
end
|
||||
input = input .. '\n'
|
||||
for command in input:gmatch('(.-)\n') do
|
||||
command = utilities.trim(command)
|
||||
msg.text = command
|
||||
bot.on_msg_receive(self, msg, config)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return control
|
||||
|
125
miku/plugins/creds.lua
Normal file
125
miku/plugins/creds.lua
Normal file
@ -0,0 +1,125 @@
|
||||
local creds_manager = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
function creds_manager:init(config)
|
||||
creds_manager.triggers = {
|
||||
"^(/creds)$",
|
||||
"^(/creds add) ([^%s]+) (.+)$",
|
||||
"^(/creds del) (.+)$",
|
||||
"^(/creds rename) ([^%s]+) (.+)$"
|
||||
}
|
||||
creds_manager.doc = [[*
|
||||
]]..config.cmd_pat..[[creds*: Zeigt alle Logindaten und API-Keys
|
||||
*]]..config.cmd_pat..[[creds* _add_ _<Variable>_ _<Schlüssel>_: Speichert Schlüssel mit dieser Variable ein
|
||||
*]]..config.cmd_pat..[[creds* _del_ _<Variable>_: Löscht Schlüssel mit dieser Variable
|
||||
*]]..config.cmd_pat..[[creds* _rename_ _<Variable>_ _<Neue Variable>_: Benennt Variable um, behält Schlüssel bei
|
||||
]]
|
||||
end
|
||||
|
||||
creds_manager.command = 'creds'
|
||||
|
||||
local hash = "telegram:credentials"
|
||||
|
||||
-- See: http://www.lua.org/pil/19.3.html
|
||||
function pairsByKeys (t, f)
|
||||
local a = {}
|
||||
for n in pairs(t) do table.insert(a, n) end
|
||||
table.sort(a, f)
|
||||
local i = 0 -- iterator variable
|
||||
local iter = function () -- iterator function
|
||||
i = i + 1
|
||||
if a[i] == nil then
|
||||
return nil
|
||||
else
|
||||
return a[i], t[a[i]]
|
||||
end
|
||||
end
|
||||
return iter
|
||||
end
|
||||
|
||||
function creds_manager:reload_creds()
|
||||
cred_data = redis:hgetall(hash)
|
||||
end
|
||||
|
||||
function creds_manager:list_creds()
|
||||
creds_manager:reload_creds()
|
||||
if redis:exists("telegram:credentials") == true then
|
||||
local text = ""
|
||||
for var, key in pairsByKeys(cred_data) do
|
||||
text = text..var..' = '..key..'\n'
|
||||
end
|
||||
return text
|
||||
else
|
||||
create_cred()
|
||||
return "Es wurden noch keine Logininformationen gespeichert, lege Tabelle an...\nSpeichere Keys mit /creds add [Variable] [Key] ein!"
|
||||
end
|
||||
end
|
||||
|
||||
function creds_manager:add_creds(var, key)
|
||||
print('Saving credential for '..var..' to redis hash '..hash)
|
||||
redis:hset(hash, var, key)
|
||||
creds_manager:reload_creds()
|
||||
return 'Gespeichert!'
|
||||
end
|
||||
|
||||
function creds_manager:del_creds(var)
|
||||
if redis:hexists(hash, var) == true then
|
||||
print('Deleting credential for '..var..' from redis hash '..hash)
|
||||
redis:hdel(hash, var)
|
||||
creds_manager:reload_creds()
|
||||
return 'Key von "'..var..'" erfolgreich gelöscht!'
|
||||
else
|
||||
return 'Du hast keine Logininformationen für diese Variable eingespeichert.'
|
||||
end
|
||||
end
|
||||
|
||||
function creds_manager:rename_creds(var, newvar)
|
||||
if redis:hexists(hash, var) == true then
|
||||
local key = redis:hget(hash, var)
|
||||
if redis:hsetnx(hash, newvar, key) == true then
|
||||
redis:hdel(hash, var)
|
||||
creds_manager:reload_creds()
|
||||
return '"'..var..'" erfolgreich zu "'..newvar..'" umbenannt.'
|
||||
else
|
||||
return "Variable konnte nicht umbenannt werden: Zielvariable existiert bereits."
|
||||
end
|
||||
else
|
||||
return 'Die zu umbennende Variable existiert nicht.'
|
||||
end
|
||||
end
|
||||
|
||||
function creds_manager:action(msg, config, matches)
|
||||
local receiver = msg.from.id
|
||||
if receiver ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
|
||||
if msg.chat.type ~= 'private' then
|
||||
utilities.send_reply(self, msg, 'Dieses Plugin solltest du nur [privat](http://telegram.me/' .. self.info.username .. '?start=creds) verwenden!', true)
|
||||
return
|
||||
end
|
||||
|
||||
if matches[1] == "/creds" then
|
||||
utilities.send_reply(self, msg, creds_manager:list_creds())
|
||||
return
|
||||
elseif matches[1] == "/creds add" then
|
||||
local var = string.lower(string.sub(matches[2], 1, 50))
|
||||
local key = string.sub(matches[3], 1, 1000)
|
||||
utilities.send_reply(self, msg, creds_manager:add_creds(var, key))
|
||||
return
|
||||
elseif matches[1] == "/creds del" then
|
||||
local var = string.lower(matches[2])
|
||||
utilities.send_reply(self, msg, creds_manager:del_creds(var))
|
||||
return
|
||||
elseif matches[1] == "/creds rename" then
|
||||
local var = string.lower(string.sub(matches[2], 1, 50))
|
||||
local newvar = string.lower(string.sub(matches[3], 1, 1000))
|
||||
utilities.send_reply(self, msg, creds_manager:rename_creds(var, newvar))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return creds_manager
|
64
miku/plugins/currency.lua
Normal file
64
miku/plugins/currency.lua
Normal file
@ -0,0 +1,64 @@
|
||||
local currency = {}
|
||||
|
||||
local HTTPS = require('ssl.https')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
currency.command = 'cash [Menge] <von> <zu>'
|
||||
|
||||
function currency:init(config)
|
||||
currency.triggers = {
|
||||
"^/cash ([A-Za-z]+)$",
|
||||
"^/cash ([A-Za-z]+) ([A-Za-z]+)$",
|
||||
"^/cash (%d+[%d%.,]*) ([A-Za-z]+) ([A-Za-z]+)$",
|
||||
"^(/eur)$"
|
||||
}
|
||||
currency.doc = [[*
|
||||
]]..config.cmd_pat..[[cash* _[Menge]_ _<von>_ _<zu>_
|
||||
Beispiel: _]]..config.cmd_pat..[[cash 5 USD EUR_]]
|
||||
end
|
||||
|
||||
function currency:action(msg, config)
|
||||
if not matches[2] then
|
||||
from = string.upper(matches[1])
|
||||
to = 'EUR'
|
||||
amount = 1
|
||||
elseif matches[3] then
|
||||
from = string.upper(matches[2])
|
||||
to = string.upper(matches[3])
|
||||
amount = matches[1]
|
||||
else
|
||||
from = string.upper(matches[1])
|
||||
to = string.upper(matches[2])
|
||||
amount = 1
|
||||
end
|
||||
|
||||
local amount = string.gsub(amount, ",", ".")
|
||||
amount = tonumber(amount)
|
||||
local result = 1
|
||||
local BASE_URL = 'https://www.google.com/finance/converter'
|
||||
if from == to then
|
||||
utilities.send_reply(self, msg, 'Jaja, sehr witzig...')
|
||||
return
|
||||
end
|
||||
|
||||
local url = BASE_URL..'?from='..from..'&to='..to..'&a='..amount
|
||||
local str, res = HTTPS.request(url)
|
||||
if res ~= 200 then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
return
|
||||
end
|
||||
|
||||
local str = str:match('<span class=bld>(.*) %u+</span>')
|
||||
if not str then
|
||||
utilities.send_reply(self, msg, 'Keine gültige Währung - sieh dir die Währungsliste bei [Google Finanzen](https://www.google.com/finance/converter) an.', true)
|
||||
return
|
||||
end
|
||||
local result = string.format('%.2f', str)
|
||||
local result = string.gsub(result, "%.", ",")
|
||||
|
||||
local amount = tostring(string.gsub(amount, "%.", ","))
|
||||
local output = amount..' '..from..' = *'..result..' '..to..'*'
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
end
|
||||
|
||||
return currency
|
31
miku/plugins/dailymotion.lua
Normal file
31
miku/plugins/dailymotion.lua
Normal file
@ -0,0 +1,31 @@
|
||||
local dailymotion = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
dailymotion.triggers = {
|
||||
"dailymotion.com/video/([A-Za-z0-9-_-]+)"
|
||||
}
|
||||
|
||||
local BASE_URL = 'https://api.dailymotion.com'
|
||||
|
||||
function dailymotion:send_dailymotion_info (dm_code)
|
||||
local url = BASE_URL..'/video/'..dm_code
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)
|
||||
|
||||
local title = data.title
|
||||
local channel = data.channel
|
||||
local text = '*'..title..'*\nHochgeladen in die Kategorie *'..channel..'*'
|
||||
return text
|
||||
end
|
||||
|
||||
function dailymotion:action(msg, config, matches)
|
||||
local text = dailymotion:send_dailymotion_info(matches[1])
|
||||
if not text then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
|
||||
return dailymotion
|
52
miku/plugins/deviantart.lua
Normal file
52
miku/plugins/deviantart.lua
Normal file
@ -0,0 +1,52 @@
|
||||
local deviantart = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
deviantart.triggers = {
|
||||
"http://(.*).deviantart.com/art/(.*)"
|
||||
}
|
||||
|
||||
local BASE_URL = 'https://backend.deviantart.com'
|
||||
|
||||
function deviantart:get_da_data (da_code)
|
||||
local url = BASE_URL..'/oembed?url='..da_code
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)
|
||||
return data
|
||||
end
|
||||
|
||||
function deviantart:send_da_data (data)
|
||||
local title = data.title
|
||||
local category = data.category
|
||||
local author_name = data.author_name
|
||||
local text = title..' von '..author_name..'\n'..category
|
||||
|
||||
if data.rating == "adult" then
|
||||
return title..' von '..author_name..'\n'..category..'\n(NSFW)'
|
||||
else
|
||||
local image_url = data.fullsize_url
|
||||
if image_url == nil then
|
||||
image_url = data.url
|
||||
end
|
||||
local file = download_to_file(image_url)
|
||||
return text, file
|
||||
end
|
||||
end
|
||||
|
||||
function deviantart:action(msg, config, matches)
|
||||
local data = deviantart:get_da_data('http://'..matches[1]..'.deviantart.com/art/'..matches[2])
|
||||
if not data then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
|
||||
local text, file = deviantart:send_da_data(data)
|
||||
if file then
|
||||
utilities.send_photo(self, msg.chat.id, file, text, msg.message_id)
|
||||
else
|
||||
utilities.send_reply(self, msg, text)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return deviantart
|
38
miku/plugins/dhl.lua
Normal file
38
miku/plugins/dhl.lua
Normal file
@ -0,0 +1,38 @@
|
||||
local dhl = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function dhl:init(config)
|
||||
dhl.triggers = {
|
||||
"/dhl (%d+)$"
|
||||
}
|
||||
dhl.doc = [[*
|
||||
]]..config.cmd_pat..[[dhl* _<Sendungsnummer>_: Aktueller Status der Sendung]]
|
||||
end
|
||||
|
||||
|
||||
local BASE_URL = 'https://mobil.dhl.de'
|
||||
|
||||
function dhl:sendungsstatus(id)
|
||||
local url = BASE_URL..'/shipmentdetails.html?shipmentId='..id
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return "Fehler beim Abrufen von mobil.dhl.de" end
|
||||
local status = string.match(res, "<div id%=\"detailShortStatus\">(.-)</div>")
|
||||
local status = all_trim(status)
|
||||
local zeit = string.match(res, "<div id%=\"detailStatusDateTime\">(.-)</div>")
|
||||
local zeit = all_trim(zeit)
|
||||
if not zeit or zeit == '<br />' then
|
||||
return status
|
||||
end
|
||||
return '*'..status..'*\n_Stand: '..zeit..'_'
|
||||
end
|
||||
|
||||
function dhl:action(msg, config, matches)
|
||||
local sendungs_id = matches[1]
|
||||
if string.len(sendungs_id) < 8 then return end
|
||||
utilities.send_reply(self, msg, dhl:sendungsstatus(sendungs_id), true)
|
||||
end
|
||||
|
||||
return dhl
|
39
miku/plugins/dropbox.lua
Normal file
39
miku/plugins/dropbox.lua
Normal file
@ -0,0 +1,39 @@
|
||||
-- Doesn't use the API for now, maybe we can integrate some cool features?
|
||||
|
||||
local dropbox = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
dropbox.triggers = {
|
||||
"dropbox.com/s/([a-z0-9]+)/(.*)"
|
||||
}
|
||||
|
||||
function dropbox:action(msg, config, matches)
|
||||
local folder = matches[1]
|
||||
local file = string.gsub(matches[2], "?dl=0", "")
|
||||
local link = 'https://dl.dropboxusercontent.com/s/'..folder..'/'..file
|
||||
|
||||
local v,code = https.request(link)
|
||||
if code == 200 then
|
||||
if string.ends(link, ".png") or string.ends(link, ".jpe?g")then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(link)
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
return
|
||||
elseif string.ends(link, ".webp") or string.ends(link, ".gif") then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(link)
|
||||
utilities.send_document(self, msg.chat.id, file, nil, msg.message_id)
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, link)
|
||||
end
|
||||
return
|
||||
else
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return dropbox
|
42
miku/plugins/echo.lua
Normal file
42
miku/plugins/echo.lua
Normal file
@ -0,0 +1,42 @@
|
||||
local echo = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
echo.command = 'echo <Text>'
|
||||
|
||||
function echo:init(config)
|
||||
echo.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('echo', true).table
|
||||
echo.inline_triggers = {
|
||||
"^e (.*)"
|
||||
}
|
||||
echo.doc = [[*
|
||||
]]..config.cmd_pat..[[echo* _<Text>_: Gibt den Text aus]]
|
||||
end
|
||||
|
||||
function echo:inline_callback(inline_query, config, matches)
|
||||
local text = matches[1]
|
||||
local results = '['
|
||||
|
||||
-- enable custom markdown button
|
||||
if text:match('%[.*%]%(.*%)') or text:match('%*.*%*') or text:match('_.*_') or text:match('`.*`') then
|
||||
results = results..'{"type":"article","id":"'..math.random(100000000000000000)..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/echo/custom.jpg","title":"Eigenes Markdown","description":"'..text..'","input_message_content":{"message_text":"'..text..'","parse_mode":"Markdown"}},'
|
||||
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":"*'..text..'*","parse_mode":"Markdown"}},{"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":"_'..text..'_","parse_mode":"Markdown"}},{"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":"`'..text..'`","parse_mode":"Markdown"}}]'
|
||||
utilities.answer_inline_query(self, inline_query, results, 0)
|
||||
end
|
||||
|
||||
function echo:action(msg)
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
utilities.send_message(self, msg.chat.id, echo.doc, true, msg.message_id, true)
|
||||
else
|
||||
local output
|
||||
if msg.chat.type == 'supergroup' then
|
||||
output = '*Echo:*\n"' .. utilities.md_escape(input) .. '"'
|
||||
end
|
||||
utilities.send_message(self, msg.chat.id, input, true, nil, true)
|
||||
end
|
||||
end
|
||||
|
||||
return echo
|
57
miku/plugins/entergroup.lua
Normal file
57
miku/plugins/entergroup.lua
Normal file
@ -0,0 +1,57 @@
|
||||
local entergroup = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
entergroup.triggers = {
|
||||
'/nil'
|
||||
}
|
||||
|
||||
function entergroup:chat_new_user(msg, self)
|
||||
local user_name = msg.new_chat_member.first_name
|
||||
local chat_title = msg.chat.title
|
||||
if msg.from.username then
|
||||
at_name = ' (@'..msg.from.username..')'
|
||||
else
|
||||
at_name = ''
|
||||
end
|
||||
if msg.from.id == msg.new_chat_member.id then -- entered through link
|
||||
added_by = ''
|
||||
else
|
||||
added_by = '\n'..msg.from.name..at_name..' hat dich hinzugefügt!'
|
||||
end
|
||||
if msg.new_chat_member.id == self.info.id then -- don't say hello to ourselves
|
||||
return
|
||||
end
|
||||
local text = 'Hallo '..user_name..', willkommen bei *'..chat_title..'*!'..added_by
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
|
||||
function entergroup:chat_del_user(msg, self)
|
||||
if msg.left_chat_member.id == msg.from.id then -- silent ignore, if user wasn't kicked
|
||||
return
|
||||
end
|
||||
local user_name = msg.left_chat_member.first_name
|
||||
if msg.from.username then
|
||||
at_name = ' (@'..msg.from.username..')'
|
||||
else
|
||||
at_name = ''
|
||||
end
|
||||
local text = user_name..' wurde von '..msg.from.first_name..at_name..' aus der Gruppe gekickt.'
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
|
||||
function entergroup:pre_process(msg, self)
|
||||
if msg.new_chat_member then
|
||||
entergroup:chat_new_user(msg, self)
|
||||
elseif msg.left_chat_member then
|
||||
entergroup:chat_del_user(msg, self)
|
||||
end
|
||||
|
||||
return msg
|
||||
end
|
||||
|
||||
function entergroup:action(msg)
|
||||
end
|
||||
|
||||
return entergroup
|
37
miku/plugins/expand.lua
Normal file
37
miku/plugins/expand.lua
Normal file
@ -0,0 +1,37 @@
|
||||
local expand = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function expand:init(config)
|
||||
expand.triggers = {
|
||||
"^/expand (https?://[%w-_%.%?%.:/%+=&]+)$"
|
||||
}
|
||||
|
||||
expand.doc = [[*
|
||||
]]..config.cmd_pat..[[expand* _<Kurz-URL>_: Verlängert Kurz-URL (301er/302er)]]
|
||||
end
|
||||
|
||||
expand.command = 'expand <Kurz-URL>'
|
||||
|
||||
function expand:action(msg, config, matches)
|
||||
local response_body = {}
|
||||
local request_constructor = {
|
||||
url = matches[1],
|
||||
method = "HEAD",
|
||||
sink = ltn12.sink.table(response_body),
|
||||
headers = {},
|
||||
redirect = false
|
||||
}
|
||||
|
||||
local ok, response_code, response_headers, response_status_line = http.request(request_constructor)
|
||||
if ok and response_headers.location then
|
||||
utilities.send_reply(self, msg, response_headers.location)
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, "Fehler beim Erweitern der URL.")
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return expand
|
182
miku/plugins/facebook.lua
Normal file
182
miku/plugins/facebook.lua
Normal file
@ -0,0 +1,182 @@
|
||||
local facebook = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local https = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
function facebook:init(config)
|
||||
if not cred_data.fb_access_token then
|
||||
print('Missing config value: fb_access_token.')
|
||||
print('facebook.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
facebook.triggers = {
|
||||
"facebook.com/([A-Za-z0-9-._-]+)/(posts)/(%d+)",
|
||||
"facebook.com/(permalink).php%?(story_fbid)=(%d+)&id=(%d+)",
|
||||
"facebook.com/(photo).php%?fbid=(%d+)",
|
||||
"facebook.com/([A-Za-z0-9-._-]+)/(photos)/a.(%d+[%d%.]*)/(%d+)",
|
||||
"facebook.com/(video).php%?v=(%d+)",
|
||||
"facebook.com/([A-Za-z0-9-._-]+)/(videos)/(%d+[%d%.]*)",
|
||||
"facebook.com/([A-Za-z0-9-._-]+)"
|
||||
}
|
||||
end
|
||||
|
||||
local BASE_URL = 'https://graph.facebook.com/v2.5'
|
||||
local fb_access_token = cred_data.fb_access_token
|
||||
|
||||
local makeOurDate = function(dateString)
|
||||
local pattern = "(%d+)%/(%d+)%/(%d+)"
|
||||
local month, day, year = dateString:match(pattern)
|
||||
return day..'.'..month..'.'..year
|
||||
end
|
||||
|
||||
function facebook:get_fb_id(name)
|
||||
local url = BASE_URL..'/'..name..'?access_token='..fb_access_token..'&locale=de_DE'
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)
|
||||
return data.id
|
||||
end
|
||||
|
||||
function facebook:fb_post (id, story_id)
|
||||
local url = BASE_URL..'/'..id..'_'..story_id..'?access_token='..fb_access_token..'&locale=de_DE&fields=from,name,story,message,link'
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)
|
||||
|
||||
local from = data.from.name
|
||||
local message = data.message
|
||||
local name = data.name
|
||||
if data.link then
|
||||
link = '\n'..data.name..':\n'..utilities.md_escape(data.link)
|
||||
else
|
||||
link = ""
|
||||
end
|
||||
|
||||
if data.story then
|
||||
story = ' ('..data.story..')'
|
||||
else
|
||||
story = ""
|
||||
end
|
||||
|
||||
local text = '*'..from..'*'..story..':\n'..message..'\n'..link
|
||||
return text
|
||||
end
|
||||
|
||||
function facebook:send_facebook_photo(photo_id, receiver)
|
||||
local url = BASE_URL..'/'..photo_id..'?access_token='..fb_access_token..'&locale=de_DE&fields=images,from,name'
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)
|
||||
|
||||
local from = '*'..data.from.name..'*'
|
||||
if data.name then
|
||||
text = from..' hat ein Bild gepostet:\n'..utilities.md_escape(data.name)
|
||||
else
|
||||
text = from..' hat ein Bild gepostet:'
|
||||
end
|
||||
local image_url = data.images[1].source
|
||||
return text, image_url
|
||||
end
|
||||
|
||||
function facebook:send_facebook_video(video_id)
|
||||
local url = BASE_URL..'/'..video_id..'?access_token='..fb_access_token..'&locale=de_DE&fields=description,from,source,title'
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)
|
||||
|
||||
local from = '*'..data.from.name..'*'
|
||||
local description = data.description
|
||||
local source = data.source
|
||||
return from..' hat ein Video gepostet:\n'..description, source, data.title
|
||||
end
|
||||
|
||||
function facebook:facebook_info(name)
|
||||
local url = BASE_URL..'/'..name..'?access_token='..fb_access_token..'&locale=de_DE&fields=about,name,birthday,category,founded,general_info,is_verified'
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)
|
||||
|
||||
local name = data.name
|
||||
if data.is_verified then
|
||||
name = name..' ✅'
|
||||
end
|
||||
|
||||
local category = data.category
|
||||
|
||||
if data.about then
|
||||
about = '\n'..data.about
|
||||
else
|
||||
about = ""
|
||||
end
|
||||
|
||||
if data.general_info then
|
||||
general_info = '\n'..data.general_info
|
||||
else
|
||||
general_info = ""
|
||||
end
|
||||
|
||||
if data.birthday and data.founded then
|
||||
birth = '\nGeburtstag: '..makeOurDate(data.birthday)
|
||||
elseif data.birthday and not data.founded then
|
||||
birth = '\nGeburtstag: '..makeOurDate(data.birthday)
|
||||
elseif data.founded and not data.birthday then
|
||||
birth = '\nGegründet: '..data.founded
|
||||
else
|
||||
birth = ""
|
||||
end
|
||||
|
||||
local text = '*'..name..'* ('..category..')_'..about..'_'..general_info..birth
|
||||
return text
|
||||
end
|
||||
|
||||
function facebook:action(msg, config, matches)
|
||||
if matches[1] == 'permalink' or matches[2] == 'posts' then
|
||||
story_id = matches[3]
|
||||
if not matches[4] then
|
||||
id = facebook:get_fb_id(matches[1])
|
||||
else
|
||||
id = matches[4]
|
||||
end
|
||||
utilities.send_reply(self, msg, facebook:fb_post(id, story_id), true)
|
||||
return
|
||||
elseif matches[1] == 'photo' or matches[2] == 'photos' then
|
||||
if not matches[4] then
|
||||
photo_id = matches[2]
|
||||
else
|
||||
photo_id = matches[4]
|
||||
end
|
||||
local text, image_url = facebook:send_facebook_photo(photo_id, receiver)
|
||||
if not image_url then return end
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(image_url, 'photo.jpg')
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
return
|
||||
elseif matches[1] == 'video' or matches[2] == 'videos' then
|
||||
if not matches[3] then
|
||||
video_id = matches[2]
|
||||
else
|
||||
video_id = matches[3]
|
||||
end
|
||||
local output, video_url, title = facebook:send_facebook_video(video_id)
|
||||
if not title then
|
||||
title = 'Video aufrufen'
|
||||
else
|
||||
title = 'VIDEO: '..title
|
||||
end
|
||||
if not video_url then return end
|
||||
utilities.send_reply(self, msg, output, true, '{"inline_keyboard":[[{"text":"'..utilities.md_escape(title)..'","url":"'..video_url..'"}]]}')
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, facebook:facebook_info(matches[1]), true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return facebook
|
36
miku/plugins/fefe.lua
Normal file
36
miku/plugins/fefe.lua
Normal file
@ -0,0 +1,36 @@
|
||||
local fefe = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
fefe.triggers = {
|
||||
"blog.fefe.de/%?ts=%w%w%w%w%w%w%w%w"
|
||||
}
|
||||
|
||||
function fefe:post(id)
|
||||
local url = 'http://'..id
|
||||
local results, code = https.request(url)
|
||||
if code ~= 200 then return "HTTP-Fehler" end
|
||||
if string.match(results, "No entries found.") then return "Eintrag nicht gefunden." end
|
||||
|
||||
local line = string.sub( results, string.find(results, "<li><a href[^\n]+"))
|
||||
local text = line:gsub("<div style=.+", "")
|
||||
-- remove link at begin
|
||||
local text = text:gsub("<li><a href=\"%?ts=%w%w%w%w%w%w%w%w\">%[l]</a>", "")
|
||||
-- replace "<p>" with newline; "<b>" and "</b>" with "*"
|
||||
local text = text:gsub("<p>", "\n\n"):gsub("<p u>", "\n\n")
|
||||
local text = text:gsub("<b>", "*"):gsub("</b>", "*")
|
||||
local text = text:gsub("<i>", "_"):gsub("</i>", "_")
|
||||
-- format quotes and links markdown-like
|
||||
local text = text:gsub("<a href=\"", "("):gsub("\">", ")["):gsub("</a>", "]")
|
||||
local text = text:gsub("<blockquote>", "\n\n> "):gsub("</blockquote>", "\n\n")
|
||||
|
||||
return text
|
||||
end
|
||||
|
||||
function fefe:action(msg, config, matches)
|
||||
utilities.send_reply(self, msg, fefe:post(matches[1]))
|
||||
end
|
||||
|
||||
return fefe
|
76
miku/plugins/flickr.lua
Normal file
76
miku/plugins/flickr.lua
Normal file
@ -0,0 +1,76 @@
|
||||
local flickr = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
function flickr:init(config)
|
||||
if not cred_data.flickr_apikey then
|
||||
print('Missing config value: flickr_apikey.')
|
||||
print('flickr.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
flickr.triggers = {
|
||||
"flickr.com/photos/([A-Za-z0-9-_-]+)/([0-9]+)"
|
||||
}
|
||||
end
|
||||
|
||||
local BASE_URL = 'https://api.flickr.com/services/rest'
|
||||
|
||||
local makeOurDate = function(dateString)
|
||||
local pattern = "(%d+)%-(%d+)%-(%d+) (%d+)%:(%d+)%:(%d+)"
|
||||
local year, month, day, hours, minutes, seconds = dateString:match(pattern)
|
||||
return day..'.'..month..'.'..year..' um '..hours..':'..minutes..':'..seconds..' Uhr'
|
||||
end
|
||||
|
||||
function flickr:get_flickr_photo_data (photo_id)
|
||||
local apikey = cred_data.flickr_apikey
|
||||
local url = BASE_URL..'/?method=flickr.photos.getInfo&api_key='..apikey..'&photo_id='..photo_id..'&format=json&nojsoncallback=1'
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return "HTTP-FEHLER" end
|
||||
local data = json.decode(res).photo
|
||||
return data
|
||||
end
|
||||
|
||||
function flickr:send_flickr_photo_data(data)
|
||||
local title = data.title._content
|
||||
local username = data.owner.username
|
||||
local taken = data.dates.taken
|
||||
local views = data.views
|
||||
if data.usage.candownload == 1 then
|
||||
local text = '"'..title..'", aufgenommen am '..makeOurDate(taken)..' von '..username..' ('..comma_value(data.views)..' Aufrufe)'
|
||||
local image_url = 'https://farm'..data.farm..'.staticflickr.com/'..data.server..'/'..data.id..'_'..data.originalsecret..'_o_d.'..data.originalformat
|
||||
if data.originalformat == 'gif' then
|
||||
return text, image_url, true
|
||||
else
|
||||
return text, image_url
|
||||
end
|
||||
else
|
||||
return '"'..title..'", aufgenommen '..taken..' von '..username..' ('..data.views..' Aufrufe)\nBild konnte nicht gedownloadet werden (Keine Berechtigung)'
|
||||
end
|
||||
end
|
||||
|
||||
function flickr:action(msg, config, matches)
|
||||
local data = flickr:get_flickr_photo_data(matches[2])
|
||||
if not data then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
local text, image_url, isgif = flickr:send_flickr_photo_data(data)
|
||||
|
||||
if image_url then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(image_url)
|
||||
if isgif then
|
||||
utilities.send_document(self, msg.chat.id, file, text, msg.message_id)
|
||||
return
|
||||
else
|
||||
utilities.send_photo(self, msg.chat.id, file, text, msg.message_id)
|
||||
return
|
||||
end
|
||||
else
|
||||
utilities.send_reply(self, msg, text)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return flickr
|
53
miku/plugins/flickr_search.lua
Normal file
53
miku/plugins/flickr_search.lua
Normal file
@ -0,0 +1,53 @@
|
||||
local flickr_search = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
function flickr_search:init(config)
|
||||
if not cred_data.flickr_apikey then
|
||||
print('Missing config value: flickr_apikey.')
|
||||
print('flickr_search.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
flickr_search.triggers = {
|
||||
"^/flickr (.*)$"
|
||||
}
|
||||
end
|
||||
|
||||
flickr_search.command = 'flickr <Suchbegriff>'
|
||||
|
||||
local apikey = cred_data.flickr_apikey
|
||||
local BASE_URL = 'https://api.flickr.com/services/rest'
|
||||
|
||||
function flickr_search:get_flickr (term)
|
||||
local url = BASE_URL..'/?method=flickr.photos.search&api_key='..apikey..'&format=json&nojsoncallback=1&privacy_filter=1&safe_search=3&extras=url_o&text='..term
|
||||
local b,c = https.request(url)
|
||||
if c ~= 200 then return nil end
|
||||
local photo = json.decode(b).photos.photo
|
||||
-- truly randomize
|
||||
math.randomseed(os.time())
|
||||
-- random max json table size
|
||||
local i = math.random(#photo)
|
||||
local link_image = photo[i].url_o
|
||||
return link_image
|
||||
end
|
||||
|
||||
function flickr_search:action(msg, config, matches)
|
||||
local url = flickr_search:get_flickr(matches[1])
|
||||
if not url then utilities.send_reply(self, msg, config.errors.results) return end
|
||||
|
||||
local file = download_to_file(url)
|
||||
|
||||
if string.ends(url, ".gif") then
|
||||
utilities.send_document(self, msg.chat.id, file, url)
|
||||
return
|
||||
else
|
||||
utilities.send_photo(self, msg.chat.id, file, url)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return flickr_search
|
222
miku/plugins/forecast.lua
Normal file
222
miku/plugins/forecast.lua
Normal file
@ -0,0 +1,222 @@
|
||||
local forecast = {}
|
||||
|
||||
local HTTPS = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local JSON = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
function forecast:init(config)
|
||||
if not cred_data.forecastio_apikey then
|
||||
print('Missing config value: forecastio_apikey.')
|
||||
print('weather.lua will not be enabled.')
|
||||
return
|
||||
elseif not cred_data.google_apikey then
|
||||
print('Missing config value: google_apikey.')
|
||||
print('weather.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
forecast.triggers = {
|
||||
"^(/f)$",
|
||||
"^(/f) (.*)$",
|
||||
"^(/fh)$",
|
||||
"^(/fh) (.*)$",
|
||||
"^(/forecast)$",
|
||||
"^(/forecast) (.*)$",
|
||||
"^(/forecasth)$",
|
||||
"^(/forecasth) (.*)$"
|
||||
}
|
||||
forecast.doc = [[*
|
||||
]]..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..[[fh*: 24-Stunden-Wettervorhersage für deine Stadt _(/location set [Ort]_
|
||||
*]]..config.cmd_pat..[[fh* _<Ort>_: 24-Stunden-Wettervorhersage für diesen Ort
|
||||
]]
|
||||
end
|
||||
|
||||
forecast.command = 'f [Ort]'
|
||||
|
||||
local BASE_URL = "https://api.forecast.io/forecast"
|
||||
local apikey = cred_data.forecastio_apikey
|
||||
local google_apikey = cred_data.google_apikey
|
||||
|
||||
function get_city_name(lat, lng)
|
||||
local city = redis:hget('telegram:cache:weather:pretty_names', lat..','..lng)
|
||||
if city then return city end
|
||||
local url = 'https://maps.googleapis.com/maps/api/geocode/json?latlng='..lat..','..lng..'&result_type=political&language=de&key='..google_apikey
|
||||
local res, code = HTTPS.request(url)
|
||||
if code ~= 200 then return 'Unbekannte Stadt' end
|
||||
local data = JSON.decode(res).results[1]
|
||||
local city = data.formatted_address
|
||||
print('Setting '..lat..','..lng..' in redis hash telegram:cache:weather:pretty_names to "'..city..'"')
|
||||
redis:hset('telegram:cache:weather:pretty_names', lat..','..lng, city)
|
||||
return city
|
||||
end
|
||||
|
||||
function get_condition_symbol(weather, n)
|
||||
if weather.data[n].icon == 'clear-day' then
|
||||
return '☀️'
|
||||
elseif weather.data[n].icon == 'clear-night' then
|
||||
return '🌙'
|
||||
elseif weather.data[n].icon == 'rain' then
|
||||
return '☔️'
|
||||
elseif weather.data[n].icon == 'snow' then
|
||||
return '❄️'
|
||||
elseif weather.data[n].icon == 'sleet' then
|
||||
return '🌨'
|
||||
elseif weather.data[n].icon == 'wind' then
|
||||
return '💨'
|
||||
elseif weather.data[n].icon == 'fog' then
|
||||
return '🌫'
|
||||
elseif weather.data[n].icon == 'cloudy' then
|
||||
return '☁️☁️'
|
||||
elseif weather.data[n].icon == 'partly-cloudy-day' then
|
||||
return '🌤'
|
||||
elseif weather.data[n].icon == 'partly-cloudy-night' then
|
||||
return '🌙☁️'
|
||||
else
|
||||
return ''
|
||||
end
|
||||
end
|
||||
|
||||
function get_temp(weather, n, hourly)
|
||||
if hourly then
|
||||
local temperature = string.gsub(round(weather.data[n].temperature, 1), "%.", ",")
|
||||
local condition = weather.data[n].summary
|
||||
return temperature..'°C | '..get_condition_symbol(weather, n)..' '..condition
|
||||
else
|
||||
local day = string.gsub(round(weather.data[n].temperatureMax, 1), "%.", ",")
|
||||
local night = string.gsub(round(weather.data[n].temperatureMin, 1), "%.", ",")
|
||||
local condition = weather.data[n].summary
|
||||
return '☀️ '..day..'°C | 🌙 '..night..'°C | '..get_condition_symbol(weather, n)..' '..condition
|
||||
end
|
||||
end
|
||||
|
||||
function forecast:get_forecast(lat, lng)
|
||||
print('Finde Wetter in '..lat..', '..lng)
|
||||
local text = redis:get('telegram:cache:forecast:'..lat..','..lng)
|
||||
if text then print('...aus dem Cache..') return text end
|
||||
|
||||
local url = BASE_URL..'/'..apikey..'/'..lat..','..lng..'?lang=de&units=si&exclude=currently,minutely,hourly,alerts,flags'
|
||||
|
||||
local response_body = {}
|
||||
local request_constructor = {
|
||||
url = url,
|
||||
method = "GET",
|
||||
sink = ltn12.sink.table(response_body)
|
||||
}
|
||||
local ok, response_code, response_headers, response_status_line = HTTPS.request(request_constructor)
|
||||
if not ok then return nil end
|
||||
local data = JSON.decode(table.concat(response_body))
|
||||
local ttl = string.sub(response_headers["cache-control"], 9)
|
||||
|
||||
|
||||
local weather = data.daily
|
||||
local city = get_city_name(lat, lng)
|
||||
|
||||
local header = '*Vorhersage für '..city..':*\n_'..weather.summary..'_\n'
|
||||
|
||||
local text = '*Heute:* '..get_temp(weather, 1)
|
||||
local text = text..'\n*Morgen:* '..get_temp(weather, 2)
|
||||
|
||||
for day in pairs(weather.data) do
|
||||
if day > 2 then
|
||||
text = text..'\n*'..convert_timestamp(weather.data[day].time, '%a, %d.%m')..'*: '..get_temp(weather, day)
|
||||
end
|
||||
end
|
||||
|
||||
local text = string.gsub(text, "Mon", "Mo")
|
||||
local text = string.gsub(text, "Tue", "Di")
|
||||
local text = string.gsub(text, "Wed", "Mi")
|
||||
local text = string.gsub(text, "Thu", "Do")
|
||||
local text = string.gsub(text, "Fri", "Fr")
|
||||
local text = string.gsub(text, "Sat", "Sa")
|
||||
local text = string.gsub(text, "Sun", "So")
|
||||
|
||||
cache_data('forecast', lat..','..lng, header..text, tonumber(ttl), 'key')
|
||||
|
||||
return header..text
|
||||
end
|
||||
|
||||
function forecast:get_forecast_hourly(lat, lng)
|
||||
print('Finde stündliches Wetter in '..lat..', '..lng)
|
||||
local text = redis:get('telegram:cache:forecast:'..lat..','..lng..':hourly')
|
||||
if text then print('...aus dem Cache..') return text end
|
||||
|
||||
local url = BASE_URL..'/'..apikey..'/'..lat..','..lng..'?lang=de&units=si&exclude=currently,minutely,daily,alerts,flags'
|
||||
|
||||
local response_body = {}
|
||||
local request_constructor = {
|
||||
url = url,
|
||||
method = "GET",
|
||||
sink = ltn12.sink.table(response_body)
|
||||
}
|
||||
local ok, response_code, response_headers, response_status_line = HTTPS.request(request_constructor)
|
||||
if not ok then return nil end
|
||||
local data = JSON.decode(table.concat(response_body))
|
||||
local ttl = string.sub(response_headers["cache-control"], 9)
|
||||
|
||||
|
||||
local weather = data.hourly
|
||||
local city = get_city_name(lat, lng)
|
||||
|
||||
local header = '*24-Stunden-Vorhersage für '..city..':*\n_'..weather.summary..'_'
|
||||
local text = ""
|
||||
|
||||
for hour in pairs(weather.data) do
|
||||
if hour < 26 then
|
||||
text = text..'\n*'..convert_timestamp(weather.data[hour].time, '%H:%M Uhr')..'* | '..get_temp(weather, hour, true)
|
||||
end
|
||||
end
|
||||
|
||||
cache_data('forecast', lat..','..lng..':hourly', header..text, tonumber(ttl), 'key')
|
||||
|
||||
return header..text
|
||||
end
|
||||
|
||||
function forecast:action(msg, config, matches)
|
||||
local user_id = msg.from.id
|
||||
local city = get_location(user_id)
|
||||
|
||||
if matches[2] then
|
||||
city = matches[2]
|
||||
else
|
||||
local set_location = get_location(user_id)
|
||||
if not set_location then
|
||||
city = 'Berlin, Deutschland'
|
||||
else
|
||||
city = set_location
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
utilities.send_reply(self, msg, '*Diesen Ort gibt es nicht!*', true)
|
||||
return
|
||||
end
|
||||
|
||||
redis:hset('telegram:cache:weather:'..string.lower(city), 'lat', lat)
|
||||
redis:hset('telegram:cache:weather:'..string.lower(city), 'lng', lng)
|
||||
|
||||
if matches[1] == '/forecasth' or matches[1] == '/fh' then
|
||||
text = forecast:get_forecast_hourly(lat, lng)
|
||||
else
|
||||
text = forecast:get_forecast(lat, lng)
|
||||
end
|
||||
if not text then
|
||||
text = '*Konnte die Wettervorhersage für diese Stadt nicht bekommen.*'
|
||||
end
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
|
||||
return forecast
|
242
miku/plugins/gImages.lua
Normal file
242
miku/plugins/gImages.lua
Normal file
@ -0,0 +1,242 @@
|
||||
-- You need a Google API key and a Google Custom Search Engine set up to use this, in config.google_api_key and config.google_cse_key, respectively.
|
||||
-- You must also sign up for the CSE in the Google Developer Console, and enable image results.
|
||||
|
||||
local gImages = {}
|
||||
|
||||
local HTTPS = require('ssl.https')
|
||||
HTTPS.timeout = 10
|
||||
local URL = require('socket.url')
|
||||
local JSON = require('dkjson')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
function gImages:init(config)
|
||||
if not cred_data.google_apikey then
|
||||
print('Missing config value: google_apikey.')
|
||||
print('gImages.lua will not be enabled.')
|
||||
return
|
||||
elseif not cred_data.google_cse_id then
|
||||
print('Missing config value: google_cse_id.')
|
||||
print('gImages.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
gImages.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('img', true):t('i', true).table
|
||||
gImages.doc = [[*
|
||||
]]..config.cmd_pat..[[img* _<Suchbegriff>_
|
||||
Sucht Bild mit Google und versendet es (SafeSearch aktiv)
|
||||
Alias: *]]..config.cmd_pat..[[i*]]
|
||||
end
|
||||
|
||||
gImages.command = 'img <Suchbegriff>'
|
||||
|
||||
-- Yes, the callback is copied from below, but I can't think of another method :\
|
||||
function gImages:callback(callback, msg, self, config, input)
|
||||
if not msg then return end
|
||||
utilities.answer_callback_query(self, callback, 'Suche nochmal nach "'..URL.unescape(input)..'"')
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local hash = 'telegram:cache:gImages'
|
||||
local results = redis:smembers(hash..':'..string.lower(URL.unescape(input)))
|
||||
|
||||
if not results[1] then
|
||||
print('doing web request')
|
||||
results = gImages:get_image(input)
|
||||
if results == 403 then
|
||||
utilities.send_reply(self, msg, config.errors.quotaexceeded, true)
|
||||
return
|
||||
elseif not results then
|
||||
utilities.send_reply(self, msg, config.errors.results, true)
|
||||
return
|
||||
end
|
||||
gImages:cache_result(results, input)
|
||||
end
|
||||
|
||||
-- Random image from table
|
||||
local i = math.random(#results)
|
||||
|
||||
-- Thanks to Amedeo for this!
|
||||
local failed = true
|
||||
local nofTries = 0
|
||||
|
||||
while failed and nofTries < #results do
|
||||
if results[i].image then
|
||||
img_url = results[i].link
|
||||
mimetype = results[i].mime
|
||||
context = results[i].image.contextLink
|
||||
else -- from cache
|
||||
img_url = results[i]
|
||||
mimetype = redis:hget(hash..':'..img_url, 'mime')
|
||||
context = redis:hget(hash..':'..img_url, 'contextLink')
|
||||
end
|
||||
|
||||
-- It's important to save the image with the right ending!
|
||||
if mimetype == 'image/gif' then
|
||||
file = download_to_file(img_url, 'img.gif')
|
||||
elseif mimetype == 'image/png' then
|
||||
file = download_to_file(img_url, 'img.png')
|
||||
elseif mimetype == 'image/jpeg' then
|
||||
file = download_to_file(img_url, 'img.jpg')
|
||||
else
|
||||
file = nil
|
||||
end
|
||||
|
||||
if not file then
|
||||
nofTries = nofTries + 1
|
||||
i = i+1
|
||||
if i > #results then
|
||||
i = 1
|
||||
end
|
||||
else
|
||||
failed = false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if failed then
|
||||
utilities.send_reply(self, msg, 'Fehler beim Herunterladen eines Bildes.', true, '{"inline_keyboard":[[{"text":"Nochmal versuchen","callback_data":"@'..self.info.username..' gImages:'..input..'"}]]}')
|
||||
return
|
||||
end
|
||||
|
||||
if mimetype == 'image/gif' then
|
||||
result = utilities.send_document(self, msg.chat.id, file, nil, msg.message_id, '{"inline_keyboard":[[{"text":"Seite aufrufen","url":"'..context..'"},{"text":"Bild aufrufen","url":"'..img_url..'"},{"text":"Nochmal suchen","callback_data":"@'..self.info.username..' gImages:'..input..'"}]]}')
|
||||
else
|
||||
result = utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id, '{"inline_keyboard":[[{"text":"Seite aufrufen","url":"'..context..'"},{"text":"Bild aufrufen","url":"'..img_url..'"},{"text":"Nochmal suchen","callback_data":"@'..self.info.username..' gImages:'..input..'"}]]}')
|
||||
end
|
||||
|
||||
if not result then
|
||||
utilities.send_reply(self, msg, config.errors.connection, true, '{"inline_keyboard":[[{"text":"Nochmal versuchen","callback_data":"@'..self.info.username..' gImages:'..input..'"}]]}')
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function gImages:get_image(input)
|
||||
local apikey = cred_data.google_apikey -- 100 requests is RIDICULOUS, Google!
|
||||
local cseid = cred_data.google_cse_id
|
||||
local BASE_URL = 'https://www.googleapis.com/customsearch/v1'
|
||||
local url = BASE_URL..'/?searchType=image&alt=json&num=10&key='..apikey..'&cx='..cseid..'&safe=high'..'&q=' .. input .. '&fields=items(link,mime,image(contextLink))'
|
||||
local jstr, res = HTTPS.request(url)
|
||||
local jdat = JSON.decode(jstr).items
|
||||
|
||||
if not jdat then
|
||||
return 'NORESULTS'
|
||||
end
|
||||
|
||||
if jdat.error then
|
||||
if jdat.error.code == 403 then
|
||||
return 403
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return jdat
|
||||
end
|
||||
|
||||
function gImages:cache_result(results, text)
|
||||
local cache = {}
|
||||
for v in pairs(results) do
|
||||
table.insert(cache, results[v].link)
|
||||
end
|
||||
for n, link in pairs(cache) do
|
||||
redis:hset('telegram:cache:gImages:'..link, 'mime', results[n].mime)
|
||||
redis:hset('telegram:cache:gImages:'..link, 'contextLink', results[n].image.contextLink)
|
||||
redis:expire('telegram:cache:gImages:'..link, 1209600)
|
||||
end
|
||||
cache_data('gImages', string.lower(text), cache, 1209600, 'set')
|
||||
end
|
||||
|
||||
function gImages:action(msg, config, matches)
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
if msg.reply_to_message and msg.reply_to_message.text then
|
||||
input = msg.reply_to_message.text
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, gImages.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
print ('Checking if search contains blacklisted word: '..input)
|
||||
if is_blacklisted(input) then
|
||||
utilities.send_reply(self, msg, 'Vergiss es! ._.')
|
||||
return
|
||||
end
|
||||
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
|
||||
local hash = 'telegram:cache:gImages'
|
||||
local results = redis:smembers(hash..':'..string.lower(input))
|
||||
|
||||
if not results[1] then
|
||||
print('doing web request')
|
||||
results = gImages:get_image(URL.escape(input))
|
||||
if results == 403 then
|
||||
utilities.send_reply(self, msg, config.errors.quotaexceeded, true)
|
||||
return
|
||||
elseif not results or results == 'NORESULTS' then
|
||||
utilities.send_reply(self, msg, config.errors.results, true)
|
||||
return
|
||||
end
|
||||
gImages:cache_result(results, input)
|
||||
end
|
||||
|
||||
-- Random image from table
|
||||
local i = math.random(#results)
|
||||
|
||||
-- Thanks to Amedeo for this!
|
||||
local failed = true
|
||||
local nofTries = 0
|
||||
|
||||
while failed and nofTries < #results do
|
||||
if results[i].image then
|
||||
img_url = results[i].link
|
||||
mimetype = results[i].mime
|
||||
context = results[i].image.contextLink
|
||||
else -- from cache
|
||||
img_url = results[i]
|
||||
mimetype = redis:hget(hash..':'..img_url, 'mime')
|
||||
context = redis:hget(hash..':'..img_url, 'contextLink')
|
||||
end
|
||||
|
||||
-- It's important to save the image with the right ending!
|
||||
if mimetype == 'image/gif' then
|
||||
file = download_to_file(img_url, 'img.gif')
|
||||
elseif mimetype == 'image/png' then
|
||||
file = download_to_file(img_url, 'img.png')
|
||||
elseif mimetype == 'image/jpeg' then
|
||||
file = download_to_file(img_url, 'img.jpg')
|
||||
else
|
||||
file = nil
|
||||
end
|
||||
|
||||
if not file then
|
||||
nofTries = nofTries + 1
|
||||
i = i+1
|
||||
if i > #results then
|
||||
i = 1
|
||||
end
|
||||
else
|
||||
failed = false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if failed then
|
||||
utilities.send_reply(self, msg, 'Fehler beim Herunterladen eines Bildes.', true, '{"inline_keyboard":[[{"text":"Nochmal versuchen","callback_data":"@'..self.info.username..' gImages:'..URL.escape(input)..'"}]]}')
|
||||
return
|
||||
end
|
||||
|
||||
if mimetype == 'image/gif' then
|
||||
result = utilities.send_document(self, msg.chat.id, file, nil, msg.message_id, '{"inline_keyboard":[[{"text":"Seite aufrufen","url":"'..context..'"},{"text":"Bild aufrufen","url":"'..img_url..'"},{"text":"Nochmal suchen","callback_data":"@'..self.info.username..' gImages:'..URL.escape(input)..'"}]]}')
|
||||
else
|
||||
result = utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id, '{"inline_keyboard":[[{"text":"Seite aufrufen","url":"'..context..'"},{"text":"Bild aufrufen","url":"'..img_url..'"},{"text":"Nochmal suchen","callback_data":"@'..self.info.username..' gImages:'..URL.escape(input)..'"}]]}')
|
||||
end
|
||||
|
||||
if not result then
|
||||
utilities.send_reply(self, msg, config.errors.connection, true, '{"inline_keyboard":[[{"text":"Nochmal versuchen","callback_data":"@'..self.info.username..' gImages:'..URL.escape(input)..'"}]]}')
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return gImages
|
43
miku/plugins/gMaps.lua
Normal file
43
miku/plugins/gMaps.lua
Normal file
@ -0,0 +1,43 @@
|
||||
local gMaps = {}
|
||||
|
||||
local URL = require('socket.url')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
gMaps.command = 'loc <Ort>'
|
||||
|
||||
function gMaps:init(config)
|
||||
gMaps.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('loc', true).table
|
||||
gMaps.doc = [[*
|
||||
]]..config.cmd_pat..[[loc* _<Ort>_: Sendet Ort via Google Maps]]
|
||||
end
|
||||
|
||||
function gMaps:get_staticmap(area, lat, lon)
|
||||
local base_api = "https://maps.googleapis.com/maps/api"
|
||||
local url = base_api .. "/staticmap?size=600x300&zoom=12¢er="..URL.escape(area).."&markers=color:red"..URL.escape("|"..area)
|
||||
|
||||
local file = download_to_file(url)
|
||||
return file
|
||||
end
|
||||
|
||||
function gMaps:action(msg, config)
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
if msg.reply_to_message and msg.reply_to_message.text then
|
||||
input = msg.reply_to_message.text
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, gMaps.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
utilities.send_typing(self, msg.chat.id, 'find_location')
|
||||
local coords = utilities.get_coords(input, config)
|
||||
if type(coords) == 'string' then
|
||||
utilities.send_reply(self, msg, coords)
|
||||
return
|
||||
end
|
||||
|
||||
utilities.send_location(self, msg.chat.id, coords.lat, coords.lon, msg.message_id)
|
||||
utilities.send_photo(self, msg.chat.id, gMaps:get_staticmap(input, coords.lat, coords.lon), nil, msg.message_id)
|
||||
end
|
||||
|
||||
return gMaps
|
84
miku/plugins/gSearch.lua
Normal file
84
miku/plugins/gSearch.lua
Normal file
@ -0,0 +1,84 @@
|
||||
local gSearch = {}
|
||||
|
||||
local HTTPS = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local JSON = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
gSearch.command = 'google <Suchbegriff>'
|
||||
|
||||
function gSearch:init(config)
|
||||
gSearch.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('g', true):t('google', true):t('gnsfw', true).table
|
||||
gSearch.doc = [[*
|
||||
]]..config.cmd_pat..[[google* _<Suchbegriff>_: Sendet Suchergebnisse von Google
|
||||
Alias: _]]..config.cmd_pat..[[g_]]
|
||||
end
|
||||
|
||||
function gSearch:googlethat(query, config)
|
||||
local BASE_URL = 'https://www.googleapis.com/customsearch/v1'
|
||||
local apikey = cred_data.google_apikey
|
||||
local cseid = cred_data.google_cse_id
|
||||
local number = 5 -- Set number of results
|
||||
|
||||
local api = BASE_URL.."/?key="..apikey.."&cx="..cseid.."&gl=de&num="..number.."&safe=medium&fields=searchInformation%28formattedSearchTime,formattedTotalResults%29,items%28title,link,displayLink%29&"
|
||||
local parameters = "q=".. (URL.escape(query) or "")
|
||||
-- Do the request
|
||||
local res, code = HTTPS.request(api..parameters)
|
||||
if code == 403 then
|
||||
return '403'
|
||||
end
|
||||
if code ~= 200 then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
return
|
||||
end
|
||||
local data = JSON.decode(res)
|
||||
if data.searchInformation.formattedTotalResults == "0" then return nil end
|
||||
|
||||
local results={}
|
||||
for key,result in ipairs(data.items) do
|
||||
table.insert(results, {
|
||||
result.title,
|
||||
result.link,
|
||||
result.displayLink
|
||||
})
|
||||
end
|
||||
|
||||
local stats = data.searchInformation.formattedTotalResults..' Ergebnisse, gefunden in '..data.searchInformation.formattedSearchTime..' Sekunden'
|
||||
return results, stats
|
||||
end
|
||||
|
||||
function gSearch:stringlinks(results, stats)
|
||||
local stringresults=""
|
||||
for key,val in ipairs(results) do
|
||||
stringresults=stringresults.."["..val[1].."]("..val[2]..") - `"..val[3].."`\n"
|
||||
end
|
||||
return stringresults..stats
|
||||
end
|
||||
|
||||
function gSearch:action(msg, config)
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
if msg.reply_to_message and msg.reply_to_message.text then
|
||||
input = msg.reply_to_message.text
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, gSearch.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local results, stats = gSearch:googlethat(input, onfig)
|
||||
if results == '403' then
|
||||
utilities.send_reply(self, msg, config.errors.quotaexceeded)
|
||||
return
|
||||
end
|
||||
|
||||
if not results then
|
||||
utilities.send_reply(self, msg, config.errors.results)
|
||||
return
|
||||
end
|
||||
|
||||
utilities.send_message(self, msg.chat.id, gSearch:stringlinks(results, stats), true, nil, true, '{"inline_keyboard":[[{"text":"Alle Ergebnisse anzeigen","url":"https://www.google.com/search?q='..URL.escape(input)..'"}]]}')
|
||||
|
||||
end
|
||||
|
||||
return gSearch
|
147
miku/plugins/games.lua
Normal file
147
miku/plugins/games.lua
Normal file
@ -0,0 +1,147 @@
|
||||
local games = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local URL = require('socket.url')
|
||||
local xml = require("xml")
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
games.command = 'game <Spiel>'
|
||||
|
||||
function games:init(config)
|
||||
games.triggers = {
|
||||
"^/game (.+)$"
|
||||
}
|
||||
games.doc = [[*
|
||||
]]..config.cmd_pat..[[game*_ <Spiel>_: Sendet Infos zum Spiel]]
|
||||
end
|
||||
|
||||
local BASE_URL = 'http://thegamesdb.net/api'
|
||||
|
||||
local makeOurDate = function(dateString)
|
||||
local pattern = "(%d+)%/(%d+)%/(%d+)"
|
||||
local month, day, year = dateString:match(pattern)
|
||||
return day..'.'..month..'.'..year
|
||||
end
|
||||
|
||||
|
||||
function games:get_game_id(game)
|
||||
local url = BASE_URL..'/GetGamesList.php?name='..game
|
||||
local res,code = http.request(url)
|
||||
if code ~= 200 then return "HTTP-FEHLER" end
|
||||
local result = xml.load(res)
|
||||
if xml.find(result, 'id') then
|
||||
local game = xml.find(result, 'id')[1]
|
||||
return game
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
function games:send_game_photo(result, self, msg)
|
||||
local BASE_URL = xml.find(result, 'baseImgUrl')[1]
|
||||
local images = {}
|
||||
|
||||
if xml.find(result, 'fanart') then
|
||||
local fanart = xml.find(result, 'fanart')[1]
|
||||
local fanrt_url = BASE_URL..fanart[1]
|
||||
table.insert(images, fanrt_url)
|
||||
end
|
||||
|
||||
if xml.find(result, 'boxart', 'side', 'front') then
|
||||
local boxart = xml.find(result, 'boxart', 'side', 'front')[1]
|
||||
local boxart_url = BASE_URL..boxart
|
||||
table.insert(images, boxart_url)
|
||||
end
|
||||
|
||||
local i = 0
|
||||
for k, v in pairs(images) do
|
||||
i = i+1
|
||||
local file = download_to_file(v, 'game'..i..'.jpg')
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
end
|
||||
|
||||
function games:send_game_data(game_id, self, msg)
|
||||
local url = BASE_URL..'/GetGame.php?id='..game_id
|
||||
local res,code = http.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local result = xml.load(res)
|
||||
|
||||
local title = xml.find(result, 'GameTitle')[1]
|
||||
local platform = xml.find(result, 'Platform')[1]
|
||||
|
||||
if xml.find(result, 'ReleaseDate') then
|
||||
date = ', erschienen am '..makeOurDate(xml.find(result, 'ReleaseDate')[1])
|
||||
else
|
||||
date = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'Overview') then
|
||||
desc = '\n_'..string.sub(xml.find(result, 'Overview')[1], 1, 200) .. '..._'
|
||||
else
|
||||
desc = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'Genres') then
|
||||
local genres = xml.find(result, 'Genres')
|
||||
local genre_count = tablelength(genres)-1
|
||||
if genre_count == 1 then
|
||||
genre = '\nGenre: '..genres[1][1]
|
||||
else
|
||||
local genre_loop = '\nGenres: '
|
||||
for v in pairs(genres) do
|
||||
if v == 'xml' then break; end
|
||||
if v < genre_count then
|
||||
genre_loop = genre_loop..genres[v][1]..', '
|
||||
else
|
||||
genre_loop = genre_loop..genres[v][1]
|
||||
end
|
||||
end
|
||||
genre = genre_loop
|
||||
end
|
||||
else
|
||||
genre = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'Players') then
|
||||
players = '\nSpieler: '..xml.find(result, 'Players')[1]
|
||||
else
|
||||
players = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'Youtube') then
|
||||
video = '\n[Video auf YouTube ansehen]('..xml.find(result, 'Youtube')[1]..')'
|
||||
else
|
||||
video = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'Publisher') then
|
||||
publisher = '\nPublisher: '..xml.find(result, 'Publisher')[1]
|
||||
else
|
||||
publisher = ''
|
||||
end
|
||||
|
||||
local text = '*'..title..'* für *'..platform..'*'..date..desc..genre..players..video..publisher
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
|
||||
if xml.find(result, 'fanrt') or xml.find(result, 'boxart') then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
games:send_game_photo(result, self, msg)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
function games:action(msg, config, matches)
|
||||
local game = URL.escape(matches[1])
|
||||
local game_id = games:get_game_id(game)
|
||||
if not game_id then
|
||||
utilities.send_reply(self, msg, 'Spiel nicht gefunden!')
|
||||
return
|
||||
else
|
||||
games:send_game_data(game_id, self, msg)
|
||||
end
|
||||
end
|
||||
|
||||
return games
|
99
miku/plugins/gdrive.lua
Normal file
99
miku/plugins/gdrive.lua
Normal file
@ -0,0 +1,99 @@
|
||||
local gdrive = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local https = require('ssl.https')
|
||||
local ltn12 = require('ltn12')
|
||||
local json = require('dkjson')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
function gdrive:init(config)
|
||||
if not cred_data.google_apikey then
|
||||
print('Missing config value: google_apikey.')
|
||||
print('gdrive.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
gdrive.triggers = {
|
||||
"docs.google.com/(.*)/d/([A-Za-z0-9-_-]+)",
|
||||
"drive.google.com/(.*)/d/([A-Za-z0-9-_-]+)",
|
||||
"drive.google.com/(open)%?id=([A-Za-z0-9-_-]+)"
|
||||
}
|
||||
end
|
||||
|
||||
local apikey = cred_data.google_apikey
|
||||
|
||||
local BASE_URL = 'https://www.googleapis.com/drive/v2'
|
||||
|
||||
function gdrive:get_drive_document_data (docid)
|
||||
local apikey = cred_data.google_apikey
|
||||
local url = BASE_URL..'/files/'..docid..'?key='..apikey..'&fields=id,title,mimeType,ownerNames,exportLinks,fileExtension'
|
||||
local res,code = https.request(url)
|
||||
local res = string.gsub(res, 'image/', '')
|
||||
local res = string.gsub(res, 'application/', '')
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)
|
||||
return data
|
||||
end
|
||||
|
||||
function gdrive:send_drive_document_data(data, self, msg)
|
||||
local title = data.title
|
||||
local mimetype = data.mimeType
|
||||
local id = data.id
|
||||
local owner = data.ownerNames[1]
|
||||
local text = '"'..title..'", freigegeben von '..owner
|
||||
if data.exportLinks then
|
||||
if data.exportLinks.png then
|
||||
local image_url = data.exportLinks.png
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(image_url)
|
||||
utilities.send_photo(self, msg.chat.id, file, text, msg.message_id)
|
||||
return
|
||||
else
|
||||
local pdf_url = data.exportLinks.pdf
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_document')
|
||||
local file = download_to_file(pdf_url)
|
||||
utilities.send_document(self, msg.chat.id, file, text, msg.message_id)
|
||||
return
|
||||
end
|
||||
else
|
||||
local get_file_url = 'https://drive.google.com/uc?id='..id
|
||||
local ext = data.fileExtension
|
||||
if mimetype == "png" or mimetype == "jpg" or mimetype == "jpeg" or mimetype == "gif" or mimetype == "webp" then
|
||||
local respbody = {}
|
||||
local options = {
|
||||
url = get_file_url,
|
||||
sink = ltn12.sink.table(respbody),
|
||||
redirect = false
|
||||
}
|
||||
local response = {https.request(options)} -- luasec doesn't support 302 redirects, so we must contact gdrive again
|
||||
local code = response[2]
|
||||
local headers = response[3]
|
||||
local file_url = headers.location
|
||||
if ext == "jpg" or ext == "jpeg" or ext == "png" then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(file_url)
|
||||
utilities.send_photo(self, msg.chat.id, file, text, msg.message_id)
|
||||
return
|
||||
else
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_document')
|
||||
local file = download_to_file(file_url)
|
||||
utilities.send_document(self, msg.chat.id, file, text, msg.message_id)
|
||||
return
|
||||
end
|
||||
else
|
||||
local text = '*'..title..'*, freigegeben von _'..owner..'_\n[Direktlink]('..get_file_url..')'
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function gdrive:action(msg, config, matches)
|
||||
local docid = matches[2]
|
||||
local data = gdrive:get_drive_document_data(docid)
|
||||
if not data then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
gdrive:send_drive_document_data(data, self, msg)
|
||||
return
|
||||
end
|
||||
|
||||
return gdrive
|
59
miku/plugins/get.lua
Normal file
59
miku/plugins/get.lua
Normal file
@ -0,0 +1,59 @@
|
||||
local get = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
get.command = 'get <Variable>'
|
||||
|
||||
function get:init(config)
|
||||
get.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('get', true).table
|
||||
get.doc = [[*
|
||||
]]..config.cmd_pat..[[get*: Gibt alle Variablen aus
|
||||
*]]..config.cmd_pat..[[get* _<Variable>_: Gibt _Variable_ aus
|
||||
Nutze `!set <Variable> <Wert>` zum Setzen von Variablen]]
|
||||
end
|
||||
|
||||
function get:get_value(msg, var_name)
|
||||
local hash = get_redis_hash(msg, 'variables')
|
||||
if hash then
|
||||
local value = redis:hget(hash, var_name)
|
||||
if not value then
|
||||
return'Nicht gefunden; benutze /get, um alle Variablen aufzulisten.'
|
||||
else
|
||||
return var_name..' = '..value
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function get:list_variables(msg)
|
||||
local hash = get_redis_hash(msg, 'variables')
|
||||
print(hash)
|
||||
|
||||
if hash then
|
||||
print('Getting variable from redis hash '..hash)
|
||||
local names = redis:hkeys(hash)
|
||||
local text = ''
|
||||
for i=1, #names do
|
||||
variables = get:get_value(msg, names[i])
|
||||
text = text..variables.."\n"
|
||||
end
|
||||
if text == '' or text == nil then
|
||||
return 'Keine Variablen vorhanden!'
|
||||
else
|
||||
return text
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function get:action(msg)
|
||||
local input = utilities.input(msg.text)
|
||||
if input then
|
||||
output = get:get_value(msg, input:match('(.+)'))
|
||||
else
|
||||
output = get:list_variables(msg)
|
||||
end
|
||||
|
||||
utilities.send_message(self, msg.chat.id, output, true, nil, true)
|
||||
end
|
||||
|
||||
return get
|
113
miku/plugins/getfile.lua
Normal file
113
miku/plugins/getfile.lua
Normal file
@ -0,0 +1,113 @@
|
||||
-- YOU NEED THE FOLLOWING FOLDERS: photo, document, video, voice
|
||||
-- PLEASE ADJUST YOUR PATH BELOW
|
||||
-- Save your bot api key in redis set telegram:credentials!
|
||||
|
||||
local media_download = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
local ltn12 = require('ltn12')
|
||||
local HTTPS = require('ssl.https')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
media_download.triggers = {
|
||||
'/nil'
|
||||
}
|
||||
|
||||
function media_download:download_to_file_permanently(url, file_name)
|
||||
local respbody = {}
|
||||
local options = {
|
||||
url = url,
|
||||
sink = ltn12.sink.table(respbody),
|
||||
redirect = false
|
||||
}
|
||||
local response = nil
|
||||
response = {HTTPS.request(options)}
|
||||
|
||||
local code = response[2]
|
||||
local headers = response[3]
|
||||
local status = response[4]
|
||||
|
||||
if code ~= 200 then return false end
|
||||
|
||||
-- TODO: Save, when folder doesn't exist
|
||||
-- Create necessary folders in this folder!
|
||||
local file_path = "/home/YOURPATH/tmp/"..file_name
|
||||
file = io.open(file_path, "w+")
|
||||
file:write(table.concat(respbody))
|
||||
file:close()
|
||||
print("Downloaded to: "..file_path)
|
||||
return true
|
||||
end
|
||||
|
||||
function media_download:pre_process(msg, self)
|
||||
if msg.photo then
|
||||
local lv = #msg.photo -- find biggest photo, always the last value
|
||||
file_id = msg.photo[lv].file_id
|
||||
file_size = msg.photo[lv].file_size
|
||||
elseif msg.video then
|
||||
file_id = msg.video.file_id
|
||||
file_size = msg.video.file_size
|
||||
elseif msg.sticker then
|
||||
file_id = msg.sticker.file_id
|
||||
file_size = msg.sticker.file_size
|
||||
elseif msg.voice then
|
||||
file_id = msg.voice.file_id
|
||||
file_size = msg.voice.file_size
|
||||
elseif msg.audio then
|
||||
file_id = msg.audio.file_id
|
||||
file_size = msg.audio.file_size
|
||||
elseif msg.document then
|
||||
file_id = msg.document.file_id
|
||||
file_size = msg.document.file_size
|
||||
else
|
||||
return
|
||||
end
|
||||
|
||||
if file_size > 19922944 then
|
||||
print('File is over 20 MB - can\'t download :(')
|
||||
return
|
||||
end
|
||||
|
||||
-- Check if file has already been downloaded
|
||||
local already_downloaded = redis:sismember('telegram:file_id', file_id)
|
||||
if already_downloaded == true then
|
||||
print('File has already been downloaded in the past, skipping...')
|
||||
return
|
||||
end
|
||||
|
||||
-- Saving file to the Telegram Cloud
|
||||
local request = bindings.request(self, 'getFile', {
|
||||
file_id = file_id
|
||||
} )
|
||||
|
||||
-- Getting file from the Telegram Cloud
|
||||
if not request then
|
||||
print('Download failed!')
|
||||
return
|
||||
end
|
||||
|
||||
-- Use original filename for documents
|
||||
if msg.document then
|
||||
file_path = 'document/'..file_id..'-'..msg.document.file_name -- to not overwrite a file
|
||||
else
|
||||
file_path = request.result.file_path
|
||||
end
|
||||
|
||||
-- Construct what we want
|
||||
local download_url = 'https://api.telegram.org/file/bot'..cred_data.bot_api_key..'/'..request.result.file_path
|
||||
local ok = media_download:download_to_file_permanently(download_url, file_path)
|
||||
if not ok then
|
||||
print('Download failed!')
|
||||
return
|
||||
end
|
||||
|
||||
-- Save file_id to redis to prevent downloading the same file over and over when forwarding
|
||||
redis:sadd('telegram:file_id', file_id)
|
||||
return msg
|
||||
end
|
||||
|
||||
function media_download:action(msg)
|
||||
end
|
||||
|
||||
return media_download
|
36
miku/plugins/gfycat.lua
Normal file
36
miku/plugins/gfycat.lua
Normal file
@ -0,0 +1,36 @@
|
||||
-- Thanks to Akamaru for the API entrypoints and the initial idea
|
||||
|
||||
local gfycat = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
gfycat.triggers = {
|
||||
"gfycat.com/([A-Za-z0-9-_-]+)"
|
||||
}
|
||||
|
||||
function gfycat:send_gfycat_video(name, self, msg)
|
||||
local BASE_URL = "https://gfycat.com"
|
||||
local url = BASE_URL..'/cajax/get/'..name
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return "HTTP-FEHLER" end
|
||||
local data = json.decode(res).gfyItem
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_video')
|
||||
local file = download_to_file(data.webmUrl)
|
||||
if file == nil then
|
||||
send_reply(self, msg, 'Fehler beim Herunterladen von '..name)
|
||||
return
|
||||
else
|
||||
utilities.send_video(self, msg.chat.id, file, nil, msg.message_id)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function gfycat:action(msg, config, matches)
|
||||
local name = matches[1]
|
||||
gfycat:send_gfycat_video(name, self, msg)
|
||||
return
|
||||
end
|
||||
|
||||
return gfycat
|
77
miku/plugins/github.lua
Normal file
77
miku/plugins/github.lua
Normal file
@ -0,0 +1,77 @@
|
||||
local github = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local https = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
function github:init(config)
|
||||
github.triggers = {
|
||||
"github.com/([A-Za-z0-9-_-.-._.]+)/([A-Za-z0-9-_-.-._.]+)/commit/([a-z0-9-]+)",
|
||||
"github.com/([A-Za-z0-9-_-.-._.]+)/([A-Za-z0-9-_-.-._.]+)/?$"
|
||||
}
|
||||
end
|
||||
|
||||
local BASE_URL = 'https://api.github.com'
|
||||
|
||||
function github:get_gh_data(gh_code, gh_commit_sha)
|
||||
if gh_commit_sha == nil then
|
||||
url = BASE_URL..'/repos/'..gh_code
|
||||
else
|
||||
url = BASE_URL..'/repos/'..gh_code..'/git/commits/'..gh_commit_sha
|
||||
end
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return "HTTP-FEHLER" end
|
||||
local data = json.decode(res)
|
||||
return data
|
||||
end
|
||||
|
||||
function github:send_github_data(data)
|
||||
if not data.owner then return nil end
|
||||
local name = '*'..utilities.md_escape(data.name)..'*'
|
||||
local description = '_'..utilities.md_escape(data.description)..'_'
|
||||
local owner = utilities.md_escape(data.owner.login)
|
||||
local clone_url = data.clone_url
|
||||
if data.language == nil or data.language == "" then
|
||||
language = ''
|
||||
else
|
||||
language = '\nSprache: '..data.language
|
||||
end
|
||||
if data.open_issues_count == 0 then
|
||||
issues = ''
|
||||
else
|
||||
issues = '\nOffene Bugreports: '..data.open_issues_count
|
||||
end
|
||||
if data.homepage == nil or data.homepage == "" then
|
||||
homepage = ''
|
||||
else
|
||||
homepage = '\n[Homepage besuchen]('..data.homepage..')'
|
||||
end
|
||||
local text = name..' von '..owner..'\n'..description..'\n`git clone '..clone_url..'`'..language..issues..homepage
|
||||
return text
|
||||
end
|
||||
|
||||
function github:send_gh_commit_data(gh_code, gh_commit_sha, data)
|
||||
if not data.committer then return nil end
|
||||
local committer = data.committer.name
|
||||
local message = utilities.md_escape(data.message)
|
||||
local text = '`'..gh_code..'@'..gh_commit_sha..'` von *'..committer..'*:\n'..message
|
||||
return text
|
||||
end
|
||||
|
||||
function github:action(msg, config, matches)
|
||||
local gh_code = matches[1]..'/'..matches[2]
|
||||
local gh_commit_sha = matches[3]
|
||||
local data = github:get_gh_data(gh_code, gh_commit_sha)
|
||||
if not gh_commit_sha then
|
||||
output = github:send_github_data(data)
|
||||
else
|
||||
output = github:send_gh_commit_data(gh_code, gh_commit_sha, data)
|
||||
end
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
end
|
||||
|
||||
return github
|
68
miku/plugins/golem.lua
Normal file
68
miku/plugins/golem.lua
Normal file
@ -0,0 +1,68 @@
|
||||
local golem = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
function golem:init(config)
|
||||
if not cred_data.golem_apikey then
|
||||
print('Missing config value: golem_apikey.')
|
||||
print('golem.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
golem.triggers = {
|
||||
"golem.de/news/([A-Za-z0-9-_-]+)-(%d+).html"
|
||||
}
|
||||
end
|
||||
|
||||
local BASE_URL = 'http://api.golem.de/api'
|
||||
|
||||
function golem:get_golem_data (article_identifier)
|
||||
local apikey = cred_data.golem_apikey
|
||||
local url = BASE_URL..'/article/meta/'..article_identifier..'/?key='..apikey..'&format=json'
|
||||
local res,code = http.request(url)
|
||||
if code ~= 200 then return "HTTP-FEHLER" end
|
||||
local data = json.decode(res).data
|
||||
|
||||
local url = BASE_URL..'/article/images/'..article_identifier..'/?key='..apikey..'&format=json'
|
||||
local res,code = http.request(url)
|
||||
if code ~= 200 then return "HTTP-FEHLER" end
|
||||
local image_data = json.decode(res).data
|
||||
return data, image_data
|
||||
end
|
||||
|
||||
function golem:send_golem_data(data, image_data)
|
||||
local headline = '*'..data.headline..'*'
|
||||
if data.subheadline ~= "" then
|
||||
subheadline = '\n_'..data.subheadline..'_'
|
||||
else
|
||||
subheadline = ""
|
||||
end
|
||||
local subheadline = data.subheadline
|
||||
local abstracttext = data.abstracttext
|
||||
local text = headline..subheadline..'\n'..abstracttext
|
||||
if image_data[1] then
|
||||
image_url = image_data[1].native.url
|
||||
else
|
||||
image_url = data.leadimg.url
|
||||
end
|
||||
return text, image_url
|
||||
end
|
||||
|
||||
function golem:action(msg, config, matches)
|
||||
local article_identifier = matches[2]
|
||||
local data, image_data = golem:get_golem_data(article_identifier)
|
||||
if not data and not image_data then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
local text, image_url = golem:send_golem_data(data, image_data)
|
||||
|
||||
if image_url then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(image_url)
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
|
||||
return golem
|
47
miku/plugins/googl.lua
Normal file
47
miku/plugins/googl.lua
Normal file
@ -0,0 +1,47 @@
|
||||
local googl = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function googl:init(config)
|
||||
if not cred_data.google_apikey then
|
||||
print('Missing config value: google_apikey.')
|
||||
print('googl.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
googl.triggers = {
|
||||
"goo.gl/([A-Za-z0-9-_-/-/]+)"
|
||||
}
|
||||
end
|
||||
|
||||
local BASE_URL = 'https://www.googleapis.com/urlshortener/v1'
|
||||
|
||||
local makeOurDate = function(dateString)
|
||||
local pattern = "(%d+)%-(%d+)%-(%d+)"
|
||||
local year, month, day = dateString:match(pattern)
|
||||
return day..'.'..month..'.'..year
|
||||
end
|
||||
|
||||
function googl:send_googl_info (shorturl)
|
||||
local apikey = cred_data.google_apikey
|
||||
local url = BASE_URL..'/url?key='..apikey..'&shortUrl=http://goo.gl/'..shorturl..'&projection=FULL&fields=longUrl,created,analytics(allTime(shortUrlClicks))'
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return "HTTP-FEHLER" end
|
||||
local data = json.decode(res)
|
||||
|
||||
local longUrl = data.longUrl
|
||||
local shortUrlClicks = data.analytics.allTime.shortUrlClicks
|
||||
local created = makeOurDate(data.created)
|
||||
local text = longUrl..'\n'..shortUrlClicks..' mal geklickt (erstellt am '..created..')'
|
||||
|
||||
return text
|
||||
end
|
||||
|
||||
function googl:action(msg, config, matches)
|
||||
local shorturl = matches[1]
|
||||
utilities.send_reply(self, msg, googl:send_googl_info(shorturl))
|
||||
end
|
||||
|
||||
return googl
|
38
miku/plugins/gps.lua
Normal file
38
miku/plugins/gps.lua
Normal file
@ -0,0 +1,38 @@
|
||||
local gps = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
gps.command = 'gps <Breitengrad>,<Längengrad>'
|
||||
|
||||
function gps:init(config)
|
||||
gps.triggers = {
|
||||
"^/gps ([^,]*)[,%s]([^,]*)$",
|
||||
"google.de/maps/@([^,]*)[,%s]([^,]*)",
|
||||
"google.com/maps/@([^,]*)[,%s]([^,]*)",
|
||||
"google.de/maps/place/@([^,]*)[,%s]([^,]*)",
|
||||
"google.com/maps/place/@([^,]*)[,%s]([^,]*)"
|
||||
}
|
||||
gps.doc = [[*
|
||||
]]..config.cmd_pat..[[gps* _<Breitengrad>_,_<Längengrad>_: Sendet Karte mit diesen Koordinaten]]
|
||||
end
|
||||
|
||||
function gps:action(msg, config, matches)
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local lat = matches[1]
|
||||
local lon = matches[2]
|
||||
|
||||
local zooms = {16, 18}
|
||||
|
||||
local urls = {}
|
||||
for i in ipairs(zooms) do
|
||||
local zoom = zooms[i]
|
||||
local url = "https://maps.googleapis.com/maps/api/staticmap?zoom=" .. zoom .. "&size=600x300&maptype=hybrid¢er=" .. lat .. "," .. lon .. "&markers=color:red%7Clabel:•%7C" .. lat .. "," .. lon
|
||||
local file = download_to_file(url, 'zoom_'..i..'.png')
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
|
||||
utilities.send_location(self, msg.chat.id, lat, lon, msg.message_id)
|
||||
end
|
||||
|
||||
return gps
|
63
miku/plugins/greetings.lua
Normal file
63
miku/plugins/greetings.lua
Normal file
@ -0,0 +1,63 @@
|
||||
-- Put this on the bottom of your plugin list, after help.lua.
|
||||
-- If you want to configure your own greetings, copy the following table
|
||||
-- (without the "config.") to your config.lua file.
|
||||
|
||||
local greetings = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function greetings:init(config)
|
||||
config.greetings = config.greetings or {
|
||||
['Hello, #NAME.'] = {
|
||||
'hello',
|
||||
'hey',
|
||||
'sup',
|
||||
'hi',
|
||||
'good morning',
|
||||
'good day',
|
||||
'good afternoon',
|
||||
'good evening'
|
||||
},
|
||||
['Goodbye, #NAME.'] = {
|
||||
'bye',
|
||||
'later',
|
||||
'see ya',
|
||||
'good night'
|
||||
},
|
||||
['Welcome back, #NAME.'] = {
|
||||
'i\'m home',
|
||||
'i\'m back'
|
||||
},
|
||||
['You\'re welcome, #NAME.'] = {
|
||||
'thanks',
|
||||
'thank you'
|
||||
}
|
||||
}
|
||||
|
||||
greetings.triggers = {
|
||||
self.info.first_name:lower() .. '%p*$'
|
||||
}
|
||||
end
|
||||
|
||||
function greetings:action(msg, config)
|
||||
|
||||
local nick = utilities.build_name(msg.from.first_name, msg.from.last_name)
|
||||
if self.database.userdata[tostring(msg.from.id)] then
|
||||
nick = self.database.userdata[tostring(msg.from.id)].nickname or nick
|
||||
end
|
||||
|
||||
for trigger,responses in pairs(config.greetings) do
|
||||
for _,response in pairs(responses) do
|
||||
if msg.text_lower:match(response..',? '..self.info.first_name:lower()) then
|
||||
local output = utilities.char.zwnj .. trigger:gsub('#NAME', nick)
|
||||
utilities.send_message(self, msg.chat.id, output)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
return greetings
|
45
miku/plugins/hackernews.lua
Normal file
45
miku/plugins/hackernews.lua
Normal file
@ -0,0 +1,45 @@
|
||||
local hackernews = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local URL = require('socket.url')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
hackernews.triggers = {
|
||||
"news.ycombinator.com/item%?id=(%d+)"
|
||||
}
|
||||
|
||||
local BASE_URL = 'https://hacker-news.firebaseio.com/v0'
|
||||
|
||||
function hackernews:send_hackernews_post (hn_code)
|
||||
local url = BASE_URL..'/item/'..hn_code..'.json'
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return "HTTP-FEHLER" end
|
||||
local data = json.decode(res)
|
||||
|
||||
local by = data.by
|
||||
local title = data.title
|
||||
|
||||
if data.url then
|
||||
url = '\n[Link besuchen]('..data.url..')'
|
||||
else
|
||||
url = ''
|
||||
end
|
||||
|
||||
if data.text then
|
||||
post = '\n'..unescape_html(data.text)
|
||||
post = string.gsub(post, '<p>', ' ')
|
||||
else
|
||||
post = ''
|
||||
end
|
||||
local text = '*'..title..'* von _'..by..'_'..post..url
|
||||
|
||||
return text
|
||||
end
|
||||
|
||||
function hackernews:action(msg, config, matches)
|
||||
local hn_code = matches[1]
|
||||
utilities.send_reply(self, msg, hackernews:send_hackernews_post(hn_code), true)
|
||||
end
|
||||
|
||||
return hackernews
|
48
miku/plugins/heise.lua
Normal file
48
miku/plugins/heise.lua
Normal file
@ -0,0 +1,48 @@
|
||||
local heise = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
heise.triggers = {
|
||||
"heise.de/newsticker/meldung/(.*).html$"
|
||||
}
|
||||
|
||||
function heise:get_heise_article(article)
|
||||
local url = 'https://query.yahooapis.com/v1/public/yql?q=select%20content,src,strong%20from%20html%20where%20url=%22http://www.heise.de/newsticker/meldung/'..article..'.html%22%20and%20xpath=%22//div[@id=%27mitte_news%27]/article/header/h2|//div[@id=%27mitte_news%27]/article/div/p[1]/strong|//div[@id=%27mitte_news%27]/article/div/figure/img%22&format=json'
|
||||
local res,code = https.request(url)
|
||||
local data = json.decode(res).query.results
|
||||
if code ~= 200 then return "HTTP-Fehler" end
|
||||
|
||||
local title = data.h2
|
||||
if data.strong then
|
||||
teaser = '\n'..data.strong
|
||||
else
|
||||
teaser = ''
|
||||
end
|
||||
if data.img then
|
||||
image_url = 'https:'..data.img.src
|
||||
end
|
||||
local text = '*'..title..'*'..teaser
|
||||
|
||||
if data.img then
|
||||
return text, image_url
|
||||
else
|
||||
return text
|
||||
end
|
||||
end
|
||||
|
||||
function heise:action(msg, config, matches)
|
||||
local article = URL.escape(matches[1])
|
||||
local text, image_url = heise:get_heise_article(article)
|
||||
if image_url then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(image_url, 'heise_teaser.jpg')
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
|
||||
return heise
|
13
miku/plugins/hello.lua
Normal file
13
miku/plugins/hello.lua
Normal file
@ -0,0 +1,13 @@
|
||||
local hello = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
hello.triggers = {
|
||||
"^[Ss][Aa][Gg] [Hh][Aa][Ll][Ll][Oo] [Zz][Uu] (.*)$"
|
||||
}
|
||||
|
||||
function hello:action(msg, config, matches)
|
||||
utilities.send_reply(self, msg, 'Hallo, '..matches[1]..'!')
|
||||
end
|
||||
|
||||
return hello
|
58
miku/plugins/help.lua
Normal file
58
miku/plugins/help.lua
Normal file
@ -0,0 +1,58 @@
|
||||
-- This plugin should go at the end of your plugin list in
|
||||
-- config.lua, but not after greetings.lua.
|
||||
|
||||
local help = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
local help_text
|
||||
|
||||
function help:init(config)
|
||||
help.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('hilfe', true):t('help', true).table
|
||||
end
|
||||
|
||||
function help:action(msg, config)
|
||||
|
||||
local commandlist = {}
|
||||
help_text = '*Verfügbare Befehle:*\n• '..config.cmd_pat
|
||||
|
||||
for _,plugin in ipairs(self.plugins) do
|
||||
if plugin.command then
|
||||
|
||||
table.insert(commandlist, plugin.command)
|
||||
--help_text = help_text .. '\n• '..config.cmd_pat .. plugin.command:gsub('%[', '\\[')
|
||||
end
|
||||
end
|
||||
|
||||
table.insert(commandlist, 'hilfe [Plugin]')
|
||||
table.sort(commandlist)
|
||||
help_text = help_text .. table.concat(commandlist, '\n• '..config.cmd_pat) .. '\nParameter: <benötigt> [optional]'
|
||||
|
||||
help_text = help_text:gsub('%[', '\\[')
|
||||
local input = utilities.input(msg.text_lower)
|
||||
|
||||
-- Attempts to send the help message via PM.
|
||||
-- If msg is from a group, it tells the group whether the PM was successful.
|
||||
if not input then
|
||||
local res = utilities.send_message(self, msg.from.id, help_text, true, nil, true)
|
||||
if not res then
|
||||
utilities.send_reply(self, msg, 'Bitte schreibe mir zuerst [privat](http://telegram.me/' .. self.info.username .. '?start=help) für eine Hilfe.', true)
|
||||
elseif msg.chat.type ~= 'private' then
|
||||
utilities.send_reply(self, msg, 'Ich habe dir die Hilfe per PN gesendet!.')
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
for _,plugin in ipairs(self.plugins) do
|
||||
if plugin.command and utilities.get_word(plugin.command, 1) == input and plugin.doc then
|
||||
local output = '*Hilfe für* _' .. utilities.get_word(plugin.command, 1) .. '_ *:*' .. plugin.doc
|
||||
utilities.send_message(self, msg.chat.id, output, true, nil, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
utilities.send_reply(self, msg, 'Für diesen Befehl gibt es keine Hilfe.')
|
||||
|
||||
end
|
||||
|
||||
return help
|
130
miku/plugins/id.lua
Normal file
130
miku/plugins/id.lua
Normal file
@ -0,0 +1,130 @@
|
||||
local id = {}
|
||||
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
local bindings = require('miku.bindings')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
id.command = 'id'
|
||||
|
||||
function id:init(config)
|
||||
id.triggers = {
|
||||
"^/id$",
|
||||
"^/ids? (chat)$"
|
||||
}
|
||||
id.doc = [[```
|
||||
Returns user and chat info for you or the replied-to message.
|
||||
Alias: ]]..config.cmd_pat..[[who
|
||||
```]]
|
||||
end
|
||||
|
||||
function id:get_member_count(self, msg, chat_id)
|
||||
return bindings.request(self, 'getChatMembersCount', {
|
||||
chat_id = chat_id
|
||||
} )
|
||||
end
|
||||
|
||||
function id:user_print_name(user) -- Yes, copied from stats plugin
|
||||
if user.name then
|
||||
return user.name
|
||||
end
|
||||
|
||||
local text = ''
|
||||
if user.first_name then
|
||||
text = user.last_name..' '
|
||||
end
|
||||
if user.lastname then
|
||||
text = text..user.last_name
|
||||
end
|
||||
|
||||
return text
|
||||
end
|
||||
|
||||
function id:get_user(user_id, chat_id)
|
||||
local user_info = {}
|
||||
local uhash = 'user:'..user_id
|
||||
local user = redis:hgetall(uhash)
|
||||
user_info.name = id:user_print_name(user)
|
||||
user_info.id = user_id
|
||||
return user_info
|
||||
end
|
||||
|
||||
function id:action(msg)
|
||||
|
||||
if matches[1] == "/id" then
|
||||
if msg.reply_to_message then
|
||||
msg = msg.reply_to_message
|
||||
msg.from.name = utilities.build_name(msg.from.first_name, msg.from.last_name)
|
||||
end
|
||||
|
||||
local chat_id = msg.chat.id
|
||||
local user = 'Du bist @%s, auch bekannt als *%s* `[%s]`'
|
||||
if msg.from.username then
|
||||
user = user:format(utilities.markdown_escape(msg.from.username), msg.from.name, msg.from.id)
|
||||
else
|
||||
user = 'Du bist *%s* `[%s]`,'
|
||||
user = user:format(msg.from.name, msg.from.id)
|
||||
end
|
||||
|
||||
local group = '@%s, auch bekannt als *%s* `[%s]`.'
|
||||
if msg.chat.type == 'private' then
|
||||
group = group:format(utilities.markdown_escape(self.info.username), self.info.first_name, self.info.id)
|
||||
elseif msg.chat.username then
|
||||
group = group:format(utilities.markdown_escape(msg.chat.username), msg.chat.title, chat_id)
|
||||
else
|
||||
group = '*%s* `[%s]`.'
|
||||
group = group:format(msg.chat.title, chat_id)
|
||||
end
|
||||
|
||||
local output = user .. ', und du bist in der Gruppe ' .. group
|
||||
|
||||
utilities.send_message(self, msg.chat.id, output, true, msg.message_id, true)
|
||||
elseif matches[1] == "chat" then
|
||||
if msg.chat.type ~= 'group' and msg.chat.type ~= 'supergroup' then
|
||||
utilities.send_reply(self, msg, 'Das hier ist keine Gruppe!')
|
||||
return
|
||||
end
|
||||
local chat_name = msg.chat.title
|
||||
local chat_id = msg.chat.id
|
||||
-- Users on chat
|
||||
local hash = 'chat:'..chat_id..':users'
|
||||
local users = redis:smembers(hash)
|
||||
local users_info = {}
|
||||
-- Get user info
|
||||
for i = 1, #users do
|
||||
local user_id = users[i]
|
||||
local user_info = id:get_user(user_id, chat_id)
|
||||
table.insert(users_info, user_info)
|
||||
end
|
||||
|
||||
-- get all administrators and the creator
|
||||
local administrators = utilities.get_chat_administrators(self, chat_id)
|
||||
local admins = {}
|
||||
for num in pairs(administrators.result) do
|
||||
if administrators.result[num].status ~= 'creator' then
|
||||
table.insert(admins, tostring(administrators.result[num].user.id))
|
||||
else
|
||||
creator_id = administrators.result[num].user.id
|
||||
end
|
||||
end
|
||||
local result = id:get_member_count(self, msg, chat_id)
|
||||
local member_count = result.result - 1 -- minus the bot
|
||||
if member_count == 1 then
|
||||
member_count = 'ist *1 Mitglied'
|
||||
else
|
||||
member_count = 'sind *'..member_count..' Mitglieder'
|
||||
end
|
||||
local text = 'IDs für *'..chat_name..'* `['..chat_id..']`\nHier '..member_count..':*\n---------\n'
|
||||
for k,user in pairs(users_info) do
|
||||
if table.contains(admins, tostring(user.id)) then
|
||||
text = text..'*'..user.name..'* `['..user.id..']` _Administrator_\n'
|
||||
elseif tostring(creator_id) == user.id then
|
||||
text = text..'*'..user.name..'* `['..user.id..']` _Gruppenersteller_\n'
|
||||
else
|
||||
text = text..'*'..user.name..'* `['..user.id..']`\n'
|
||||
end
|
||||
end
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
end
|
||||
|
||||
return id
|
80
miku/plugins/ifttt.lua
Normal file
80
miku/plugins/ifttt.lua
Normal file
@ -0,0 +1,80 @@
|
||||
local ifttt = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
function ifttt:init(config)
|
||||
ifttt.triggers = {
|
||||
"^/ifttt (!set) (.*)$",
|
||||
"^/ifttt (!unauth)$",
|
||||
"^/ifttt (.*)%&(.*)%&(.*)%&(.*)",
|
||||
"^/ifttt (.*)%&(.*)%&(.*)",
|
||||
"^/ifttt (.*)%&(.*)",
|
||||
"^/ifttt (.*)$"
|
||||
}
|
||||
|
||||
ifttt.doc = [[*
|
||||
]]..config.cmd_pat..[[ifttt* _!set_ _<Key>_: Speichere deinen Schlüssel ein (erforderlich)
|
||||
*]]..config.cmd_pat..[[ifttt* _!unauth_: Löscht deinen Account aus dem Bot
|
||||
*]]..config.cmd_pat..[[ifttt* _<Event>_&_<Value1>_&_<Value2>_&_<Value3>_: Führt [Event] mit den optionalen Parametern Value1, Value2 und Value3 aus
|
||||
Beispiel: `/ifttt DeinFestgelegterName&Hallo&NochEinHallo`: Führt 'DeinFestgelegterName' mit den Parametern 'Hallo' und 'NochEinHallo' aus.]]
|
||||
end
|
||||
|
||||
ifttt.command = 'ifttt <Event>&<Value1>&<Value2>&<Value3>'
|
||||
|
||||
local BASE_URL = 'https://maker.ifttt.com/trigger'
|
||||
|
||||
function ifttt:set_ifttt_key(hash, key)
|
||||
print('Setting ifttt in redis hash '..hash..' to '..key)
|
||||
redis:hset(hash, 'ifttt', key)
|
||||
return '*Schlüssel eingespeichert!* Das Plugin kann jetzt verwendet werden.'
|
||||
end
|
||||
|
||||
function ifttt:do_ifttt_request(key, event, value1, value2, value3)
|
||||
if not value1 then
|
||||
url = BASE_URL..'/'..event..'/with/key/'..key
|
||||
elseif not value2 then
|
||||
url = BASE_URL..'/'..event..'/with/key/'..key..'/?value1='..URL.escape(value1)
|
||||
elseif not value3 then
|
||||
url = BASE_URL..'/'..event..'/with/key/'..key..'/?value1='..URL.escape(value1)..'&value2='..URL.escape(value2)
|
||||
else
|
||||
url = BASE_URL..'/'..event..'/with/key/'..key..'/?value1='..URL.escape(value1)..'&value2='..URL.escape(value2)..'&value3='..URL.escape(value3)
|
||||
end
|
||||
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return "*Ein Fehler ist aufgetreten!* Aktion wurde nicht ausgeführt." end
|
||||
|
||||
return "*Event \""..event.."\" getriggert!*"
|
||||
end
|
||||
|
||||
function ifttt:action(msg, config, matches)
|
||||
local hash = 'user:'..msg.from.id
|
||||
local key = redis:hget(hash, 'ifttt')
|
||||
local event = matches[1]
|
||||
local value1 = matches[2]
|
||||
local value2 = matches[3]
|
||||
local value3 = matches[4]
|
||||
|
||||
if event == '!set' then
|
||||
utilities.send_reply(self, msg, ifttt:set_ifttt_key(hash, value1), true)
|
||||
return
|
||||
end
|
||||
|
||||
if not key then
|
||||
utilities.send_reply(self, msg, '*Bitte speichere zuerst deinen Schlüssel ein!* Aktiviere dazu den [Maker Channel](https://ifttt.com/maker) und speichere deinen Schlüssel mit `/ifttt !set KEY` ein', true)
|
||||
return
|
||||
end
|
||||
|
||||
if event == '!unauth' then
|
||||
redis:hdel(hash, 'ifttt')
|
||||
utilities.send_reply(self, msg, '*Erfolgreich ausgeloggt!*', true)
|
||||
return
|
||||
end
|
||||
|
||||
utilities.send_reply(self, msg, ifttt:do_ifttt_request(key, event, value1, value2, value3), true)
|
||||
end
|
||||
|
||||
return ifttt
|
21
miku/plugins/images.lua
Normal file
21
miku/plugins/images.lua
Normal file
@ -0,0 +1,21 @@
|
||||
local images = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
images.triggers = {
|
||||
"(https?://[%w-_%%%.%?%.:,/%+=~&%[%]]+%.[Pp][Nn][Gg])$",
|
||||
"(https?://[%w-_%%%.%?%.:,/%+=~&%[%]]+%.[Jj][Pp][Ee]?[Gg])$"
|
||||
}
|
||||
|
||||
function images:action(msg)
|
||||
local url = matches[1]
|
||||
local file, last_modified, nocache = get_cached_file(url, nil, msg.chat.id, 'upload_photo', self)
|
||||
local result = utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
|
||||
if nocache then return end
|
||||
if not result then return end
|
||||
|
||||
-- Cache File-ID und Last-Modified-Header in Redis
|
||||
cache_file(result, url, last_modified)
|
||||
end
|
||||
|
||||
return images
|
59
miku/plugins/imdb.lua
Normal file
59
miku/plugins/imdb.lua
Normal file
@ -0,0 +1,59 @@
|
||||
local imdb = {}
|
||||
|
||||
local HTTP = require('socket.http')
|
||||
local URL = require('socket.url')
|
||||
local JSON = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
imdb.command = 'imdb <query>'
|
||||
|
||||
function imdb:init(config)
|
||||
imdb.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('imdb', true).table
|
||||
imdb.doc = [[*
|
||||
]]..config.cmd_pat..[[imdb* _<Film>_
|
||||
Sucht _Film_ bei IMDB]]
|
||||
end
|
||||
|
||||
function imdb:action(msg, config)
|
||||
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
if msg.reply_to_message and msg.reply_to_message.text then
|
||||
input = msg.reply_to_message.text
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, imdb.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local url = 'http://www.omdbapi.com/?t=' .. URL.escape(input)
|
||||
|
||||
local jstr, res = HTTP.request(url)
|
||||
if res ~= 200 then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
return
|
||||
end
|
||||
|
||||
local jdat = JSON.decode(jstr)
|
||||
|
||||
if jdat.Response ~= 'True' then
|
||||
utilities.send_reply(self, msg, config.errors.results)
|
||||
return
|
||||
end
|
||||
|
||||
local output = '*' .. jdat.Title .. ' ('.. jdat.Year ..')* von '..jdat.Director..'\n'
|
||||
output = output .. string.gsub(jdat.imdbRating, '%.', ',') ..'/10 | '.. jdat.Runtime ..' | '.. jdat.Genre ..'\n'
|
||||
output = output .. '_' .. jdat.Plot .. '_\n'
|
||||
output = output .. '[IMDB-Seite besuchen](http://imdb.com/title/' .. jdat.imdbID .. ')'
|
||||
|
||||
utilities.send_message(self, msg.chat.id, output, true, nil, true)
|
||||
|
||||
if jdat.Poster ~= "N/A" then
|
||||
local file = download_to_file(jdat.Poster)
|
||||
utilities.send_photo(self, msg.chat.id, file)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return imdb
|
84
miku/plugins/imgblacklist.lua
Normal file
84
miku/plugins/imgblacklist.lua
Normal file
@ -0,0 +1,84 @@
|
||||
local imgblacklist = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
imgblacklist.command = 'imgblacklist'
|
||||
|
||||
function imgblacklist:init(config)
|
||||
imgblacklist.triggers = {
|
||||
"^/imgblacklist show$",
|
||||
"^/imgblacklist (add) (.*)$",
|
||||
"^/imgblacklist (remove) (.*)$"
|
||||
}
|
||||
imgblacklist.doc = [[*
|
||||
]]..config.cmd_pat..[[imgblacklist* _show_: Zeige Blacklist
|
||||
*]]..config.cmd_pat..[[imgblacklist* _add_ _<Wort>_: Fügt Wort der Blacklist hinzu
|
||||
*]]..config.cmd_pat..[[imgblacklist* _remove_ _<Wort>_: Entfernt Wort von der Blacklist]]
|
||||
end
|
||||
|
||||
function imgblacklist:show_blacklist()
|
||||
if not _blacklist[1] then
|
||||
return "Keine Wörter geblacklisted!\nBlackliste welche mit `/imgblacklist add [Wort]`"
|
||||
else
|
||||
local sort_alph = function( a,b ) return a < b end
|
||||
table.sort( _blacklist, sort_alph )
|
||||
local blacklist = "Folgende Wörter stehen auf der Blacklist:\n"
|
||||
for v,word in pairs(_blacklist) do
|
||||
blacklist = blacklist..'- '..word..'\n'
|
||||
end
|
||||
return blacklist
|
||||
end
|
||||
end
|
||||
|
||||
function imgblacklist:add_blacklist(word)
|
||||
print('Blacklisting '..word..' - saving to redis set telegram:img_blacklist')
|
||||
if redis:sismember("telegram:img_blacklist", word) == true then
|
||||
return '"'..word..'" steht schon auf der Blacklist.'
|
||||
else
|
||||
redis:sadd("telegram:img_blacklist", word)
|
||||
return '"'..word..'" blacklisted!'
|
||||
end
|
||||
end
|
||||
|
||||
function imgblacklist:remove_blacklist(word)
|
||||
print('De-blacklisting '..word..' - removing from redis set telegram:img_blacklist')
|
||||
if redis:sismember("telegram:img_blacklist", word) == true then
|
||||
redis:srem("telegram:img_blacklist", word)
|
||||
return '"'..word..'" erfolgreich von der Blacklist gelöscht!'
|
||||
else
|
||||
return '"'..word..'" steht nicht auf der Blacklist.'
|
||||
end
|
||||
end
|
||||
|
||||
function imgblacklist:action(msg, config, matches)
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
|
||||
|
||||
local action = matches[1]
|
||||
if matches[2] then word = string.lower(matches[2]) else word = nil end
|
||||
_blacklist = redis:smembers("telegram:img_blacklist")
|
||||
|
||||
if action == 'add' and not word then
|
||||
utilities.send_reply(self, msg, imgblacklist.doc, true)
|
||||
return
|
||||
elseif action == "add" and word then
|
||||
utilities.send_reply(self, msg, imgblacklist:add_blacklist(word), true)
|
||||
return
|
||||
end
|
||||
|
||||
if action == 'remove' and not word then
|
||||
utilities.send_reply(self, msg, imgblacklist.doc, true)
|
||||
return
|
||||
elseif action == "remove" and word then
|
||||
utilities.send_reply(self, msg, imgblacklist:remove_blacklist(word), true)
|
||||
return
|
||||
end
|
||||
|
||||
utilities.send_reply(self, msg, imgblacklist:show_blacklist())
|
||||
end
|
||||
|
||||
return imgblacklist
|
60
miku/plugins/imgur.lua
Normal file
60
miku/plugins/imgur.lua
Normal file
@ -0,0 +1,60 @@
|
||||
local imgur = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function imgur:init(config)
|
||||
if not cred_data.imgur_client_id then
|
||||
print('Missing config value: imgur_client_id.')
|
||||
print('imgur.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
imgur.triggers = {
|
||||
"imgur.com/([A-Za-z0-9]+).gifv",
|
||||
"https?://imgur.com/([A-Za-z0-9]+)"
|
||||
}
|
||||
end
|
||||
|
||||
local client_id = cred_data.imgur_client_id
|
||||
local BASE_URL = 'https://api.imgur.com/3'
|
||||
|
||||
function imgur:get_imgur_data(imgur_code)
|
||||
local response_body = {}
|
||||
local request_constructor = {
|
||||
url = BASE_URL..'/image/'..imgur_code,
|
||||
method = "GET",
|
||||
sink = ltn12.sink.table(response_body),
|
||||
headers = {
|
||||
Authorization = 'Client-ID '..client_id
|
||||
}
|
||||
}
|
||||
local ok, response_code, response_headers, response_status_line = https.request(request_constructor)
|
||||
if not ok then
|
||||
return nil
|
||||
end
|
||||
|
||||
local response_body = json.decode(table.concat(response_body))
|
||||
|
||||
if response_body.status ~= 200 then return nil end
|
||||
|
||||
return response_body.data.link
|
||||
end
|
||||
|
||||
function imgur:action(msg)
|
||||
local imgur_code = matches[1]
|
||||
if imgur_code == "login" then return nil end
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local link = imgur:get_imgur_data(imgur_code)
|
||||
if link then
|
||||
local file = download_to_file(link)
|
||||
if string.ends(link, ".gif") then
|
||||
utilities.send_document(self, msg.chat.id, file, nil, msg.message_id)
|
||||
else
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return imgur
|
80
miku/plugins/instagram.lua
Normal file
80
miku/plugins/instagram.lua
Normal file
@ -0,0 +1,80 @@
|
||||
local instagram = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local URL = require('socket.url')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function instagram:init(config)
|
||||
if not cred_data.instagram_access_token then
|
||||
print('Missing config value: instagram_access_token.')
|
||||
print('instagram.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
instagram.triggers = {
|
||||
"instagram.com/p/([A-Za-z0-9-_-]+)"
|
||||
}
|
||||
end
|
||||
|
||||
local BASE_URL = 'https://api.instagram.com/v1'
|
||||
local access_token = cred_data.instagram_access_token
|
||||
|
||||
function instagram:get_insta_data(insta_code)
|
||||
local url = BASE_URL..'/media/shortcode/'..insta_code..'?access_token='..access_token
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res).data
|
||||
return data
|
||||
end
|
||||
|
||||
function instagram:send_instagram_data(data)
|
||||
-- Header
|
||||
local username = data.user.username
|
||||
local full_name = data.user.full_name
|
||||
if username == full_name then
|
||||
header = full_name..' hat ein'
|
||||
else
|
||||
header = full_name..' ('..username..') hat ein'
|
||||
end
|
||||
if data.type == 'video' then
|
||||
header = header..' Video gepostet'
|
||||
else
|
||||
header = header..' Foto gepostet'
|
||||
end
|
||||
|
||||
-- Caption
|
||||
if data.caption == nil then
|
||||
caption = ''
|
||||
else
|
||||
caption = ':\n'..data.caption.text
|
||||
end
|
||||
|
||||
-- Footer
|
||||
local comments = comma_value(data.comments.count)
|
||||
local likes = comma_value(data.likes.count)
|
||||
local footer = '\n'..likes..' Likes, '..comments..' Kommentare'
|
||||
if data.type == 'video' then
|
||||
footer = '\n'..data.videos.standard_resolution.url..footer
|
||||
end
|
||||
|
||||
-- Image
|
||||
local image_url = data.images.standard_resolution.url
|
||||
|
||||
return header..caption..footer, image_url
|
||||
end
|
||||
|
||||
function instagram:action(msg, config, matches)
|
||||
local insta_code = matches[1]
|
||||
local data = instagram:get_insta_data(insta_code)
|
||||
if not data then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
|
||||
local text, image_url = instagram:send_instagram_data(data)
|
||||
if not image_url then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(image_url)
|
||||
utilities.send_photo(self, msg.chat.id, file, text, msg.message_id)
|
||||
end
|
||||
|
||||
return instagram
|
92
miku/plugins/ip_info.lua
Normal file
92
miku/plugins/ip_info.lua
Normal file
@ -0,0 +1,92 @@
|
||||
local ip_info = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local json = require('dkjson')
|
||||
local URL = require('socket.url')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function ip_info:init(config)
|
||||
ip_info.triggers = {
|
||||
"^/ip (.*)$",
|
||||
"^/dns (.*)$"
|
||||
}
|
||||
|
||||
ip_info.doc = [[*
|
||||
]]..config.cmd_pat..[[ip* _<IP-Adresse>_: Sendet Infos zu dieser IP]]
|
||||
end
|
||||
|
||||
ip_info.command = 'ip <IP-Adresse>'
|
||||
|
||||
local BASE_URL = 'http://ip-api.com/json'
|
||||
|
||||
function ip_info:get_host_data(host)
|
||||
local url = BASE_URL..'/'..host..'?lang=de&fields=country,regionName,city,zip,lat,lon,isp,org,as,status,message,reverse,query'
|
||||
local res,code = http.request(url)
|
||||
if code ~= 200 then return "HTTP-FEHLER: "..code end
|
||||
local data = json.decode(res)
|
||||
if data.status == 'fail' then
|
||||
return nil
|
||||
end
|
||||
|
||||
local isp = data.isp
|
||||
|
||||
local url
|
||||
if data.lat and data.lon then
|
||||
lat = tostring(data.lat)
|
||||
lon = tostring(data.lon)
|
||||
url = "https://maps.googleapis.com/maps/api/staticmap?zoom=16&size=600x300&maptype=hybrid¢er="..lat..","..lon.."&markers=color:red%7Clabel:•%7C"..lat..","..lon
|
||||
end
|
||||
|
||||
if data.query == host then
|
||||
query = ''
|
||||
else
|
||||
query = ' / '..data.query
|
||||
end
|
||||
|
||||
if data.reverse ~= "" and data.reverse ~= host then
|
||||
host_addr = ' ('..data.reverse..')'
|
||||
else
|
||||
host_addr = ''
|
||||
end
|
||||
|
||||
-- Location
|
||||
if data.zip ~= "" then
|
||||
zipcode = data.zip..' '
|
||||
else
|
||||
zipcode = ''
|
||||
end
|
||||
|
||||
local city = data.city
|
||||
|
||||
if data.regionName ~= "" then
|
||||
region = ', '..data.regionName
|
||||
else
|
||||
region = ''
|
||||
end
|
||||
|
||||
if data.country ~= "" then
|
||||
country = ', '..data.country
|
||||
else
|
||||
country = ''
|
||||
end
|
||||
|
||||
local text = host..query..host_addr..' ist bei '..isp..':\n'
|
||||
local location = zipcode..city..region..country
|
||||
return text..location, url
|
||||
end
|
||||
|
||||
function ip_info:action(msg, config, matches)
|
||||
local host = matches[1]
|
||||
local text, image_url = ip_info:get_host_data(host)
|
||||
if not text then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
|
||||
if image_url then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(image_url, 'map.png')
|
||||
utilities.send_photo(self, msg.chat.id, file, text, msg.message_id)
|
||||
else
|
||||
utilities.send_reply(self, msg, text)
|
||||
end
|
||||
end
|
||||
|
||||
return ip_info
|
85
miku/plugins/isup.lua
Normal file
85
miku/plugins/isup.lua
Normal file
@ -0,0 +1,85 @@
|
||||
local isup = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local https = require('ssl.https')
|
||||
local socket = require('socket')
|
||||
local URL = require('socket.url')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function isup:init(config)
|
||||
isup.triggers = {
|
||||
"^/isup (.*)$",
|
||||
"^/ping (.*)$"
|
||||
}
|
||||
|
||||
isup.doc = [[*
|
||||
]]..config.cmd_pat..[[isup* _<URL>_: Prüft, ob die URL up ist]]
|
||||
end
|
||||
|
||||
function isup:is_up_socket(ip, port)
|
||||
print('Connect to', ip, port)
|
||||
local c = socket.try(socket.tcp())
|
||||
c:settimeout(3)
|
||||
local conn = c:connect(ip, port)
|
||||
if not conn then
|
||||
return false
|
||||
else
|
||||
c:close()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function isup:is_up_http(url)
|
||||
-- Parse URL from input, default to http
|
||||
local parsed_url = URL.parse(url, { scheme = 'http', authority = '' })
|
||||
-- Fix URLs without subdomain not parsed properly
|
||||
if not parsed_url.host and parsed_url.path then
|
||||
parsed_url.host = parsed_url.path
|
||||
parsed_url.path = ""
|
||||
end
|
||||
-- Re-build URL
|
||||
local url = URL.build(parsed_url)
|
||||
|
||||
local protocols = {
|
||||
["https"] = https,
|
||||
["http"] = http
|
||||
}
|
||||
local options = {
|
||||
url = url,
|
||||
redirect = false,
|
||||
method = "GET"
|
||||
}
|
||||
local response = { protocols[parsed_url.scheme].request(options) }
|
||||
local code = tonumber(response[2])
|
||||
if code == nil or code >= 400 then
|
||||
return false
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
function isup:isup(url)
|
||||
local pattern = '^(%d%d?%d?%.%d%d?%d?%.%d%d?%d?%.%d%d?%d?):?(%d?%d?%d?%d?%d?)$'
|
||||
local ip,port = string.match(url, pattern)
|
||||
local result = nil
|
||||
|
||||
-- /isup 8.8.8.8:53
|
||||
if ip then
|
||||
port = port or '80'
|
||||
result = isup:is_up_socket(ip, port)
|
||||
else
|
||||
result = isup:is_up_http(url)
|
||||
end
|
||||
return result
|
||||
end
|
||||
|
||||
function isup:action(msg, config)
|
||||
if isup:isup(matches[1]) then
|
||||
utilities.send_reply(self, msg, matches[1]..' ist UP! ✅')
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, matches[1]..' ist DOWN! ❌')
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return isup
|
52
miku/plugins/leave_group.lua
Normal file
52
miku/plugins/leave_group.lua
Normal file
@ -0,0 +1,52 @@
|
||||
local leave_group = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
leave_group.triggers = {
|
||||
'/nil'
|
||||
}
|
||||
|
||||
local report_to_admin = true -- set to false to not be notified, when Bot leaves groups without you
|
||||
|
||||
function leave_group:check_for_admin(msg, self, config)
|
||||
local result = bindings.request(self, 'getChatMember', {
|
||||
chat_id = msg.chat.id,
|
||||
user_id = config.admin
|
||||
} )
|
||||
if not result.ok then
|
||||
print('Konnte nicht prüfen, ob Admin in Gruppe ist! Verlasse sie sicherheitshalber...')
|
||||
return false
|
||||
end
|
||||
if result.result.status ~= "member" and result.result.status ~= "administrator" and result.result.status ~= "creator" then
|
||||
return false
|
||||
else
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
function leave_group:pre_process(msg, self, config)
|
||||
if msg.group_chat_created or msg.new_chat_member then
|
||||
local admin_in_group = leave_group:check_for_admin(msg, self, config)
|
||||
if not admin_in_group then
|
||||
print('Admin ist nicht in der Gruppe, verlasse sie deshalb...')
|
||||
utilities.send_reply(self, msg, 'Dieser Bot wurde in eine fremde Gruppe hinzugefügt. Dies wird gemeldet!\nThis bot was added to foreign group. This incident will be reported!')
|
||||
local result = bindings.request(self, 'leaveChat', {
|
||||
chat_id = msg.chat.id
|
||||
} )
|
||||
local chat_name = msg.chat.title
|
||||
local chat_id = msg.chat.id
|
||||
local from = msg.from.name
|
||||
local from_id = msg.from.id
|
||||
if report_to_admin then
|
||||
utilities.send_message(self, config.admin, '#WARNUNG: Bot wurde in fremde Gruppe hinzugefügt:\nGruppenname: '..chat_name..' ('..chat_id..')\nHinzugefügt von: '..from..' ('..from_id..')')
|
||||
end
|
||||
end
|
||||
end
|
||||
return msg
|
||||
end
|
||||
|
||||
function leave_group:action(msg)
|
||||
end
|
||||
|
||||
return leave_group
|
69
miku/plugins/location_manager.lua
Normal file
69
miku/plugins/location_manager.lua
Normal file
@ -0,0 +1,69 @@
|
||||
local loc_manager = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
function loc_manager:init(config)
|
||||
loc_manager.triggers = {
|
||||
"^/location (set) (.*)$",
|
||||
"^/location (del)$",
|
||||
"^/location$"
|
||||
}
|
||||
loc_manager.doc = [[*
|
||||
]]..config.cmd_pat..[[location*: Gibt deinen gesetzten Wohnort aus
|
||||
*]]..config.cmd_pat..[[location* _set_ _<Ort>_: Setzt deinen Wohnort auf diesen Ort
|
||||
*]]..config.cmd_pat..[[location* _del_: Löscht deinen angegebenen Wohnort
|
||||
]]
|
||||
end
|
||||
|
||||
loc_manager.command = 'location'
|
||||
|
||||
function loc_manager:set_location(user_id, location)
|
||||
local hash = 'user:'..user_id
|
||||
local set_location = get_location(user_id)
|
||||
if set_location == location then
|
||||
return 'Dieser Ort wurde bereits gesetzt.'
|
||||
else
|
||||
print('Setting location in redis hash '..hash..' to location')
|
||||
redis:hset(hash, 'location', location)
|
||||
return 'Dein Wohnort wurde auf *'..location..'* festgelegt.'
|
||||
end
|
||||
end
|
||||
|
||||
function loc_manager:del_location(user_id)
|
||||
local hash = 'user:'..user_id
|
||||
local set_location = get_location(user_id)
|
||||
if not set_location then
|
||||
return 'Du hast keinen Ort gesetzt'
|
||||
else
|
||||
print('Setting location in redis hash '..hash..' to false')
|
||||
-- We set the location to false, because deleting the value blocks redis for a few milliseconds
|
||||
redis:hset(hash, 'location', false)
|
||||
return 'Dein Wohnort *'..set_location..'* wurde gelöscht!'
|
||||
end
|
||||
end
|
||||
|
||||
function loc_manager:action(msg, config, matches)
|
||||
local user_id = msg.from.id
|
||||
|
||||
if matches[1] == 'set' then
|
||||
utilities.send_reply(self, msg, loc_manager:set_location(user_id, matches[2]), true)
|
||||
return
|
||||
elseif matches[1] == 'del' then
|
||||
utilities.send_reply(self, msg, loc_manager:del_location(user_id), true)
|
||||
return
|
||||
else
|
||||
local set_location = get_location(user_id)
|
||||
if not set_location then
|
||||
utilities.send_reply(self, msg, '*Du hast keinen Ort gesetzt!*', true)
|
||||
return
|
||||
else
|
||||
local coords = utilities.get_coords(set_location, config)
|
||||
utilities.send_location(self, msg.chat.id, coords.lat, coords.lon, msg.message_id)
|
||||
utilities.send_reply(self, msg, 'Gesetzter Wohnort: *'..set_location..'*', true)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return loc_manager
|
53
miku/plugins/luarun.lua
Normal file
53
miku/plugins/luarun.lua
Normal file
@ -0,0 +1,53 @@
|
||||
local luarun = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local URL = require('socket.url')
|
||||
local JSON = require('dkjson')
|
||||
|
||||
function luarun:init(config)
|
||||
luarun.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('lua', true):t('return', true).table
|
||||
end
|
||||
|
||||
function luarun:action(msg, config)
|
||||
|
||||
if msg.from.id ~= config.admin then
|
||||
return true
|
||||
end
|
||||
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
utilities.send_reply(self, msg, 'Please enter a string to load.')
|
||||
return
|
||||
end
|
||||
|
||||
if msg.text_lower:match('^'..config.cmd_pat..'return') then
|
||||
input = 'return ' .. input
|
||||
end
|
||||
|
||||
local output = loadstring( [[
|
||||
local bot = require('miku.bot')
|
||||
local bindings = require('miku.bindings')
|
||||
local utilities = require('miku.utilities')
|
||||
local JSON = require('dkjson')
|
||||
local URL = require('socket.url')
|
||||
local HTTP = require('socket.http')
|
||||
local HTTPS = require('ssl.https')
|
||||
return function (self, msg, config) ]] .. input .. [[ end
|
||||
]] )()(self, msg, config)
|
||||
if output == nil then
|
||||
output = 'Done!'
|
||||
else
|
||||
if type(output) == 'table' then
|
||||
local s = JSON.encode(output, {indent=true})
|
||||
if URL.escape(s):len() < 4000 then
|
||||
output = s
|
||||
end
|
||||
end
|
||||
output = '```\n' .. tostring(output) .. '\n```'
|
||||
end
|
||||
utilities.send_message(self, msg.chat.id, output, true, msg.message_id, true)
|
||||
|
||||
end
|
||||
|
||||
return luarun
|
||||
|
51
miku/plugins/lyrics.lua
Normal file
51
miku/plugins/lyrics.lua
Normal file
@ -0,0 +1,51 @@
|
||||
local lyrics = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function lyrics:init(config)
|
||||
if not cred_data.lyricsnmusic_apikey then
|
||||
print('Missing config value: lyricsnmusic_apikey.')
|
||||
print('lyrics.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
lyrics.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('lyrics', true).table
|
||||
lyrics.doc = [[*
|
||||
]]..config.cmd_pat..[[lyrics* _<Lied>_: Postet Liedertext]]
|
||||
end
|
||||
|
||||
lyrics.command = 'lyrics <Lied>'
|
||||
|
||||
function lyrics:getLyrics(text)
|
||||
local apikey = cred_data.lyricsnmusic_apikey
|
||||
local q = url_encode(text)
|
||||
local b = http.request("http://api.lyricsnmusic.com/songs?api_key="..apikey.."&q=" .. q)
|
||||
response = json.decode(b)
|
||||
local reply = ""
|
||||
if #response > 0 then
|
||||
-- grab first match
|
||||
local result = response[1]
|
||||
reply = result.title .. " - " .. result.artist.name .. "\n" .. result.snippet .. "\n[Ganzen Liedertext ansehen](" .. result.url .. ")"
|
||||
else
|
||||
reply = nil
|
||||
end
|
||||
return reply
|
||||
end
|
||||
|
||||
function lyrics:action(msg, config, matches)
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
if msg.reply_to_message and msg.reply_to_message.text then
|
||||
input = msg.reply_to_message.text
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, lyrics.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
utilities.send_reply(self, msg, lyrics:getLyrics(input), true)
|
||||
end
|
||||
|
||||
return lyrics
|
23
miku/plugins/magische_miesmuschel.lua
Normal file
23
miku/plugins/magische_miesmuschel.lua
Normal file
@ -0,0 +1,23 @@
|
||||
local muschel = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
muschel.triggers = {
|
||||
"^[Mm][Aa][Gg][Ii][Ss][Cc][Hh][Ee] [Mm][Ii][Ee][Ss][Mm][Uu][Ss][Cc][Hh][Ee][Ll], (.*)$"
|
||||
}
|
||||
|
||||
function muschel:frag_die_muschel()
|
||||
local possibilities = {
|
||||
"Ja",
|
||||
"Nein",
|
||||
"Eines Tages vielleicht"
|
||||
}
|
||||
local random = math.random(3)
|
||||
return possibilities[random]
|
||||
end
|
||||
|
||||
function muschel:action(msg, config, matches)
|
||||
utilities.send_reply(self, msg, muschel:frag_die_muschel())
|
||||
end
|
||||
|
||||
return muschel
|
58
miku/plugins/media.lua
Normal file
58
miku/plugins/media.lua
Normal file
@ -0,0 +1,58 @@
|
||||
local media = {}
|
||||
|
||||
local HTTP = require('socket.http')
|
||||
local HTTPS = require('ssl.https')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
local utilities = require('miku.utilities')
|
||||
local mimetype = (loadfile "./miku/mimetype.lua")()
|
||||
|
||||
media.triggers = {
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(gif))$",
|
||||
"^(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(mp4))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(pdf))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(ogg))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(zip))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(tar.gz))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(7z))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(mp3))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(rar))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(wmv))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(doc))$",
|
||||
"^(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(avi))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(wav))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(apk))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(webm))$",
|
||||
"^(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(ogv))$",
|
||||
"(https?://[%w-_%.%?%.:,/%+=&%[%]]+%.(webp))$"
|
||||
}
|
||||
|
||||
function media:action(msg)
|
||||
local url = matches[1]
|
||||
local ext = matches[2]
|
||||
local receiver = msg.chat.id
|
||||
|
||||
local file, last_modified, nocache = get_cached_file(url, nil, msg.chat.id, 'upload_document', self)
|
||||
local mime_type = mimetype.get_content_type_no_sub(ext)
|
||||
|
||||
if ext == 'gif' then
|
||||
print('send gif')
|
||||
result = utilities.send_document(self, receiver, file, nil, msg.message_id)
|
||||
elseif mime_type == 'audio' then
|
||||
print('send_audio')
|
||||
result = utilities.send_audio(self, receiver, file, nil, msg.message_id)
|
||||
elseif mime_type == 'video' then
|
||||
print('send_video')
|
||||
result = utilities.send_video(self, receiver, file, nil, msg.message_id)
|
||||
else
|
||||
print('send_file')
|
||||
result = utilities.send_document(self, receiver, file, nil, msg.message_id)
|
||||
end
|
||||
|
||||
if nocache then return end
|
||||
if not result then return end
|
||||
|
||||
-- Cache File-ID und Last-Modified-Header in Redis
|
||||
cache_file(result, url, last_modified)
|
||||
end
|
||||
|
||||
return media
|
86
miku/plugins/minecraft_server.lua
Normal file
86
miku/plugins/minecraft_server.lua
Normal file
@ -0,0 +1,86 @@
|
||||
local mc_server = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local ltn12 = require('ltn12')
|
||||
local URL = require('socket.url')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function mc_server:init(config)
|
||||
mc_server.triggers = {
|
||||
"^/mine (.*)$"
|
||||
}
|
||||
mc_server.doc = [[*
|
||||
]]..config.cmd_pat..[[mine* _<IP>_: Sucht Minecraft-Server und sendet Infos. Standard-Port: 25565
|
||||
*]]..config.cmd_pat..[[mine* _<IP>_ _<Port>_: Sucht Minecraft-Server auf Port und sendet Infos.
|
||||
]]
|
||||
end
|
||||
|
||||
mc_server.command = "mine <IP> [Port]"
|
||||
|
||||
function mc_server:mineSearch(ip, port)
|
||||
local responseText = ""
|
||||
local api = "https://mcapi.us/server/status"
|
||||
local parameters = "?ip="..(URL.escape(ip) or "").."&port="..(URL.escape(port) or "").."&players=true"
|
||||
local respbody = {}
|
||||
local body, code, headers, status = http.request{
|
||||
url = api..parameters,
|
||||
method = "GET",
|
||||
redirect = true,
|
||||
sink = ltn12.sink.table(respbody)
|
||||
}
|
||||
local body = table.concat(respbody)
|
||||
if (status == nil) then return "FEHLER: status = nil" end
|
||||
if code ~=200 then return "FEHLER: "..code..". Status: "..status end
|
||||
local jsonData = json.decode(body)
|
||||
responseText = responseText..ip..":"..port..":\n"
|
||||
if (jsonData.motd ~= nil and jsonData.motd ~= '') then
|
||||
local tempMotd = ""
|
||||
tempMotd = jsonData.motd:gsub('%ยง.', '')
|
||||
if (jsonData.motd ~= nil) then responseText = responseText.."*MOTD*: "..tempMotd.."\n" end
|
||||
end
|
||||
if (jsonData.online ~= nil) then
|
||||
if jsonData.online == true then
|
||||
server_online = "Ja"
|
||||
else
|
||||
server_online = "Nein"
|
||||
end
|
||||
responseText = responseText.."*Online*: "..server_online.."\n"
|
||||
end
|
||||
if (jsonData.players ~= nil) then
|
||||
if (jsonData.players.max ~= nil and jsonData.players.max ~= 0) then
|
||||
responseText = responseText.."*Slots*: "..jsonData.players.max.."\n"
|
||||
end
|
||||
if (jsonData.players.now ~= nil and jsonData.players.max ~= 0) then
|
||||
responseText = responseText.."*Spieler online*: "..jsonData.players.now.."\n"
|
||||
end
|
||||
if (jsonData.players.sample ~= nil and jsonData.players.sample ~= false) then
|
||||
responseText = responseText.."*Spieler*: "..table.concat(jsonData.players.sample, ", ").."\n"
|
||||
end
|
||||
if (jsonData.server.name ~= nil and jsonData.server.name ~= "") then
|
||||
responseText = responseText.."*Server*: "..jsonData.server.name.."\n"
|
||||
end
|
||||
end
|
||||
return responseText
|
||||
end
|
||||
|
||||
function mc_server:parseText(text, mc_server)
|
||||
if (text == nil or text == "/mine") then
|
||||
return mc_server.doc
|
||||
end
|
||||
ip, port = string.match(text, "^/mine (.-) (.*)$")
|
||||
if (ip ~= nil and port ~= nil) then
|
||||
return mc_server:mineSearch(ip, port)
|
||||
end
|
||||
local ip = string.match(text, "^/mine (.*)$")
|
||||
if (ip ~= nil) then
|
||||
return mc_server:mineSearch(ip, "25565")
|
||||
end
|
||||
return "FEHLER: Keine Input IP!"
|
||||
end
|
||||
|
||||
function mc_server:action(msg, config, matches)
|
||||
utilities.send_reply(self, msg, mc_server:parseText(msg.text, mc_server), true)
|
||||
end
|
||||
|
||||
return mc_server
|
31
miku/plugins/minecraft_skin.lua
Normal file
31
miku/plugins/minecraft_skin.lua
Normal file
@ -0,0 +1,31 @@
|
||||
local mc_skin = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function mc_skin:init(config)
|
||||
mc_skin.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('skin', true).table
|
||||
mc_skin.doc = [[*
|
||||
]]..config.cmd_pat..[[skin* _<Username>_: Sendet Minecraft-Skin dieses Nutzers]]
|
||||
end
|
||||
|
||||
mc_skin.command = 'skin <Username>'
|
||||
|
||||
local BASE_URL = 'http://ip-api.com/json'
|
||||
|
||||
function mc_skin:action(msg, config, matches)
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
if msg.reply_to_message and msg.reply_to_message.text then
|
||||
input = msg.reply_to_message.text
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, mc_skin.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local url = 'http://www.minecraft-skin-viewer.net/3d.php?layers=true&aa=true&a=0&w=330&wt=10&abg=330&abd=40&ajg=340&ajd=20&ratio=13&format=png&login='..input..'&headOnly=false&displayHairs=true&randomness=341.png'
|
||||
local file = download_to_file(url)
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
|
||||
return mc_skin
|
228
miku/plugins/myanimelist.lua
Normal file
228
miku/plugins/myanimelist.lua
Normal file
@ -0,0 +1,228 @@
|
||||
local mal = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local URL = require('socket.url')
|
||||
local xml = require("xml")
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
mal.command = 'anime <Anime>, /manga <Manga>'
|
||||
|
||||
function mal:init(config)
|
||||
if not cred_data.mal_user then
|
||||
print('Missing config value: mal_user.')
|
||||
print('myanimelist.lua will not be enabled.')
|
||||
return
|
||||
elseif not cred_data.mal_pw then
|
||||
print('Missing config value: mal_pw.')
|
||||
print('myanimelist.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
mal.triggers = {
|
||||
"^/(anime) (.+)$",
|
||||
"^/(manga) (.+)$"
|
||||
}
|
||||
mal.doc = [[*
|
||||
]]..config.cmd_pat..[[anime*_ <Anime>_: Sendet Infos zum Anime
|
||||
*]]..config.cmd_pat..[[manga*_ <Manga>_: Sendet Infos zum Manga
|
||||
]]
|
||||
end
|
||||
|
||||
local user = cred_data.mal_user
|
||||
local password = cred_data.mal_pw
|
||||
|
||||
local BASE_URL = 'http://'..user..':'..password..'@myanimelist.net/api'
|
||||
|
||||
function mal:delete_tags(str)
|
||||
str = string.gsub( str, '<br />', '')
|
||||
str = string.gsub( str, '%[i%]', '')
|
||||
str = string.gsub( str, '%[/i%]', '')
|
||||
str = string.gsub( str, '—', ' — ')
|
||||
return str
|
||||
end
|
||||
|
||||
local makeOurDate = function(dateString)
|
||||
local pattern = "(%d+)%-(%d+)%-(%d+)"
|
||||
local year, month, day = dateString:match(pattern)
|
||||
return day..'.'..month..'.'..year
|
||||
end
|
||||
|
||||
function mal:get_mal_info(query, typ)
|
||||
if typ == 'anime' then
|
||||
url = BASE_URL..'/anime/search.xml?q='..query
|
||||
elseif typ == 'manga' then
|
||||
url = BASE_URL..'/manga/search.xml?q='..query
|
||||
end
|
||||
local res,code = http.request(url)
|
||||
if code ~= 200 then return "HTTP-Fehler" end
|
||||
local result = xml.load(res)
|
||||
return result
|
||||
end
|
||||
|
||||
function mal:send_anime_data(result, receiver)
|
||||
local title = xml.find(result, 'title')[1]
|
||||
local id = xml.find(result, 'id')[1]
|
||||
local mal_url = 'http://myanimelist.net/anime/'..id
|
||||
|
||||
if xml.find(result, 'synonyms')[1] then
|
||||
alt_name = '\noder: '..unescape(mal:delete_tags(xml.find(result, 'synonyms')[1]))
|
||||
else
|
||||
alt_name = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'synopsis')[1] then
|
||||
desc = '\n'..unescape(mal:delete_tags(string.sub(xml.find(result, 'synopsis')[1], 1, 200))) .. '...'
|
||||
else
|
||||
desc = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'episodes')[1] then
|
||||
episodes = '\nEpisoden: '..xml.find(result, 'episodes')[1]
|
||||
else
|
||||
episodes = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'status')[1] then
|
||||
status = ' ('..xml.find(result, 'status')[1]..')'
|
||||
else
|
||||
status = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'score')[1] ~= "0.00" then
|
||||
score = '\nScore: '..string.gsub(xml.find(result, 'score')[1], "%.", ",")
|
||||
else
|
||||
score = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'type')[1] then
|
||||
typ = '\nTyp: '..xml.find(result, 'type')[1]
|
||||
else
|
||||
typ = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'start_date')[1] ~= "0000-00-00" then
|
||||
startdate = '\nVeröffentlichungszeitraum: '..makeOurDate(xml.find(result, 'start_date')[1])
|
||||
else
|
||||
startdate = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'end_date')[1] ~= "0000-00-00" then
|
||||
enddate = ' - '..makeOurDate(xml.find(result, 'end_date')[1])
|
||||
else
|
||||
enddate = ''
|
||||
end
|
||||
|
||||
local text = '*'..title..'*'..alt_name..typ..episodes..status..score..startdate..enddate..'_'..desc..'_\n[Auf MyAnimeList ansehen]('..mal_url..')'
|
||||
if xml.find(result, 'image') then
|
||||
local image_url = xml.find(result, 'image')[1]
|
||||
return text, image_url
|
||||
else
|
||||
return text
|
||||
end
|
||||
end
|
||||
|
||||
function mal:send_manga_data(result)
|
||||
local title = xml.find(result, 'title')[1]
|
||||
local id = xml.find(result, 'id')[1]
|
||||
local mal_url = 'http://myanimelist.net/manga/'..id
|
||||
|
||||
if xml.find(result, 'type')[1] then
|
||||
typ = ' ('..xml.find(result, 'type')[1]..')'
|
||||
else
|
||||
typ = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'synonyms')[1] then
|
||||
alt_name = '\noder: '..unescape(mal:delete_tags(xml.find(result, 'synonyms')[1]))
|
||||
else
|
||||
alt_name = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'chapters')[1] then
|
||||
chapters = '\nKapitel: '..xml.find(result, 'chapters')[1]
|
||||
else
|
||||
chapters = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'status')[1] then
|
||||
status = ' ('..xml.find(result, 'status')[1]..')'
|
||||
else
|
||||
status = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'volumes')[1] then
|
||||
volumes = '\nBände '..xml.find(result, 'volumes')[1]
|
||||
else
|
||||
volumes = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'score')[1] ~= "0.00" then
|
||||
score = '\nScore: '..xml.find(result, 'score')[1]
|
||||
else
|
||||
score = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'start_date')[1] ~= "0000-00-00" then
|
||||
startdate = '\nVeröffentlichungszeitraum: '..makeOurDate(xml.find(result, 'start_date')[1])
|
||||
else
|
||||
startdate = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'end_date')[1] ~= "0000-00-00" then
|
||||
enddate = ' - '..makeOurDate(xml.find(result, 'end_date')[1])
|
||||
else
|
||||
enddate = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'synopsis')[1] then
|
||||
desc = '\n'..unescape(mal:delete_tags(string.sub(xml.find(result, 'synopsis')[1], 1, 200))) .. '...'
|
||||
else
|
||||
desc = ''
|
||||
end
|
||||
|
||||
local text = '*'..title..'*'..alt_name..typ..chapters..status..volumes..score..startdate..enddate..'_'..desc..'_\n[Auf MyAnimeList ansehen]('..mal_url..')'
|
||||
if xml.find(result, 'image') then
|
||||
local image_url = xml.find(result, 'image')[1]
|
||||
return text, image_url
|
||||
else
|
||||
return text
|
||||
end
|
||||
end
|
||||
|
||||
function mal:action(msg, config, matches)
|
||||
local query = URL.escape(matches[2])
|
||||
if matches[1] == 'anime' then
|
||||
local anime_info = mal:get_mal_info(query, 'anime')
|
||||
if anime_info == "HTTP-Fehler" then
|
||||
utilities.send_reply(self, msg, 'Anime nicht gefunden!')
|
||||
return
|
||||
else
|
||||
local text, image_url = mal:send_anime_data(anime_info)
|
||||
if image_url then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(image_url)
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
return
|
||||
end
|
||||
elseif matches[1] == 'manga' then
|
||||
local manga_info = mal:get_mal_info(query, 'manga')
|
||||
if manga_info == "HTTP-Fehler" then
|
||||
utilities.send_reply(self, msg, 'Manga nicht gefunden!')
|
||||
return
|
||||
else
|
||||
local text, image_url = mal:send_manga_data(manga_info)
|
||||
if image_url then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(image_url)
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return mal
|
103
miku/plugins/notify.lua
Normal file
103
miku/plugins/notify.lua
Normal file
@ -0,0 +1,103 @@
|
||||
-- INFO: Stats must be activated, so that it can collect all members of a group and save his/her id to redis.
|
||||
-- You can deactivate it afterwards.
|
||||
|
||||
local notify = {}
|
||||
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function notify:init(config)
|
||||
notify.triggers = {
|
||||
"^/notify (del)$",
|
||||
"^/notify$"
|
||||
}
|
||||
|
||||
notify.doc = [[*
|
||||
]]..config.cmd_pat..[[notify* (del): Benachrichtigt dich privat, wenn du erwähnt wirst (bzw. schaltet das Feature wieder aus)]]
|
||||
end
|
||||
|
||||
notify.command = 'notify [del]'
|
||||
|
||||
-- See https://stackoverflow.com/a/32854917
|
||||
function isWordFoundInString(word,input)
|
||||
return select(2,input:gsub('^' .. word .. '%W+','')) +
|
||||
select(2,input:gsub('%W+' .. word .. '$','')) +
|
||||
select(2,input:gsub('^' .. word .. '$','')) +
|
||||
select(2,input:gsub('%W+' .. word .. '%W+','')) > 0
|
||||
end
|
||||
|
||||
function notify:pre_process(msg, self)
|
||||
local notify_users = redis:smembers('notify:ls')
|
||||
|
||||
-- I call this beautiful lady the "if soup"
|
||||
if msg.chat.type == 'chat' or msg.chat.type == 'supergroup' then
|
||||
if msg.text then
|
||||
for _,user in pairs(notify_users) do
|
||||
if isWordFoundInString('@'..user, string.lower(msg.text)) then
|
||||
local chat_id = msg.chat.id
|
||||
local id = redis:hget('notify:'..user, 'id')
|
||||
-- check, if user has sent at least one message to the group,
|
||||
-- so that we don't send the user some private text, when he/she is not
|
||||
-- in the group.
|
||||
if redis:sismember('chat:'..chat_id..':users', id) then
|
||||
|
||||
-- ignore message, if user is mentioning him/herself
|
||||
if id == tostring(msg.from.id) then break; end
|
||||
|
||||
local send_date = run_command('date -d @'..msg.date..' +"%d.%m.%Y um %H:%M:%S Uhr"')
|
||||
local send_date = string.gsub(send_date, "\n", "")
|
||||
local from = string.gsub(msg.from.name, "%_", " ")
|
||||
local chat_name = string.gsub(msg.chat.title, "%_", " ")
|
||||
local text = from..' am '..send_date..' in "'..chat_name..'":\n\n'..msg.text
|
||||
utilities.send_message(self, id, text)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return msg
|
||||
end
|
||||
|
||||
function notify:action(msg, config, matches)
|
||||
if not msg.from.username then
|
||||
utilities.send_reply(self, msg, 'Du hast keinen Usernamen und kannst daher dieses Feature nicht nutzen. Tut mir leid!' )
|
||||
return
|
||||
end
|
||||
|
||||
local username = string.lower(msg.from.username)
|
||||
|
||||
local hash = 'notify:'..username
|
||||
|
||||
if matches[1] == "del" then
|
||||
if not redis:sismember('notify:ls', username) then
|
||||
utilities.send_reply(self, msg, 'Du wirst noch gar nicht benachrichtigt!')
|
||||
return
|
||||
end
|
||||
print('Setting notify in redis hash '..hash..' to false')
|
||||
redis:hset(hash, 'notify', false)
|
||||
print('Removing '..username..' from redis set notify:ls')
|
||||
redis:srem('notify:ls', username)
|
||||
utilities.send_reply(self, msg, 'Du erhälst jetzt keine Benachrichtigungen mehr, wenn du angesprochen wirst.')
|
||||
return
|
||||
else
|
||||
if redis:sismember('notify:ls', username) then
|
||||
utilities.send_reply(self, msg, 'Du wirst schon benachrichtigt!')
|
||||
return
|
||||
end
|
||||
print('Setting notify in redis hash '..hash..' to true')
|
||||
redis:hset(hash, 'notify', true)
|
||||
print('Setting id in redis hash '..hash..' to '..msg.from.id)
|
||||
redis:hset(hash, 'id', msg.from.id)
|
||||
print('Adding '..username..' to redis set notify:ls')
|
||||
redis:sadd('notify:ls', username)
|
||||
local res = utilities.send_message(self, msg.from.id, 'Du erhälst jetzt Benachrichtigungen, wenn du angesprochen wirst, nutze `/notify del` zum Deaktivieren.', true, nil, true)
|
||||
if not res then
|
||||
utilities.send_reply(self, msg, 'Bitte schreibe mir [privat](http://telegram.me/' .. self.info.username .. '?start=notify), um den Vorgang abzuschließen.', true)
|
||||
elseif msg.chat.type ~= 'private' then
|
||||
utilities.send_reply(self, msg, 'Du erhälst jetzt Benachrichtigungen, wenn du angesprochen wirst, nutze `/notify del` zum Deaktivieren.', true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return notify
|
39
miku/plugins/pagespeed_insights.lua
Normal file
39
miku/plugins/pagespeed_insights.lua
Normal file
@ -0,0 +1,39 @@
|
||||
local pagespeed_insights = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function pagespeed_insights:init(config)
|
||||
if not cred_data.google_apikey then
|
||||
print('Missing config value: google_apikey.')
|
||||
print('pagespeed_insights.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
pagespeed_insights.triggers = {
|
||||
"^/speed (https?://[%w-_%.%?%.:/%+=&]+)"
|
||||
}
|
||||
pagespeed_insights.doc = [[*
|
||||
]]..config.cmd_pat..[[speed* _<Seiten-URL>_: Testet Geschwindigkeit der Seite mit PageSpeed Insights]]
|
||||
end
|
||||
|
||||
local BASE_URL = 'https://www.googleapis.com/pagespeedonline/v2'
|
||||
|
||||
function pagespeed_insights:get_pagespeed(test_url)
|
||||
local apikey = cred_data.google_apikey
|
||||
local url = BASE_URL..'/runPagespeed?url='..test_url..'&key='..apikey..'&fields=id,ruleGroups(SPEED(score))'
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return "HTTP-FEHLER" end
|
||||
local data = json.decode(res)
|
||||
return data.id..' hat einen PageSpeed-Score von *'..data.ruleGroups.SPEED.score..' Punkten.*'
|
||||
end
|
||||
|
||||
function pagespeed_insights:action(msg, config, matches)
|
||||
utilities.send_typing(self, msg.chat.id, 'typing')
|
||||
local text = pagespeed_insights:get_pagespeed(matches[1])
|
||||
if not text then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
|
||||
return pagespeed_insights
|
45
miku/plugins/pasteee.lua
Normal file
45
miku/plugins/pasteee.lua
Normal file
@ -0,0 +1,45 @@
|
||||
local pasteee = {}
|
||||
|
||||
local bot = require('miku.bot')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function pasteee:init(config)
|
||||
if not cred_data.pasteee_key then
|
||||
print('Missing config value: pasteee_key.')
|
||||
print('pasteee.lua will not be enabled, listquotes won\'t be available.')
|
||||
return
|
||||
end
|
||||
|
||||
pasteee.triggers = {
|
||||
"^/pasteee (.*)$"
|
||||
}
|
||||
pasteee.doc = [[*
|
||||
]]..config.cmd_pat..[[pasteee* _<Text>_: Postet Text auf Paste.ee]]
|
||||
end
|
||||
|
||||
pasteee.command = 'pasteee <Text>'
|
||||
|
||||
local key = cred_data.pasteee_key
|
||||
|
||||
function upload(text, noraw)
|
||||
local url = "https://paste.ee/api"
|
||||
local pet = post_petition(url, 'key='..key..'&paste='..text..'&format=json')
|
||||
if pet.status ~= 'success' then return 'Ein Fehler ist aufgetreten: '..pet.error, true end
|
||||
if noraw then
|
||||
return pet.paste.link
|
||||
else
|
||||
return pet.paste.raw
|
||||
end
|
||||
end
|
||||
|
||||
function pasteee:action(msg, config, matches)
|
||||
local text = matches[1]
|
||||
local link, iserror = upload(text)
|
||||
if iserror then
|
||||
utilities.send_reply(self, msg, link)
|
||||
return
|
||||
end
|
||||
utilities.send_reply(self, msg, '[Text auf Paste.ee ansehen]('..link..')', true)
|
||||
end
|
||||
|
||||
return pasteee
|
120
miku/plugins/pixabay.lua
Normal file
120
miku/plugins/pixabay.lua
Normal file
@ -0,0 +1,120 @@
|
||||
local pixabay = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
function pixabay:init(config)
|
||||
if not cred_data.pixabay_apikey then
|
||||
print('Missing config value: pixabay_apikey.')
|
||||
print('pixabay.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
pixabay.triggers = {
|
||||
"^/pix(id) (%d+)",
|
||||
"^/pix (.*)$",
|
||||
"(pixabay.com).*%-(%d+)"
|
||||
}
|
||||
pixabay.doc = [[*
|
||||
]]..config.cmd_pat..[[pix* _<Suchbegriff>_: Sendet lizenzfreies Bild]]
|
||||
end
|
||||
|
||||
pixabay.command = 'pix <Suchbegriff>'
|
||||
|
||||
local BASE_URL = 'https://pixabay.com/api'
|
||||
local apikey = cred_data.pixabay_apikey
|
||||
|
||||
function pixabay:get_pixabay_directlink(id)
|
||||
local url = BASE_URL..'/?key='..apikey..'&lang=de&id='..id
|
||||
local b,c = https.request(url)
|
||||
if c ~= 200 then return nil end
|
||||
local data = json.decode(b)
|
||||
if data.totalHits == 0 then return 'NOPIX' end
|
||||
|
||||
local webformatURL = data.hits[1].webformatURL
|
||||
local image_url = string.gsub(webformatURL, '_640.jpg', '_960.jpg')
|
||||
|
||||
-- Link to full, high resolution image
|
||||
local preview_url = data.hits[1].previewURL
|
||||
local image_code = string.sub(preview_url, 59)
|
||||
local image_code = string.sub(image_code, 0, -9)
|
||||
local full_url = 'https://pixabay.com/de/photos/download/'..image_code..'.jpg'
|
||||
|
||||
local user = data.hits[1].user
|
||||
local tags = data.hits[1].tags
|
||||
local page_url = data.hits[1].pageURL
|
||||
|
||||
-- cache this shit
|
||||
local hash = 'telegram:cache:pixabay:'..id
|
||||
print('Caching data in '..hash..' with timeout 1209600')
|
||||
redis:hset(hash, 'image_url', image_url)
|
||||
redis:hset(hash, 'full_url', full_url)
|
||||
redis:hset(hash, 'page_url', page_url)
|
||||
redis:hset(hash, 'user', user)
|
||||
redis:hset(hash, 'tags', tags)
|
||||
redis:expire(hash, 1209600) -- 1209600 = two weeks
|
||||
|
||||
return image_url, full_url, page_url, user, tags
|
||||
end
|
||||
|
||||
function pixabay:get_pixabay(term)
|
||||
local count = 70 -- how many pictures should be returned (3 to 200) NOTE: more pictures = higher load time
|
||||
local url = BASE_URL..'/?key='..apikey..'&lang=de&safesearch=true&per_page='..count..'&image_type=photo&q='..term
|
||||
local b,c = https.request(url)
|
||||
if c ~= 200 then return nil end
|
||||
local photo = json.decode(b)
|
||||
if photo.totalHits == 0 then return 'NOPIX' end
|
||||
local photos = photo.hits
|
||||
-- truly randomize
|
||||
math.randomseed(os.time())
|
||||
-- random max json table size
|
||||
local i = math.random(#photos)
|
||||
|
||||
local webformatURL = photos[i].webformatURL
|
||||
local image_url = string.gsub(webformatURL, '_640.jpg', '_960.jpg')
|
||||
|
||||
-- Link to full, high resolution image
|
||||
local preview_url = photos[i].previewURL
|
||||
local image_code = string.sub(preview_url, 59)
|
||||
local image_code = string.sub(image_code, 0, -9)
|
||||
local full_url = 'https://pixabay.com/de/photos/download/'..image_code..'.jpg'
|
||||
|
||||
local user = photos[i].user
|
||||
local tags = photos[i].tags
|
||||
local page_url = photos[i].pageURL
|
||||
|
||||
return image_url, full_url, page_url, user, tags
|
||||
end
|
||||
|
||||
function pixabay:action(msg, config, matches)
|
||||
local term = matches[1]
|
||||
if matches[2] then
|
||||
if redis:exists("telegram:cache:pixabay:"..matches[2]) == true then -- if cached
|
||||
local hash = 'telegram:cache:pixabay:'..matches[2]
|
||||
url = redis:hget(hash, 'image_url')
|
||||
full_url = redis:hget(hash, 'full_url')
|
||||
page_url = redis:hget(hash, 'page_url')
|
||||
user = redis:hget(hash, 'user')
|
||||
tags = redis:hget(hash, 'tags')
|
||||
else
|
||||
url, full_url, page_url, user, tags = pixabay:get_pixabay_directlink(matches[2])
|
||||
end
|
||||
else
|
||||
url, full_url, page_url, user, tags = pixabay:get_pixabay(term)
|
||||
end
|
||||
|
||||
if url == 'NOPIX' then
|
||||
utilities.send_reply(self, msg, config.errors.results)
|
||||
return
|
||||
else
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(url)
|
||||
local text = '"'..tags..'" von '..user
|
||||
utilities.send_photo(self, msg.chat.id, file, text, msg.message_id, '{"inline_keyboard":[[{"text":"Seite aufrufen","url":"'..page_url..'"},{"text":"Volles Bild (Login notwendig)","url":"'..full_url..'"}]]}')
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return pixabay
|
62
miku/plugins/play_store.lua
Normal file
62
miku/plugins/play_store.lua
Normal file
@ -0,0 +1,62 @@
|
||||
local play_store = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function play_store:init(config)
|
||||
if not cred_data.x_mashape_key then
|
||||
print('Missing config value: x_mashape_key.')
|
||||
print('play_store.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
play_store.triggers = {
|
||||
"play.google.com/store/apps/details%?id=(.*)"
|
||||
}
|
||||
end
|
||||
|
||||
local BASE_URL = 'https://apps.p.mashape.com/google/application'
|
||||
|
||||
function play_store:get_playstore_data (appid)
|
||||
local apikey = cred_data.x_mashape_key
|
||||
local url = BASE_URL..'/'..appid..'?mashape-key='..apikey
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res).data
|
||||
return data
|
||||
end
|
||||
|
||||
function play_store:send_playstore_data(data)
|
||||
local title = data.title
|
||||
local developer = data.developer.id
|
||||
local category = data.category.name
|
||||
local rating = data.rating.average
|
||||
local installs = data.performance.installs
|
||||
local description = data.description
|
||||
if data.version == "Varies with device" then
|
||||
appversion = "variiert je nach Gerät"
|
||||
else
|
||||
appversion = data.version
|
||||
end
|
||||
if data.price == 0 then
|
||||
price = "Gratis"
|
||||
else
|
||||
price = data.price
|
||||
end
|
||||
local text = '*'..title..'* von *'..developer..'* aus der Kategorie _'..category..'_, durschnittlich bewertet mit '..rating..' Sternen.\n_'..description..'_\n'..installs..' Installationen, Version '..appversion
|
||||
return text
|
||||
end
|
||||
|
||||
function play_store:action(msg, config, matches)
|
||||
local appid = matches[1]
|
||||
local data = play_store:get_playstore_data(appid)
|
||||
if data == nil then
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, play_store:send_playstore_data(data), true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return play_store
|
230
miku/plugins/plugins.lua
Normal file
230
miku/plugins/plugins.lua
Normal file
@ -0,0 +1,230 @@
|
||||
local plugin_manager = {}
|
||||
|
||||
local bot = require('miku.bot')
|
||||
local bindings = require('miku.bindings')
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
function plugin_manager:init(config)
|
||||
plugin_manager.triggers = {
|
||||
"^/plugins$",
|
||||
"^/plugins? (enable) ([%w_%.%-]+)$",
|
||||
"^/plugins? (disable) ([%w_%.%-]+)$",
|
||||
"^/plugins? (enable) ([%w_%.%-]+) (chat) (%d+)",
|
||||
"^/plugins? (enable) ([%w_%.%-]+) (chat)",
|
||||
"^/plugins? (disable) ([%w_%.%-]+) (chat) (%d+)",
|
||||
"^/plugins? (disable) ([%w_%.%-]+) (chat)",
|
||||
"^/plugins? (reload)$",
|
||||
"^/(reload)$"
|
||||
}
|
||||
plugin_manager.doc = [[*
|
||||
]]..config.cmd_pat..[[plugins*: Listet alle Plugins auf
|
||||
*]]..config.cmd_pat..[[plugins* _enable/disable_ _<Plugin>_: Aktiviert/deaktiviert Plugin
|
||||
*]]..config.cmd_pat..[[plugins* _enable/disable_ _<Plugin>_ chat: Aktiviert/deaktiviert Plugin im aktuellen Chat
|
||||
*]]..config.cmd_pat..[[plugins* _enable/disable_ _<Plugin>_ _<chat#id>_: Aktiviert/deaktiviert Plugin in diesem Chat
|
||||
*]]..config.cmd_pat..[[reload*: Lädt Plugins neu]]
|
||||
end
|
||||
|
||||
plugin_manager.command = 'plugins <nur für Superuser>'
|
||||
|
||||
-- Returns the key (index) in the config.enabled_plugins table
|
||||
function plugin_manager:plugin_enabled(name, chat)
|
||||
for k,v in pairs(enabled_plugins) do
|
||||
if name == v then
|
||||
return k
|
||||
end
|
||||
end
|
||||
-- If not found
|
||||
return false
|
||||
end
|
||||
|
||||
-- Returns true if file exists in plugins folder
|
||||
function plugin_manager:plugin_exists(name)
|
||||
for k,v in pairs(plugins_names()) do
|
||||
if name..'.lua' == v then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function plugin_manager:list_plugins()
|
||||
local text = ''
|
||||
for k, v in pairs(plugins_names()) do
|
||||
-- ✔ enabled, ❌ disabled
|
||||
local status = '❌'
|
||||
-- Check if is enabled
|
||||
for k2, v2 in pairs(enabled_plugins) do
|
||||
if v == v2..'.lua' then
|
||||
status = '✔'
|
||||
end
|
||||
end
|
||||
if not only_enabled or status == '✔' then
|
||||
-- get the name
|
||||
v = string.match (v, "(.*)%.lua")
|
||||
text = text..v..' '..status..'\n'
|
||||
end
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
function plugin_manager:reload_plugins(self, config, plugin_name, status)
|
||||
for pac, _ in pairs(package.loaded) do
|
||||
if pac:match('^miku%.plugins%.') then
|
||||
package.loaded[pac] = nil
|
||||
end
|
||||
end
|
||||
package.loaded['miku.bindings'] = nil
|
||||
package.loaded['miku.utilities'] = nil
|
||||
package.loaded['config'] = nil
|
||||
bot.init(self, config)
|
||||
if plugin_name then
|
||||
return 'Plugin '..plugin_name..' wurde '..status
|
||||
else
|
||||
return 'Plugins neu geladen'
|
||||
end
|
||||
end
|
||||
|
||||
function plugin_manager:enable_plugin(self, config, plugin_name)
|
||||
print('checking if '..plugin_name..' exists')
|
||||
-- Check if plugin is enabled
|
||||
if plugin_manager:plugin_enabled(plugin_name) then
|
||||
return 'Plugin '..plugin_name..' ist schon aktiviert'
|
||||
end
|
||||
-- Checks if plugin exists
|
||||
if plugin_manager:plugin_exists(plugin_name) then
|
||||
-- Add to redis set
|
||||
redis:sadd('telegram:enabled_plugins', plugin_name)
|
||||
print(plugin_name..' saved to redis set telegram:enabled_plugins')
|
||||
-- Reload the plugins
|
||||
return plugin_manager:reload_plugins(self, config, plugin_name, 'aktiviert')
|
||||
else
|
||||
return 'Plugin '..plugin_name..' existiert nicht'
|
||||
end
|
||||
end
|
||||
|
||||
function plugin_manager:disable_plugin(self, config, name, chat)
|
||||
-- Check if plugins exists
|
||||
if not plugin_manager:plugin_exists(name) then
|
||||
return 'Plugin '..name..' existiert nicht'
|
||||
end
|
||||
local k = plugin_manager:plugin_enabled(name)
|
||||
-- Check if plugin is enabled
|
||||
if not k then
|
||||
return 'Plugin '..name..' ist nicht aktiviert'
|
||||
end
|
||||
-- Disable and reload
|
||||
redis:srem('telegram:enabled_plugins', name)
|
||||
print(name..' saved to redis set telegram:enabled_plugins')
|
||||
return plugin_manager:reload_plugins(self, config, name, 'deaktiviert')
|
||||
end
|
||||
|
||||
function plugin_manager:disable_plugin_on_chat(msg, plugin)
|
||||
if not plugin_manager:plugin_exists(plugin) then
|
||||
return "Plugin existiert nicht!"
|
||||
end
|
||||
|
||||
if not msg.chat then
|
||||
hash = 'chat:'..msg..':disabled_plugins'
|
||||
else
|
||||
hash = get_redis_hash(msg, 'disabled_plugins')
|
||||
end
|
||||
local disabled = redis:hget(hash, plugin)
|
||||
|
||||
if disabled ~= 'true' then
|
||||
print('Setting '..plugin..' in redis hash '..hash..' to true')
|
||||
redis:hset(hash, plugin, true)
|
||||
return 'Plugin '..plugin..' für diesen Chat deaktiviert.'
|
||||
else
|
||||
return 'Plugin '..plugin..' wurde für diesen Chat bereits deaktiviert.'
|
||||
end
|
||||
end
|
||||
|
||||
function plugin_manager:reenable_plugin_on_chat(msg, plugin)
|
||||
if not plugin_manager:plugin_exists(plugin) then
|
||||
return "Plugin existiert nicht!"
|
||||
end
|
||||
|
||||
if not msg.chat then
|
||||
hash = 'chat:'..msg..':disabled_plugins'
|
||||
else
|
||||
hash = get_redis_hash(msg, 'disabled_plugins')
|
||||
end
|
||||
local disabled = redis:hget(hash, plugin)
|
||||
|
||||
if disabled == nil then return 'Es gibt keine deaktivierten Plugins für disen Chat.' end
|
||||
|
||||
if disabled == 'true' then
|
||||
print('Setting '..plugin..' in redis hash '..hash..' to false')
|
||||
redis:hset(hash, plugin, false)
|
||||
return 'Plugin '..plugin..' wurde für diesen Chat reaktiviert.'
|
||||
else
|
||||
return 'Plugin '..plugin..' ist nicht deaktiviert.'
|
||||
end
|
||||
end
|
||||
|
||||
function plugin_manager:action(msg, config, matches)
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
|
||||
-- Show the available plugins
|
||||
if matches[1] == '/plugins' then
|
||||
utilities.send_reply(self, msg, plugin_manager:list_plugins())
|
||||
return
|
||||
end
|
||||
|
||||
-- Reenable a plugin for this chat
|
||||
if matches[1] == 'enable' and matches[3] == 'chat' then
|
||||
local plugin = matches[2]
|
||||
if matches[4] then
|
||||
local id = matches[4]
|
||||
print("enable "..plugin..' on chat#id'..id)
|
||||
utilities.send_reply(self, msg, plugin_manager:reenable_plugin_on_chat(id, plugin))
|
||||
return
|
||||
else
|
||||
print("enable "..plugin..' on this chat')
|
||||
utilities.send_reply(self, msg, plugin_manager:reenable_plugin_on_chat(msg, plugin))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- Enable a plugin
|
||||
if matches[1] == 'enable' then
|
||||
local plugin_name = matches[2]
|
||||
print("enable: "..matches[2])
|
||||
utilities.send_reply(self, msg, plugin_manager:enable_plugin(self, config, plugin_name))
|
||||
return
|
||||
end
|
||||
|
||||
-- Disable a plugin on a chat
|
||||
if matches[1] == 'disable' and matches[3] == 'chat' then
|
||||
local plugin = matches[2]
|
||||
if matches[4] then
|
||||
local id = matches[4]
|
||||
print("disable "..plugin..' on chat#id'..id)
|
||||
utilities.send_reply(self, msg, plugin_manager:disable_plugin_on_chat(id, plugin))
|
||||
return
|
||||
else
|
||||
print("disable "..plugin..' on this chat')
|
||||
utilities.send_reply(self, msg, plugin_manager:disable_plugin_on_chat(msg, plugin))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
-- Disable a plugin
|
||||
if matches[1] == 'disable' then
|
||||
print("disable: "..matches[2])
|
||||
utilities.send_reply(self, msg, plugin_manager:disable_plugin(self, config, matches[2]))
|
||||
return
|
||||
end
|
||||
|
||||
-- Reload all the plugins!
|
||||
if matches[1] == 'reload' then
|
||||
utilities.send_reply(self, msg, plugin_manager:reload_plugins(self, config))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return plugin_manager
|
149
miku/plugins/pocket.lua
Normal file
149
miku/plugins/pocket.lua
Normal file
@ -0,0 +1,149 @@
|
||||
local pocket = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
function pocket:init(config)
|
||||
if not cred_data.pocket_consumer_key then
|
||||
print('Missing config value: pocket_consumer_key.')
|
||||
print('pocket.lua will not be enabled.')
|
||||
return
|
||||
end
|
||||
|
||||
pocket.triggers = {
|
||||
"^/pocket(set)(.+)$",
|
||||
"^/pocket (add) (https?://.*)$",
|
||||
"^/pocket (archive) (%d+)$",
|
||||
"^/pocket (readd) (%d+)$",
|
||||
"^/pocket (unfavorite) (%d+)$",
|
||||
"^/pocket (favorite) (%d+)$",
|
||||
"^/pocket (delete) (%d+)$",
|
||||
"^/pocket (unauth)$",
|
||||
"^/pocket$"
|
||||
}
|
||||
|
||||
pocket.doc = [[*
|
||||
]]..config.cmd_pat..[[pocket*: Postet Liste deiner Links
|
||||
*]]..config.cmd_pat..[[pocket* add _(url)_: Fügt diese URL deiner Liste hinzu
|
||||
*]]..config.cmd_pat..[[pocket* archive _[id]_: Archiviere diesen Eintrag
|
||||
*]]..config.cmd_pat..[[pocket* readd _[id]_: De-archiviere diesen Eintrag
|
||||
*]]..config.cmd_pat..[[pocket* favorite _[id]_: Favorisiere diesen Eintrag
|
||||
*]]..config.cmd_pat..[[pocket* unfavorite _[id]_: Entfavorisiere diesen Eintrag
|
||||
*]]..config.cmd_pat..[[pocket* delete _[id]_: Lösche diesen Eintrag
|
||||
*]]..config.cmd_pat..[[pocket* unauth: Löscht deinen Account aus dem Bot]]
|
||||
end
|
||||
|
||||
pocket.command = 'pocket <siehe `/hilfe pocket`>'
|
||||
|
||||
local BASE_URL = 'https://getpocket.com/v3'
|
||||
local consumer_key = cred_data.pocket_consumer_key
|
||||
local headers = {
|
||||
["Content-Type"] = "application/x-www-form-urlencoded; charset=UTF8",
|
||||
["X-Accept"] = "application/json"
|
||||
}
|
||||
|
||||
function pocket:set_pocket_access_token(hash, access_token)
|
||||
if string.len(access_token) ~= 30 then return '*Inkorrekter Access-Token*' end
|
||||
print('Setting pocket in redis hash '..hash..' to users access_token')
|
||||
redis:hset(hash, 'pocket', access_token)
|
||||
return '*Authentifizierung abgeschlossen!*\nDas Plugin kann jetzt verwendet werden.'
|
||||
end
|
||||
|
||||
function pocket:list_pocket_items(access_token)
|
||||
local items = post_petition(BASE_URL..'/get', 'consumer_key='..consumer_key..'&access_token='..access_token..'&state=unread&sort=newest&detailType=simple', headers)
|
||||
|
||||
if items.status == 2 then return 'Keine Elemente eingespeichert.' end
|
||||
if items.status ~= 1 then return 'Ein Fehler beim Holen der Elemente ist aufgetreten.' end
|
||||
|
||||
local text = ''
|
||||
for element in pairs(items.list) do
|
||||
title = items.list[element].given_title
|
||||
if not title or title == "" then title = items.list[element].resolved_title end
|
||||
text = text..'#'..items.list[element].item_id..': '..title..'\n— '..items.list[element].resolved_url..'\n\n'
|
||||
end
|
||||
|
||||
return text
|
||||
end
|
||||
|
||||
function pocket:add_pocket_item(access_token, url)
|
||||
local result = post_petition(BASE_URL..'/add', 'consumer_key='..consumer_key..'&access_token='..access_token..'&url='..url, headers)
|
||||
if result.status ~= 1 then return 'Ein Fehler beim Hinzufügen der URL ist aufgetreten :(' end
|
||||
local given_url = result.item.given_url
|
||||
if result.item.title == "" or not result.item.title then
|
||||
title = 'Seite'
|
||||
else
|
||||
title = '"'..result.item.title..'"'
|
||||
end
|
||||
local code = result.item.response_code
|
||||
|
||||
local text = title..' ('..given_url..') hinzugefügt!'
|
||||
if code ~= "200" and code ~= "0" then text = text..'\nAber die Seite liefert Fehler '..code..' zurück.' end
|
||||
return text
|
||||
end
|
||||
|
||||
function pocket:modify_pocket_item(access_token, action, id)
|
||||
local result = post_petition(BASE_URL..'/send', 'consumer_key='..consumer_key..'&access_token='..access_token..'&actions=[{"action":"'..action..'","item_id":'..id..'}]', headers)
|
||||
if result.status ~= 1 then return 'Ein Fehler ist aufgetreten :(' end
|
||||
|
||||
if action == 'readd' then
|
||||
if result.action_results[1] == false then
|
||||
return 'Dieser Eintrag existiert nicht!'
|
||||
end
|
||||
local url = result.action_results[1].normal_url
|
||||
return url..' wieder de-archiviert'
|
||||
end
|
||||
if result.action_results[1] == true then
|
||||
return 'Aktion ausgeführt.'
|
||||
else
|
||||
return 'Ein Fehler ist aufgetreten.'
|
||||
end
|
||||
end
|
||||
|
||||
function pocket:action(msg, config, matches)
|
||||
local hash = 'user:'..msg.from.id
|
||||
local access_token = redis:hget(hash, 'pocket')
|
||||
|
||||
if matches[1] == 'set' then
|
||||
local access_token = matches[2]
|
||||
utilities.send_reply(self, msg, pocket:set_pocket_access_token(hash, access_token), true)
|
||||
local message_id = redis:hget(hash, 'pocket_login_msg')
|
||||
utilities.edit_message(self, msg.chat.id, message_id, '*Anmeldung abgeschlossen!*', true, true)
|
||||
redis:hdel(hash, 'pocket_login_msg')
|
||||
return
|
||||
end
|
||||
|
||||
if not access_token then
|
||||
local result = utilities.send_reply(self, msg, '*Bitte authentifiziere dich zuerst, indem du dich anmeldest.*', true, '{"inline_keyboard":[[{"text":"Bei Pocket anmelden","url":"https://brawlbot.tk/apis/callback/pocket/connect.php"}]]}')
|
||||
redis:hset(hash, 'pocket_login_msg', result.result.message_id)
|
||||
return
|
||||
end
|
||||
|
||||
if matches[1] == 'unauth' then
|
||||
redis:hdel(hash, 'pocket')
|
||||
utilities.send_reply(self, msg, 'Erfolgreich ausgeloggt! Du kannst den Zugriff [in deinen Einstellungen](https://getpocket.com/connected_applications) endgültig entziehen.', true)
|
||||
return
|
||||
end
|
||||
|
||||
if matches[1] == 'add' then
|
||||
utilities.send_reply(self, msg, pocket:add_pocket_item(access_token, matches[2]))
|
||||
return
|
||||
end
|
||||
|
||||
if matches[1] == 'archive' or matches[1] == 'delete' or matches[1] == 'readd' or matches[1] == 'favorite' or matches[1] == 'unfavorite' then
|
||||
utilities.send_reply(self, msg, pocket:modify_pocket_item(access_token, matches[1], matches[2]))
|
||||
return
|
||||
end
|
||||
|
||||
if msg.chat.type == 'chat' or msg.chat.type == 'supergroup' then
|
||||
utilities.send_reply(self, msg, 'Ausgeben deiner privaten Pocket-Liste in einem öffentlichen Chat wird feige verweigert. Bitte schreibe mich privat an!', true)
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, pocket:list_pocket_items(access_token))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
return pocket
|
71
miku/plugins/pokedex.lua
Normal file
71
miku/plugins/pokedex.lua
Normal file
@ -0,0 +1,71 @@
|
||||
local pokedex = {}
|
||||
|
||||
local HTTP = require('socket.http')
|
||||
local JSON = require('dkjson')
|
||||
local bindings = require('miku.bindings')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
pokedex.command = 'pokedex <query>'
|
||||
|
||||
function pokedex:init(config)
|
||||
pokedex.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('pokedex', true):t('dex', true).table
|
||||
pokedex.doc = [[```
|
||||
]]..config.cmd_pat..[[pokedex <query>
|
||||
Returns a Pokedex entry from pokeapi.co.
|
||||
Alias: ]]..config.cmd_pat..[[dex
|
||||
```]]
|
||||
end
|
||||
|
||||
function pokedex:action(msg, config)
|
||||
|
||||
bindings.sendChatAction(self, { chat_id = msg.chat.id, action = 'typing' } )
|
||||
|
||||
local input = utilities.input(msg.text_lower)
|
||||
if not input then
|
||||
if msg.reply_to_message and msg.reply_to_message.text then
|
||||
input = msg.reply_to_message.text
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, pokedex.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local url = 'http://pokeapi.co'
|
||||
|
||||
local dex_url = url .. '/api/v1/pokemon/' .. input
|
||||
local dex_jstr, res = HTTP.request(dex_url)
|
||||
if res ~= 200 then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
return
|
||||
end
|
||||
|
||||
local dex_jdat = JSON.decode(dex_jstr)
|
||||
|
||||
local desc_url = url .. dex_jdat.descriptions[math.random(#dex_jdat.descriptions)].resource_uri
|
||||
local desc_jstr, _ = HTTP.request(desc_url)
|
||||
if res ~= 200 then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
return
|
||||
end
|
||||
|
||||
local desc_jdat = JSON.decode(desc_jstr)
|
||||
|
||||
local poke_type
|
||||
for _,v in ipairs(dex_jdat.types) do
|
||||
local type_name = v.name:gsub("^%l", string.upper)
|
||||
if not poke_type then
|
||||
poke_type = type_name
|
||||
else
|
||||
poke_type = poke_type .. ' / ' .. type_name
|
||||
end
|
||||
end
|
||||
poke_type = poke_type .. ' type'
|
||||
|
||||
local output = '*' .. dex_jdat.name .. '*\n#' .. dex_jdat.national_id .. ' | ' .. poke_type .. '\n_' .. desc_jdat.description:gsub('POKMON', 'Pokémon'):gsub('Pokmon', 'Pokémon') .. '_'
|
||||
|
||||
|
||||
utilities.send_message(self, msg.chat.id, output, true, nil, true)
|
||||
|
||||
end
|
||||
|
||||
return pokedex
|
47
miku/plugins/preview.lua
Normal file
47
miku/plugins/preview.lua
Normal file
@ -0,0 +1,47 @@
|
||||
local preview = {}
|
||||
|
||||
local HTTP = require('socket.http')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
preview.command = 'preview <link>'
|
||||
|
||||
function preview:init(config)
|
||||
preview.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('preview', true).table
|
||||
preview.doc = [[```
|
||||
]]..config.cmd_pat..[[preview <link>
|
||||
Returns a full-message, "unlinked" preview.
|
||||
```]]
|
||||
end
|
||||
|
||||
function preview:action(msg)
|
||||
|
||||
local input = utilities.input(msg.text)
|
||||
|
||||
if not input then
|
||||
utilities.send_message(self, msg.chat.id, preview.doc, true, nil, true)
|
||||
return
|
||||
end
|
||||
|
||||
input = utilities.get_word(input, 1)
|
||||
if not input:match('^https?://.+') then
|
||||
input = 'http://' .. input
|
||||
end
|
||||
|
||||
local res = HTTP.request(input)
|
||||
if not res then
|
||||
utilities.send_reply(self, msg, 'Please provide a valid link.')
|
||||
return
|
||||
end
|
||||
|
||||
if res:len() == 0 then
|
||||
utilities.send_reply(self, msg, 'Sorry, the link you provided is not letting us make a preview.')
|
||||
return
|
||||
end
|
||||
|
||||
-- Invisible zero-width, non-joiner.
|
||||
local output = '[](' .. input .. ')'
|
||||
utilities.send_message(self, msg.chat.id, output, false, nil, true)
|
||||
|
||||
end
|
||||
|
||||
return preview
|
86
miku/plugins/qr.lua
Normal file
86
miku/plugins/qr.lua
Normal file
@ -0,0 +1,86 @@
|
||||
local qr = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local URL = require('socket.url')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function qr:init(config)
|
||||
qr.triggers = {
|
||||
'^/qr "(%w+)" "(%w+)" (.+)$',
|
||||
"^/qr (.+)$"
|
||||
}
|
||||
qr.doc = [[*
|
||||
]]..config.cmd_pat..[[qr* _<Text>_: Sendet QR-Code mit diesem Text
|
||||
*]]..config.cmd_pat..[[qr* _"[Hintergrundfarbe]"_ _"[Datenfarbe]"_ _[Text]_
|
||||
Farbe mit Text: red|green|blue|purple|black|white|gray
|
||||
Farbe als HEX: ("a56729" ist braun)
|
||||
oder Farbe als Dezimalwert: ("255-192-203" ist pink)]]
|
||||
end
|
||||
|
||||
qr.command = 'qr <Text>'
|
||||
|
||||
function qr:get_hex(str)
|
||||
local colors = {
|
||||
red = "f00",
|
||||
blue = "00f",
|
||||
green = "0f0",
|
||||
yellow = "ff0",
|
||||
purple = "f0f",
|
||||
white = "fff",
|
||||
black = "000",
|
||||
gray = "ccc"
|
||||
}
|
||||
|
||||
for color, value in pairs(colors) do
|
||||
if color == str then
|
||||
return value
|
||||
end
|
||||
end
|
||||
|
||||
return str
|
||||
end
|
||||
|
||||
function qr:qr(text, color, bgcolor)
|
||||
|
||||
local url = "http://api.qrserver.com/v1/create-qr-code/?"
|
||||
.."size=600x600" --fixed size otherways it's low detailed
|
||||
.."&data="..URL.escape(utilities.trim(text))
|
||||
|
||||
if color then
|
||||
url = url.."&color="..qr:get_hex(color)
|
||||
end
|
||||
if bgcolor then
|
||||
url = url.."&bgcolor="..qr:get_hex(bgcolor)
|
||||
end
|
||||
|
||||
local response, code, headers = http.request(url)
|
||||
|
||||
if code ~= 200 then
|
||||
return nil
|
||||
end
|
||||
|
||||
if #response > 0 then
|
||||
return url
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
function qr:action(msg, config, matches)
|
||||
local text = matches[1]
|
||||
local color
|
||||
local back
|
||||
|
||||
if #matches > 1 then
|
||||
text = matches[3]
|
||||
color = matches[2]
|
||||
back = matches[1]
|
||||
end
|
||||
|
||||
local image_url = qr:qr(text, color, back)
|
||||
if not image_url then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
local file = download_to_file(image_url, 'qr.png')
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
|
||||
return qr
|
111
miku/plugins/quotes.lua
Normal file
111
miku/plugins/quotes.lua
Normal file
@ -0,0 +1,111 @@
|
||||
local quotes = {}
|
||||
|
||||
local bot = require('miku.bot')
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
require("./miku/plugins/pasteee")
|
||||
|
||||
function quotes:init(config)
|
||||
quotes.triggers = {
|
||||
"^/(delquote) (.+)$",
|
||||
"^/(addquote) (.+)$",
|
||||
"^/(quote)$",
|
||||
"^/(listquotes)$"
|
||||
}
|
||||
quotes.doc = [[*
|
||||
]]..config.cmd_pat..[[addquote* _<Zitat>_: Fügt Zitat hinzu.
|
||||
*]]..config.cmd_pat..[[delquote* _<Zitat>_: Löscht das Zitat (nur Superuser)
|
||||
*]]..config.cmd_pat..[[quote*: Gibt zufälliges Zitat aus
|
||||
*]]..config.cmd_pat..[[listquotes*: Listet alle Zitate auf
|
||||
]]
|
||||
end
|
||||
|
||||
quotes.command = 'quote'
|
||||
|
||||
function quotes:save_quote(msg)
|
||||
if msg.text:sub(11):isempty() then
|
||||
return "Benutzung: /addquote [Zitat]"
|
||||
end
|
||||
|
||||
local quote = msg.text:sub(11)
|
||||
local hash = get_redis_hash(msg, 'quotes')
|
||||
print('Saving quote to redis set '..hash)
|
||||
redis:sadd(hash, quote)
|
||||
return '*Gespeichert!*'
|
||||
end
|
||||
|
||||
function quotes:delete_quote(msg)
|
||||
if msg.text:sub(11):isempty() then
|
||||
return "Benutzung: /delquote [Zitat]"
|
||||
end
|
||||
|
||||
local quote = msg.text:sub(11)
|
||||
local hash = get_redis_hash(msg, 'quotes')
|
||||
print('Deleting quote from redis set '..hash)
|
||||
if redis:sismember(hash, quote) == true then
|
||||
redis:srem(hash, quote)
|
||||
return '*Zitat erfolgreich gelöscht!*'
|
||||
else
|
||||
return 'Dieses Zitat existiert nicht.'
|
||||
end
|
||||
end
|
||||
|
||||
function quotes:get_quote(msg)
|
||||
local hash = get_redis_hash(msg, 'quotes')
|
||||
|
||||
if hash then
|
||||
print('Getting quote from redis set '..hash)
|
||||
local quotes_table = redis:smembers(hash)
|
||||
if not quotes_table[1] then
|
||||
return 'Es wurden noch keine Zitate gespeichert.\nSpeichere doch welche mit /addquote [Zitat]'
|
||||
else
|
||||
return quotes_table[math.random(1,#quotes_table)]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function quotes:list_quotes(msg)
|
||||
local hash = get_redis_hash(msg, 'quotes')
|
||||
|
||||
if hash then
|
||||
print('Getting quotes from redis set '..hash)
|
||||
local quotes_table = redis:smembers(hash)
|
||||
local text = ""
|
||||
for num,quote in pairs(quotes_table) do
|
||||
text = text..num..") "..quote..'\n'
|
||||
end
|
||||
if not text or text == "" then
|
||||
return '*Es wurden noch keine Zitate gespeichert.*\nSpeichere doch welche mit `/addquote [Zitat]`', true
|
||||
else
|
||||
return upload(text)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function quotes:action(msg, config, matches)
|
||||
if matches[1] == "quote" then
|
||||
utilities.send_message(self, msg.chat.id, quotes:get_quote(msg), true)
|
||||
return
|
||||
elseif matches[1] == "addquote" and matches[2] then
|
||||
utilities.send_reply(self, msg, quotes:save_quote(msg), true)
|
||||
return
|
||||
elseif matches[1] == "delquote" and matches[2] then
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
utilities.send_reply(self, msg, quotes:delete_quote(msg), true)
|
||||
return
|
||||
elseif matches[1] == "listquotes" then
|
||||
local link, iserror = quotes:list_quotes(msg)
|
||||
if iserror then
|
||||
utilities.send_reply(self, msg, link, true)
|
||||
return
|
||||
end
|
||||
utilities.send_reply(self, msg, 'Ich habe eine Liste aller Zitate hochgeladen.', false, '{"inline_keyboard":[[{"text":"Alle Zitate abrufen","url":"'..link..'"}]]}')
|
||||
return
|
||||
end
|
||||
utilities.send_reply(self, msg, quotes.doc, true)
|
||||
end
|
||||
|
||||
return quotes
|
67
miku/plugins/random.lua
Normal file
67
miku/plugins/random.lua
Normal file
@ -0,0 +1,67 @@
|
||||
local fun = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function fun:init(config)
|
||||
fun.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('random', true).table
|
||||
fun.doc = [[*
|
||||
]]..config.cmd_pat..[[random* _<Username>_: Schau, was passiert!]]
|
||||
end
|
||||
|
||||
fun.command = 'random <Username>'
|
||||
|
||||
function fun:choose_random(user_name, other_user)
|
||||
randoms = {
|
||||
user_name..' schlägt '..other_user..' mit einem stinkenden Fisch.',
|
||||
user_name..' versucht, '..other_user..' mit einem Messer zu töten, bringt sich dabei aber selbst um.',
|
||||
user_name..' versucht, '..other_user..' mit einem Messer zu töten, stolpert aber und schlitzt sich dabei das Knie auf.',
|
||||
user_name..' ersticht '..other_user..'.',
|
||||
user_name..' tritt '..other_user..'.',
|
||||
user_name..' hat '..other_user..' umgebracht! Möge er in der Hölle schmoren!',
|
||||
user_name..' hat die Schnauze voll von '..other_user..' und sperrt ihn in einen Schrank.',
|
||||
user_name..' erwürgt '..other_user..'. BILD sprach als erstes mit der Hand.',
|
||||
user_name..' schickt '..other_user..' nach /dev/null.',
|
||||
user_name..' umarmt '..other_user..'.',
|
||||
user_name..' verschenkt eine Kartoffel an '..other_user..'.',
|
||||
user_name..' melkt '..other_user..'. *muuh* :D',
|
||||
user_name..' wirft einen Gameboy auf '..other_user..'.',
|
||||
user_name..' hetzt die NSA auf '..other_user..'.',
|
||||
user_name..' ersetzt alle CDs von '..other_user..' durch Nickelback-CDs.',
|
||||
other_user..' melkt '..user_name..'. *muuh* :D',
|
||||
user_name..' ist in '..other_user..' verliebt.',
|
||||
user_name..' schmeißt '..other_user..' in einen Fluss.',
|
||||
user_name..' klaut '..other_user..' einen Lolli.',
|
||||
user_name..' hätte gern Sex mit '..other_user..'.',
|
||||
user_name..' schenkt '..other_user..' ein Foto von seinem Penis.',
|
||||
user_name..' dreht durch und wirft '..other_user..' in einen Häcksler.',
|
||||
user_name..' gibt '..other_user..' einen Keks.',
|
||||
user_name..' lacht '..other_user..' aus.',
|
||||
user_name..' gibt '..other_user..[[ ganz viel Liebe. ( ͡° ͜ʖ ͡°)]],
|
||||
user_name..' lädt '..other_user..' zum Essen ein.',
|
||||
user_name..' schwatzt '..other_user..' Ubuntu auf.',
|
||||
user_name..' fliegt mit '..other_user..' nach Hawaii.',
|
||||
user_name..' küsst '..other_user..' leidenschaftlich.'
|
||||
}
|
||||
math.randomseed(os.time())
|
||||
math.randomseed(os.time())
|
||||
local random = math.random(#randoms)
|
||||
return randoms[random]
|
||||
end
|
||||
|
||||
function fun:action(msg, config, matches)
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
if msg.reply_to_message and msg.reply_to_message.text then
|
||||
input = msg.reply_to_message.text
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, fun.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local user_name = get_name(msg)
|
||||
local result = fun:choose_random(user_name, input)
|
||||
utilities.send_message(self, msg.chat.id, result)
|
||||
end
|
||||
|
||||
return fun
|
82
miku/plugins/reddit.lua
Normal file
82
miku/plugins/reddit.lua
Normal file
@ -0,0 +1,82 @@
|
||||
local reddit = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local JSON = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
reddit.command = 'reddit [r/subreddit | Suchbegriff]'
|
||||
|
||||
function reddit:init(config)
|
||||
reddit.triggers = utilities.triggers(self.info.username, config.cmd_pat, {'^/r/'}):t('reddit', true):t('r', true):t('r/', true).table
|
||||
reddit.doc = [[*
|
||||
]]..config.cmd_pat..[[r* _[r/subreddit | Suchbegriff]_: Gibt Top-Posts oder Ergebnisse eines Subreddits aus. Wenn kein Argument gegeben ist, wird /r/all genommen.]]
|
||||
end
|
||||
|
||||
local format_results = function(posts)
|
||||
local output = ''
|
||||
for _,v in ipairs(posts) do
|
||||
local post = v.data
|
||||
local title = post.title:gsub('%[', '('):gsub('%]', ')'):gsub('&', '&')
|
||||
if title:len() > 256 then
|
||||
title = title:sub(1, 253)
|
||||
title = utilities.trim(title) .. '...'
|
||||
end
|
||||
local short_url = 'https://redd.it/' .. post.id
|
||||
local s = '[' .. unescape(title) .. '](' .. short_url .. ')'
|
||||
if post.domain and not post.is_self and not post.over_18 then
|
||||
s = '`[`[' .. post.domain .. '](' .. post.url:gsub('%)', '\\)') .. ')`]` ' .. s
|
||||
end
|
||||
output = output .. '• ' .. s .. '\n'
|
||||
end
|
||||
return output
|
||||
end
|
||||
|
||||
reddit.subreddit_url = 'https://www.reddit.com/%s/.json?limit='
|
||||
reddit.search_url = 'https://www.reddit.com/search.json?q=%s&limit='
|
||||
reddit.rall_url = 'https://www.reddit.com/.json?limit='
|
||||
|
||||
function reddit:action(msg, config)
|
||||
-- Eight results in PM, four results elsewhere.
|
||||
local limit = 4
|
||||
if msg.chat.type == 'private' then
|
||||
limit = 8
|
||||
end
|
||||
local text = msg.text_lower
|
||||
if text:match('^/r/.') then
|
||||
-- Normalize input so this hack works easily.
|
||||
text = msg.text_lower:gsub('^/r/', config.cmd_pat..'r r/')
|
||||
end
|
||||
local input = utilities.input(text)
|
||||
local source, url
|
||||
if input then
|
||||
if input:match('^r/.') then
|
||||
input = utilities.get_word(input, 1)
|
||||
url = reddit.subreddit_url:format(input) .. limit
|
||||
source = '*/' .. utilities.md_escape(input) .. '*\n'
|
||||
else
|
||||
input = utilities.input(msg.text)
|
||||
source = '*Ergebnisse für* _' .. utilities.md_escape(input) .. '_ *:*\n'
|
||||
input = URL.escape(input)
|
||||
url = reddit.search_url:format(input) .. limit
|
||||
end
|
||||
else
|
||||
url = reddit.rall_url .. limit
|
||||
source = '*/r/all*\n'
|
||||
end
|
||||
local jstr, res = https.request(url)
|
||||
if res ~= 200 then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
else
|
||||
local jdat = JSON.decode(jstr)
|
||||
if #jdat.data.children == 0 then
|
||||
utilities.send_reply(self, msg, config.errors.results)
|
||||
else
|
||||
local output = format_results(jdat.data.children)
|
||||
output = source .. output
|
||||
utilities.send_message(self, msg.chat.id, output, true, nil, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return reddit
|
55
miku/plugins/reddit_post.lua
Normal file
55
miku/plugins/reddit_post.lua
Normal file
@ -0,0 +1,55 @@
|
||||
local reddit_post = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
reddit_post.triggers = {
|
||||
"reddit.com/r/([A-Za-z0-9-/-_-.]+)/comments/([A-Za-z0-9-/-_-.]+)"
|
||||
}
|
||||
|
||||
local BASE_URL = 'https://www.reddit.com'
|
||||
|
||||
function reddit_post:get_reddit_data(subreddit, reddit_code)
|
||||
local url = BASE_URL..'/r/'..subreddit..'/comments/'..reddit_code..'.json'
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)
|
||||
return data
|
||||
end
|
||||
|
||||
function reddit_post:send_reddit_data(data)
|
||||
local title = utilities.md_escape(data[1].data.children[1].data.title)
|
||||
local author = utilities.md_escape(data[1].data.children[1].data.author)
|
||||
local subreddit = utilities.md_escape(data[1].data.children[1].data.subreddit)
|
||||
if string.len(data[1].data.children[1].data.selftext) > 300 then
|
||||
selftext = string.sub(unescape(data[1].data.children[1].data.selftext:gsub("%b<>", "")), 1, 300) .. '...'
|
||||
else
|
||||
selftext = unescape(data[1].data.children[1].data.selftext:gsub("%b<>", ""))
|
||||
end
|
||||
if not data[1].data.children[1].data.is_self then
|
||||
url = data[1].data.children[1].data.url
|
||||
else
|
||||
url = ''
|
||||
end
|
||||
local score = comma_value(data[1].data.children[1].data.score)
|
||||
local comments = comma_value(data[1].data.children[1].data.num_comments)
|
||||
local text = '*'..author..'* in */r/'..subreddit..'* _('..score..' Upvotes - '..comments..' Kommentare)_:\n'..title..'\n'..selftext..url
|
||||
return text
|
||||
end
|
||||
|
||||
|
||||
function reddit_post:action(msg, config, matches)
|
||||
local subreddit = matches[1]
|
||||
local reddit_code = matches[2]
|
||||
local data = reddit_post:get_reddit_data(subreddit, reddit_code)
|
||||
if not data then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
|
||||
local text = reddit_post:send_reddit_data(data)
|
||||
if not text then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
|
||||
return reddit_post
|
95
miku/plugins/remind.lua
Normal file
95
miku/plugins/remind.lua
Normal file
@ -0,0 +1,95 @@
|
||||
local remind = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
remind.command = 'remind <Länge> <Nachricht>'
|
||||
|
||||
function remind:init(config)
|
||||
self.database.reminders = self.database.reminders or {}
|
||||
|
||||
remind.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('remind', true).table
|
||||
remind.doc = [[*
|
||||
]]..config.cmd_pat..[[remind* _<Länge>_ _<Nachricht>_: Erinnert dich in X Minuten an die Nachricht]]
|
||||
end
|
||||
|
||||
function remind:action(msg)
|
||||
-- Ensure there are arguments. If not, send doc.
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
utilities.send_message(self, msg.chat.id, remind.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
-- Ensure first arg is a number. If not, send doc.
|
||||
local duration = utilities.get_word(input, 1)
|
||||
if not tonumber(duration) then
|
||||
utilities.send_message(self, msg.chat.id, remind.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
-- Duration must be between one minute and one year (approximately).
|
||||
duration = tonumber(duration)
|
||||
if duration < 1 then
|
||||
duration = 1
|
||||
elseif duration > 526000 then
|
||||
duration = 526000
|
||||
end
|
||||
-- Ensure there is a second arg.
|
||||
local message = utilities.input(input)
|
||||
if not message then
|
||||
utilities.send_message(self, msg.chat.id, remind.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
-- Make a database entry for the group/user if one does not exist.
|
||||
self.database.reminders[msg.chat.id_str] = self.database.reminders[msg.chat.id_str] or {}
|
||||
-- Limit group reminders to 10 and private reminders to 50.
|
||||
if msg.chat.type ~= 'private' and utilities.table_size(self.database.reminders[msg.chat.id_str]) > 9 then
|
||||
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
|
||||
end
|
||||
-- Put together the reminder with the expiration, message, and message to reply to.
|
||||
local reminder = {
|
||||
time = os.time() + duration * 60,
|
||||
message = message
|
||||
}
|
||||
table.insert(self.database.reminders[msg.chat.id_str], reminder)
|
||||
local output = 'Ich werde dich in ' .. duration
|
||||
if duration == 1 then
|
||||
output = output .. ' Minute erinnern!'
|
||||
else
|
||||
output = output .. ' Minuten erinnern!'
|
||||
end
|
||||
utilities.send_reply(self, msg, output)
|
||||
end
|
||||
|
||||
function remind:cron()
|
||||
local time = os.time()
|
||||
-- Iterate over the group entries in the reminders database.
|
||||
for chat_id, group in pairs(self.database.reminders) do
|
||||
local new_group = {}
|
||||
-- Iterate over each reminder.
|
||||
for _, reminder in ipairs(group) do
|
||||
-- If the reminder is past-due, send it and nullify it.
|
||||
-- Otherwise, add it to the replacement table.
|
||||
if time > reminder.time then
|
||||
local output = '*ERINNERUNG:*\n"' .. utilities.md_escape(reminder.message) .. '"'
|
||||
local res = utilities.send_message(self, chat_id, output, true, nil, true)
|
||||
-- If the message fails to send, save it for later.
|
||||
if not res then
|
||||
table.insert(new_group, reminder)
|
||||
end
|
||||
else
|
||||
table.insert(new_group, reminder)
|
||||
end
|
||||
end
|
||||
-- Nullify the original table and replace it with the new one.
|
||||
self.database.reminders[chat_id] = new_group
|
||||
-- Nullify the table if it is empty.
|
||||
if #new_group == 0 then
|
||||
self.database.reminders[chat_id] = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return remind
|
86
miku/plugins/respond.lua
Normal file
86
miku/plugins/respond.lua
Normal file
@ -0,0 +1,86 @@
|
||||
local respond = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
function respond:init(config)
|
||||
respond.triggers = {
|
||||
"([Ff][Gg][Tt].? [Ss][Ww][Ii][Ff][Tt])",
|
||||
"([Ee][Ii][Nn][Zz][Ii][Gg][Ss][Tt][Ee][Ss])",
|
||||
"([Ee][Ii][Nn][Zz][Ii][Gg][Ss][Tt][Ee][Rr])",
|
||||
"([Ee][Ii][Nn][Zz][Ii][Gg][Ss][Tt][Ee])",
|
||||
"^[Bb][Oo][Tt]%??$",
|
||||
"^/([Ll][Oo][Dd])$",
|
||||
"^/([Ll][Ff])$",
|
||||
"^/([Kk][Aa])$",
|
||||
"^/([Ii][Dd][Kk])$",
|
||||
"^/([Nn][Bb][Cc])$",
|
||||
"^/([Ii][Dd][Cc])$",
|
||||
"^%*([Ff][Rr][Oo][Ss][Cc][Hh])%*",
|
||||
"^/([Ff][Rr][Oo][Ss][Cc][Hh])$",
|
||||
"^%(([Ii][Nn][Ll][Oo][Vv][Ee])%)$",
|
||||
"^/[Ww][Aa][Tt]$"
|
||||
}
|
||||
end
|
||||
|
||||
respond.command = 'lod, /lf, /nbc, /wat'
|
||||
|
||||
function respond:action(msg, config, matches)
|
||||
local user_name = get_name(msg)
|
||||
local receiver = msg.chat.id
|
||||
local GDRIVE_URL = 'https://de2319bd4b4b51a5ef2939a7638c1d35646f49f8.googledrive.com/host/0B_mfIlDgPiyqU25vUHZqZE9IUXc'
|
||||
if user_name == "DefenderX" then user_name = "Deffu" end
|
||||
|
||||
if string.match(msg.text, "[Ff][Gg][Tt].? [Ss][Ww][Ii][Ff][Tt]") then
|
||||
utilities.send_message(self, receiver, 'Dünnes Eis, '..user_name..'!')
|
||||
return
|
||||
elseif string.match(msg.text, "([Ee][Ii][Nn][Zz][Ii][Gg][Ss][Tt][Ee][Ss])") then
|
||||
utilities.send_message(self, receiver, '*einziges')
|
||||
return
|
||||
elseif string.match(msg.text, "([Ee][Ii][Nn][Zz][Ii][Gg][Ss][Tt][Ee][Rr])") then
|
||||
utilities.send_message(self, receiver, '*einziger')
|
||||
return
|
||||
elseif string.match(msg.text, "([Ee][Ii][Nn][Zz][Ii][Gg][Ss][Tt][Ee])") then
|
||||
utilities.send_message(self, receiver, '*einzige')
|
||||
return
|
||||
elseif string.match(msg.text, "[Bb][Oo][Tt]%??") then
|
||||
utilities.send_reply(self, msg, '*Ich bin da, '..user_name..'!*', true)
|
||||
return
|
||||
elseif string.match(msg.text, "[Ll][Oo][Dd]") then
|
||||
utilities.send_message(self, receiver, 'ಠ_ಠ')
|
||||
return
|
||||
elseif string.match(msg.text, "[Ll][Ff]") then
|
||||
utilities.send_message(self, receiver, '( ͡° ͜ʖ ͡°)')
|
||||
return
|
||||
elseif string.match(msg.text, "[Nn][Bb][Cc]") or string.match(msg.text, "[Ii][Dd][Cc]") or string.match(msg.text, "[Kk][Aa]") or string.match(msg.text, "[Ii][Dd][Kk]") then
|
||||
utilities.send_message(self, receiver, [[¯\_(ツ)_/¯]])
|
||||
return
|
||||
elseif string.match(msg.text, "[Ff][Rr][Oo][Ss][Cc][Hh]") then
|
||||
utilities.send_message(self, receiver, '🐸🐸🐸')
|
||||
return
|
||||
elseif string.match(msg.text, "[Ii][Nn][Ll][Oo][Vv][Ee]") then
|
||||
local file = download_to_file(GDRIVE_URL..'/inlove.gif')
|
||||
utilities.send_document(self, receiver, file)
|
||||
return
|
||||
elseif string.match(msg.text, "[Ww][Aa][Tt]") then
|
||||
local WAT_URL = GDRIVE_URL..'/wat'
|
||||
local wats = {
|
||||
"/wat1.jpg",
|
||||
"/wat2.jpg",
|
||||
"/wat3.jpg",
|
||||
"/wat4.jpg",
|
||||
"/wat5.jpg",
|
||||
"/wat6.jpg",
|
||||
"/wat7.jpg",
|
||||
"/wat8.jpg"
|
||||
}
|
||||
local random_wat = math.random(5)
|
||||
local file = download_to_file(WAT_URL..wats[random_wat])
|
||||
utilities.send_photo(self, receiver, file)
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return respond
|
31
miku/plugins/roll.lua
Normal file
31
miku/plugins/roll.lua
Normal file
@ -0,0 +1,31 @@
|
||||
local roll = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
roll.command = 'roll'
|
||||
|
||||
function roll:init(config)
|
||||
roll.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('roll', true).table
|
||||
roll.doc = [[*
|
||||
]]..config.cmd_pat..[[roll*: Werfe einen Würfel]]
|
||||
end
|
||||
|
||||
local canroll = {
|
||||
"1",
|
||||
"2",
|
||||
"3",
|
||||
"4",
|
||||
"5",
|
||||
"6"
|
||||
}
|
||||
|
||||
function roll:roll_dice()
|
||||
local randomroll = math.random(6)
|
||||
return canroll[randomroll]
|
||||
end
|
||||
|
||||
function roll:action(msg)
|
||||
utilities.send_reply(self, msg, 'Du hast eine *'..roll:roll_dice()..'* gewürfelt.', true)
|
||||
end
|
||||
|
||||
return roll
|
361
miku/plugins/rss.lua
Normal file
361
miku/plugins/rss.lua
Normal file
@ -0,0 +1,361 @@
|
||||
local rss = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local https = require('ssl.https')
|
||||
local url = require('socket.url')
|
||||
local bindings = require('miku.bindings')
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
local feedparser = require("feedparser")
|
||||
|
||||
rss.command = 'rss <sub/del>'
|
||||
|
||||
function rss:init(config)
|
||||
rss.triggers = {
|
||||
"^/(rss) @(.*)$",
|
||||
"^/rss$",
|
||||
"^/rss (sub) (https?://[%w-_%.%?%.:/%+=&%~]+) @(.*)$",
|
||||
"^/rss (sub) (https?://[%w-_%.%?%.:/%+=&%~]+)$",
|
||||
"^/rss (del) (%d+) @(.*)$",
|
||||
"^/rss (del) (%d+)$",
|
||||
"^/rss (del)",
|
||||
"^/rss (sync)$"
|
||||
}
|
||||
rss.doc = [[*
|
||||
]]..config.cmd_pat..[[rss* _@[Kanalname]_: Feed-Abonnements anzeigen
|
||||
*]]..config.cmd_pat..[[rss* _sub_ _<URL>_ _@[Kanalname]_: Diesen Feed abonnieren
|
||||
*]]..config.cmd_pat..[[rss* _del_ _<#>_ _@[Kanalname]_: Diesen Feed deabonnieren
|
||||
*]]..config.cmd_pat..[[rss* _sync_: Feeds syncen (nur Superuser)
|
||||
Der Kanalname ist optional]]
|
||||
end
|
||||
|
||||
function tail(n, k)
|
||||
local u, r=''
|
||||
for i=1,k do
|
||||
n,r = math.floor(n/0x40), n%0x40
|
||||
u = string.char(r+0x80) .. u
|
||||
end
|
||||
return u, n
|
||||
end
|
||||
|
||||
function to_utf8(a)
|
||||
local n, r, u = tonumber(a)
|
||||
if n<0x80 then -- 1 byte
|
||||
return string.char(n)
|
||||
elseif n<0x800 then -- 2 byte
|
||||
u, n = tail(n, 1)
|
||||
return string.char(n+0xc0) .. u
|
||||
elseif n<0x10000 then -- 3 byte
|
||||
u, n = tail(n, 2)
|
||||
return string.char(n+0xe0) .. u
|
||||
elseif n<0x200000 then -- 4 byte
|
||||
u, n = tail(n, 3)
|
||||
return string.char(n+0xf0) .. u
|
||||
elseif n<0x4000000 then -- 5 byte
|
||||
u, n = tail(n, 4)
|
||||
return string.char(n+0xf8) .. u
|
||||
else -- 6 byte
|
||||
u, n = tail(n, 5)
|
||||
return string.char(n+0xfc) .. u
|
||||
end
|
||||
end
|
||||
|
||||
function unescape_for_rss(str)
|
||||
str = string.gsub( str, '<', '<' )
|
||||
str = string.gsub( str, '>', '>' )
|
||||
str = string.gsub( str, '"', '"' )
|
||||
str = string.gsub( str, ''', "'" )
|
||||
str = string.gsub( str, "Ä", "Ä")
|
||||
str = string.gsub( str, "ä", "ä")
|
||||
str = string.gsub( str, "Ö", "Ö")
|
||||
str = string.gsub( str, "ö", "ö")
|
||||
str = string.gsub( str, "Uuml;", "Ü")
|
||||
str = string.gsub( str, "ü", "ü")
|
||||
str = string.gsub( str, "ß", "ß")
|
||||
str = string.gsub(str, '&#(%d+);', to_utf8)
|
||||
str = string.gsub( str, '&#x(%d+);', function(n) return string.char(tonumber(n,16)) end )
|
||||
str = string.gsub( str, '&', '&' ) -- Be sure to do this after all others
|
||||
return str
|
||||
end
|
||||
|
||||
function get_base_redis(id, option, extra)
|
||||
local ex = ''
|
||||
if option ~= nil then
|
||||
ex = ex .. ':' .. option
|
||||
if extra ~= nil then
|
||||
ex = ex .. ':' .. extra
|
||||
end
|
||||
end
|
||||
return 'rss:' .. id .. ex
|
||||
end
|
||||
|
||||
function prot_url(url)
|
||||
local url, h = string.gsub(url, "http://", "")
|
||||
local url, hs = string.gsub(url, "https://", "")
|
||||
local protocol = "http"
|
||||
if hs == 1 then
|
||||
protocol = "https"
|
||||
end
|
||||
return url, protocol
|
||||
end
|
||||
|
||||
function get_rss(url, prot)
|
||||
local res, code = nil, 0
|
||||
if prot == "http" then
|
||||
res, code = http.request(url)
|
||||
elseif prot == "https" then
|
||||
res, code = https.request(url)
|
||||
end
|
||||
if code ~= 200 then
|
||||
return nil, "Fehler beim Erreichen von " .. url
|
||||
end
|
||||
local parsed = feedparser.parse(res)
|
||||
if parsed == nil then
|
||||
return nil, "Fehler beim Dekodieren des Feeds.\nBist du sicher, dass "..url.." ein Feed ist?"
|
||||
end
|
||||
return parsed, nil
|
||||
end
|
||||
|
||||
function get_new_entries(last, nentries)
|
||||
local entries = {}
|
||||
for k,v in pairs(nentries) do
|
||||
if v.id == last then
|
||||
return entries
|
||||
else
|
||||
table.insert(entries, v)
|
||||
end
|
||||
end
|
||||
return entries
|
||||
end
|
||||
|
||||
function print_subs(id, chat_name)
|
||||
local uhash = get_base_redis(id)
|
||||
local subs = redis:smembers(uhash)
|
||||
local text = '"'..chat_name..'" hat abonniert:\n---------\n'
|
||||
for k,v in pairs(subs) do
|
||||
text = text .. k .. ") " .. v .. '\n'
|
||||
end
|
||||
return text
|
||||
end
|
||||
|
||||
function rss:subscribe(id, url)
|
||||
local baseurl, protocol = prot_url(url)
|
||||
|
||||
local prothash = get_base_redis(baseurl, "protocol")
|
||||
local lasthash = get_base_redis(baseurl, "last_entry")
|
||||
local lhash = get_base_redis(baseurl, "subs")
|
||||
local uhash = get_base_redis(id)
|
||||
|
||||
if redis:sismember(uhash, baseurl) then
|
||||
return "Du hast `"..url.."` bereits abonniert."
|
||||
end
|
||||
|
||||
local parsed, err = get_rss(url, protocol)
|
||||
if err ~= nil then
|
||||
return err
|
||||
end
|
||||
|
||||
local last_entry = ""
|
||||
if #parsed.entries > 0 then
|
||||
last_entry = parsed.entries[1].id
|
||||
end
|
||||
|
||||
local name = parsed.feed.title
|
||||
|
||||
redis:set(prothash, protocol)
|
||||
redis:set(lasthash, last_entry)
|
||||
redis:sadd(lhash, id)
|
||||
redis:sadd(uhash, baseurl)
|
||||
|
||||
return "_"..name.."_ abonniert!"
|
||||
end
|
||||
|
||||
function rss:unsubscribe(id, n)
|
||||
if #n > 5 then
|
||||
return "Du kannst nicht mehr als fünf Feeds abonnieren!"
|
||||
end
|
||||
n = tonumber(n)
|
||||
|
||||
local uhash = get_base_redis(id)
|
||||
local subs = redis:smembers(uhash)
|
||||
if n < 1 or n > #subs then
|
||||
return "Abonnement-ID zu hoch!"
|
||||
end
|
||||
local sub = subs[n]
|
||||
local lhash = get_base_redis(sub, "subs")
|
||||
|
||||
redis:srem(uhash, sub)
|
||||
redis:srem(lhash, id)
|
||||
|
||||
local left = redis:smembers(lhash)
|
||||
if #left < 1 then -- no one subscribed, remove it
|
||||
local prothash = get_base_redis(sub, "protocol")
|
||||
local lasthash = get_base_redis(sub, "last_entry")
|
||||
redis:del(prothash)
|
||||
redis:del(lasthash)
|
||||
end
|
||||
|
||||
return "Du hast `"..sub.."` deabonniert."
|
||||
end
|
||||
|
||||
function rss:print_subs(id, chat_name)
|
||||
local uhash = get_base_redis(id)
|
||||
local subs = redis:smembers(uhash)
|
||||
if not subs[1] then
|
||||
return 'Keine Feeds abonniert!'
|
||||
end
|
||||
local keyboard = '{"keyboard":[['
|
||||
local keyboard_buttons = ''
|
||||
local text = '*'..chat_name..'* hat abonniert:\n---------\n'
|
||||
for k,v in pairs(subs) do
|
||||
text = text .. k .. ") " .. v .. '\n'
|
||||
if k == #subs then
|
||||
keyboard_buttons = keyboard_buttons..'{"text":"/rss del '..k..'"}'
|
||||
break;
|
||||
end
|
||||
keyboard_buttons = keyboard_buttons..'{"text":"/rss del '..k..'"},'
|
||||
end
|
||||
local keyboard = keyboard..keyboard_buttons..']], "one_time_keyboard":true, "selective":true, "resize_keyboard":true}'
|
||||
return text, keyboard
|
||||
end
|
||||
|
||||
function rss:action(msg, config, matches)
|
||||
local id = "user#id" .. msg.from.id
|
||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||
id = 'chat#id'..msg.chat.id
|
||||
end
|
||||
|
||||
-- For channels
|
||||
if matches[1] == 'sub' and matches[2] and matches[3] then
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
local id = '@'..matches[3]
|
||||
local result = utilities.get_chat_info(self, id)
|
||||
if not result then
|
||||
utilities.send_reply(self, msg, 'Diesen Kanal gibt es nicht!')
|
||||
return
|
||||
end
|
||||
local output = rss:subscribe(id, matches[2])
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
return
|
||||
elseif matches[1] == 'del' and matches[2] and matches[3] then
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
local id = '@'..matches[3]
|
||||
local result = utilities.get_chat_info(self, id)
|
||||
if not result then
|
||||
utilities.send_reply(self, msg, 'Diesen Kanal gibt es nicht!')
|
||||
return
|
||||
end
|
||||
local output = rss:unsubscribe(id, matches[2])
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
return
|
||||
elseif matches[1] == 'rss' and matches[2] then
|
||||
local id = '@'..matches[2]
|
||||
local result = utilities.get_chat_info(self, id)
|
||||
if not result then
|
||||
utilities.send_reply(self, msg, 'Diesen Kanal gibt es nicht!')
|
||||
return
|
||||
end
|
||||
local chat_name = result.result.title
|
||||
local output = rss:print_subs(id, chat_name)
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
return
|
||||
end
|
||||
|
||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||
chat_name = msg.chat.title
|
||||
else
|
||||
chat_name = msg.chat.first_name
|
||||
end
|
||||
|
||||
if matches[1] == 'sub' and matches[2] then
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
local output = rss:subscribe(id, matches[2])
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
return
|
||||
elseif matches[1] == 'del' and matches[2] then
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
local output = rss:unsubscribe(id, matches[2])
|
||||
utilities.send_reply(self, msg, output, true, '{"hide_keyboard":true}')
|
||||
return
|
||||
elseif matches[1] == 'del' and not matches[2] then
|
||||
local list_subs, keyboard = rss:print_subs(id, chat_name)
|
||||
utilities.send_reply(self, msg, list_subs, true, keyboard)
|
||||
return
|
||||
elseif matches[1] == 'sync' then
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
rss:cron(self)
|
||||
return
|
||||
end
|
||||
|
||||
local output = rss:print_subs(id, chat_name)
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
return
|
||||
end
|
||||
|
||||
function rss:cron(self_plz)
|
||||
if not self.BASE_URL then
|
||||
self = self_plz
|
||||
end
|
||||
local keys = redis:keys(get_base_redis("*", "subs"))
|
||||
for k,v in pairs(keys) do
|
||||
local base = string.match(v, "rss:(.+):subs") -- Get the URL base
|
||||
print('RSS: '..base)
|
||||
local prot = redis:get(get_base_redis(base, "protocol"))
|
||||
local last = redis:get(get_base_redis(base, "last_entry"))
|
||||
local url = prot .. "://" .. base
|
||||
local parsed, err = get_rss(url, prot)
|
||||
if err ~= nil then
|
||||
return
|
||||
end
|
||||
-- local feed_title = parsed.feed.title
|
||||
local newentr = get_new_entries(last, parsed.entries)
|
||||
local subscribers = {}
|
||||
local text = '' -- Send one message per feed with the latest entries
|
||||
for k2, v2 in pairs(newentr) do
|
||||
local title = v2.title or 'Kein Titel'
|
||||
local link = v2.link or v2.id or 'Kein Link'
|
||||
if v2.content then
|
||||
if string.len(v2.content) > 250 then
|
||||
content = string.sub(unescape_for_rss(v2.content:gsub("%b<>", "")), 1, 250) .. '...'
|
||||
else
|
||||
content = unescape_for_rss(v2.content:gsub("%b<>", ""))
|
||||
end
|
||||
elseif v2.summary then
|
||||
if string.len(v2.summary) > 250 then
|
||||
content = string.sub(unescape_for_rss(v2.summary:gsub("%b<>", "")), 1, 250) .. '...'
|
||||
else
|
||||
content = unescape_for_rss(v2.summary:gsub("%b<>", ""))
|
||||
end
|
||||
else
|
||||
content = ''
|
||||
end
|
||||
text = text..'\n[[#RSS]] *'..title..'*\n'..utilities.trim(utilities.markdown_escape_simple(content))..' [Weiterlesen]('..link..')\n'
|
||||
end
|
||||
if text ~= '' then
|
||||
local newlast = newentr[1].id
|
||||
redis:set(get_base_redis(base, "last_entry"), newlast)
|
||||
for k2, receiver in pairs(redis:smembers(v)) do
|
||||
local receiver = string.gsub(receiver, 'chat%#id', '')
|
||||
local receiver = string.gsub(receiver, 'user%#id', '')
|
||||
utilities.send_message(self, receiver, text, true, nil, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return rss
|
55
miku/plugins/set.lua
Normal file
55
miku/plugins/set.lua
Normal file
@ -0,0 +1,55 @@
|
||||
local set = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
set.command = 'set <Variable> <Wert>'
|
||||
|
||||
function set:init(config)
|
||||
set.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('set', true).table
|
||||
set.doc = [[*
|
||||
]]..config.cmd_pat..[[set* _<Variable>_ _<Wert>_: Speichert eine Variable mit einem Wert
|
||||
*]]..config.cmd_pat..[[set* _<Variable>_ _nil_: Löscht Variable
|
||||
Nutze `!get <Variable>` zum Abrufen]]
|
||||
end
|
||||
|
||||
function set:save_value(msg, name, value)
|
||||
local hash = get_redis_hash(msg, 'variables')
|
||||
if hash then
|
||||
print('Saving variable to redis hash '..hash)
|
||||
redis:hset(hash, name, value)
|
||||
return "Gespeichert: "..name.." = "..value
|
||||
end
|
||||
end
|
||||
|
||||
function set:delete_value(msg, name)
|
||||
local hash = get_redis_hash(msg, 'variables')
|
||||
if redis:hexists(hash, name) == true then
|
||||
print('Deleting variable from redis hash '..hash)
|
||||
redis:hdel(hash, name)
|
||||
return 'Variable "'..name..'" erfolgreich gelöscht!'
|
||||
else
|
||||
return 'Du kannst keine Variable löschen, die nicht existiert .-.'
|
||||
end
|
||||
end
|
||||
|
||||
function set:action(msg)
|
||||
local input = utilities.input(msg.text)
|
||||
if not input or not input:match('([^%s]+) (.+)') then
|
||||
utilities.send_message(self, msg.chat.id, set.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
|
||||
local name = input:match('([^%s]+) ')
|
||||
local value = input:match(' (.+)')
|
||||
|
||||
if value == "nil" then
|
||||
output = set:delete_value(msg, name)
|
||||
else
|
||||
output = set:save_value(msg, name, value)
|
||||
end
|
||||
|
||||
utilities.send_message(self, msg.chat.id, output, true, nil, true)
|
||||
end
|
||||
|
||||
return set
|
34
miku/plugins/shell.lua
Normal file
34
miku/plugins/shell.lua
Normal file
@ -0,0 +1,34 @@
|
||||
local shell = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function shell:init(config)
|
||||
shell.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('sh', true).table
|
||||
end
|
||||
|
||||
function shell:action(msg, config)
|
||||
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
|
||||
local input = utilities.input(msg.text)
|
||||
input = input:gsub('—', '--')
|
||||
|
||||
if not input then
|
||||
utilities.send_reply(self, msg, 'Bitte gebe ein Kommando ein.')
|
||||
return
|
||||
end
|
||||
|
||||
local output = io.popen(input):read('*all')
|
||||
if output:len() == 0 then
|
||||
output = 'Ausgeführt.'
|
||||
else
|
||||
output = '```\n' .. output .. '\n```'
|
||||
end
|
||||
utilities.send_message(self, msg.chat.id, output, true, msg.message_id, true)
|
||||
|
||||
end
|
||||
|
||||
return shell
|
28
miku/plugins/site_header.lua
Normal file
28
miku/plugins/site_header.lua
Normal file
@ -0,0 +1,28 @@
|
||||
local site_header = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
function site_header:init(config)
|
||||
site_header.triggers = {
|
||||
"^/(head) ([%w-_%.%?%.:,/%+=&#!]+)$",
|
||||
"^/(dig) ([%w-_%.%?%.:,/%+=&#!]+)$"
|
||||
}
|
||||
end
|
||||
|
||||
function site_header:action(msg, config, matches)
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
end
|
||||
|
||||
local url = matches[2]
|
||||
if matches[1] == 'head' then
|
||||
input = 'curl --head '..url
|
||||
elseif matches[1] == 'dig' then
|
||||
input = 'dig '..url..' ANY'
|
||||
end
|
||||
local output = io.popen(input):read('*all')
|
||||
output = '```\n' .. output .. '\n```'
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
end
|
||||
|
||||
return site_header
|
41
miku/plugins/soundcloud.lua
Normal file
41
miku/plugins/soundcloud.lua
Normal file
@ -0,0 +1,41 @@
|
||||
local soundcloud = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
soundcloud.triggers = {
|
||||
"soundcloud.com/([A-Za-z0-9-/-_-.]+)"
|
||||
}
|
||||
|
||||
local BASE_URL = 'http://api.soundcloud.com/resolve.json'
|
||||
local client_id = cred_data.soundcloud_client_id
|
||||
|
||||
function soundcloud:send_soundcloud_info(sc_url)
|
||||
local url = BASE_URL..'?url=http://soundcloud.com/'..sc_url..'&client_id='..client_id
|
||||
|
||||
local res,code = http.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)
|
||||
|
||||
local title = data.title
|
||||
local description = data.description
|
||||
local user = data.user.username
|
||||
local user = 'Unbekannt'
|
||||
local genre = data.genre
|
||||
local playback_count = data.playback_count
|
||||
local milliseconds = data.duration
|
||||
local totalseconds = math.floor(milliseconds / 1000)
|
||||
local duration = makeHumanTime(totalseconds)
|
||||
|
||||
local text = '*'..title..'* von _'..user..'_\n_(Tag: '..genre..', '..duration..'; '..playback_count..' mal angehört)_\n'..description
|
||||
return text
|
||||
end
|
||||
|
||||
function soundcloud:action(msg, config, matches)
|
||||
local text = soundcloud:send_soundcloud_info(matches[1])
|
||||
if not text then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
|
||||
return soundcloud
|
17
miku/plugins/speedtest.lua
Normal file
17
miku/plugins/speedtest.lua
Normal file
@ -0,0 +1,17 @@
|
||||
local speedtest = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
speedtest.triggers = {
|
||||
"speedtest.net/my%-result/(%d+)",
|
||||
"speedtest.net/my%-result/i/(%d+)"
|
||||
}
|
||||
|
||||
function speedtest:action(msg, config, matches)
|
||||
local url = 'http://www.speedtest.net/result/'..matches[1]..'.png'
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(url)
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
|
||||
return speedtest
|
52
miku/plugins/spotify.lua
Normal file
52
miku/plugins/spotify.lua
Normal file
@ -0,0 +1,52 @@
|
||||
local spotify = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
spotify.triggers = {
|
||||
"open.spotify.com/track/([A-Za-z0-9-]+)",
|
||||
"play.spotify.com/track/([A-Za-z0-9-]+)"
|
||||
}
|
||||
|
||||
local BASE_URL = 'https://api.spotify.com/v1'
|
||||
|
||||
function spotify:get_track_data(track)
|
||||
local url = BASE_URL..'/tracks/'..track
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)
|
||||
return data
|
||||
end
|
||||
|
||||
function spotify:send_track_data(data, self, msg)
|
||||
local name = data.name
|
||||
local album = data.album.name
|
||||
local artist = data.artists[1].name
|
||||
local preview = data.preview_url
|
||||
local milliseconds = data.duration_ms
|
||||
|
||||
-- convert s to mm:ss
|
||||
local totalseconds = math.floor(milliseconds / 1000)
|
||||
local duration = makeHumanTime(totalseconds)
|
||||
|
||||
local text = '*'..name..'* von *'..artist..'* aus dem Album *'..album..'* _('..duration..')_'
|
||||
if preview then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_audio')
|
||||
local file = download_to_file(preview, name..'.mp3')
|
||||
utilities.send_audio(self, msg.chat.id, file, msg.message_id, totalseconds, artist, name)
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
function spotify:action(msg, config, matches)
|
||||
local data = spotify:get_track_data(matches[1])
|
||||
if not data then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
spotify:send_track_data(data, self, msg)
|
||||
return
|
||||
end
|
||||
|
||||
return spotify
|
144
miku/plugins/stats.lua
Normal file
144
miku/plugins/stats.lua
Normal file
@ -0,0 +1,144 @@
|
||||
local stats = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
function stats:init(config)
|
||||
stats.triggers = {
|
||||
"^/([Ss]tats)$",
|
||||
"^/([Ss]tats) (chat) (%-%d+)",
|
||||
"^/([Ss]tats) (chat) (%d+)"
|
||||
}
|
||||
stats.doc = [[*
|
||||
]]..config.cmd_pat..[[stats*: Zeigt Stats an
|
||||
*]]..config.cmd_pat..[[stats* _chat_ _<chat#id>_: Stats für Chat-ID (nur Superuser)
|
||||
]]
|
||||
end
|
||||
|
||||
stats.command = 'stats'
|
||||
|
||||
function stats:user_print_name(user)
|
||||
if user.name then
|
||||
return user.name
|
||||
end
|
||||
|
||||
local text = ''
|
||||
if user.first_name then
|
||||
text = user.last_name..' '
|
||||
end
|
||||
if user.lastname then
|
||||
text = text..user.last_name
|
||||
end
|
||||
|
||||
return text
|
||||
end
|
||||
|
||||
-- Returns a table with `name` and `msgs`
|
||||
function stats:get_msgs_user_chat(user_id, chat_id)
|
||||
local user_info = {}
|
||||
local uhash = 'user:'..user_id
|
||||
local user = redis:hgetall(uhash)
|
||||
local um_hash = 'msgs:'..user_id..':'..chat_id
|
||||
user_info.msgs = tonumber(redis:get(um_hash) or 0)
|
||||
user_info.name = stats:user_print_name(user)
|
||||
return user_info
|
||||
end
|
||||
|
||||
function stats:chat_stats(chat_id)
|
||||
-- Users on chat
|
||||
local hash = 'chat:'..chat_id..':users'
|
||||
local users = redis:smembers(hash)
|
||||
local users_info = {}
|
||||
|
||||
-- Get user info
|
||||
for i = 1, #users do
|
||||
local user_id = users[i]
|
||||
local user_info = stats:get_msgs_user_chat(user_id, chat_id)
|
||||
table.insert(users_info, user_info)
|
||||
end
|
||||
|
||||
-- Sort users by msgs number
|
||||
table.sort(users_info, function(a, b)
|
||||
if a.msgs and b.msgs then
|
||||
return a.msgs > b.msgs
|
||||
end
|
||||
end)
|
||||
|
||||
local text = ''
|
||||
for k,user in pairs(users_info) do
|
||||
text = text..user.name..': '..user.msgs..'\n'
|
||||
text = string.gsub(text, "%_", " ") -- Bot API doesn't use underscores anymore! Yippie!
|
||||
end
|
||||
if text:isempty() then return 'Keine Stats für diesen Chat verfügbar!'end
|
||||
return text
|
||||
end
|
||||
|
||||
function stats:pre_process(msg, self)
|
||||
-- Ignore service msg
|
||||
if msg.service then -- check how Bot API handles service msgs, will update this
|
||||
print('Service message')
|
||||
return
|
||||
end
|
||||
|
||||
if msg.left_chat_member then
|
||||
-- delete user from redis set, but keep message count
|
||||
local hash = 'chat:'..msg.chat.id..':users'
|
||||
local user_id_left = msg.left_chat_member.id
|
||||
print('User '..user_id_left..' was kicked, deleting him/her from redis set '..hash)
|
||||
redis:srem(hash, user_id_left)
|
||||
return msg
|
||||
end
|
||||
|
||||
-- Save user on Redis
|
||||
local hash = 'user:'..msg.from.id
|
||||
-- print('Saving user', hash) -- remove comment to restore old behaviour
|
||||
if msg.from.name then
|
||||
redis:hset(hash, 'name', msg.from.name)
|
||||
end
|
||||
if msg.from.first_name then
|
||||
redis:hset(hash, 'first_name', msg.from.first_name)
|
||||
end
|
||||
if msg.from.last_name then
|
||||
redis:hset(hash, 'last_name', msg.from.last_name)
|
||||
end
|
||||
|
||||
-- Save stats on Redis
|
||||
if msg.chat.type ~= 'private' then
|
||||
-- User is on chat
|
||||
local hash = 'chat:'..msg.chat.id..':users'
|
||||
redis:sadd(hash, msg.from.id)
|
||||
end
|
||||
|
||||
-- Total user msgs
|
||||
local hash = 'msgs:'..msg.from.id..':'..msg.chat.id
|
||||
redis:incr(hash)
|
||||
return msg
|
||||
end
|
||||
|
||||
function stats:action(msg, config, matches)
|
||||
if matches[1]:lower() == "stats" then
|
||||
|
||||
if not matches[2] then
|
||||
if msg.chat.type == 'private' then
|
||||
utilities.send_reply(self, msg, 'Stats funktionieren nur in Chats!')
|
||||
return
|
||||
else
|
||||
local chat_id = msg.chat.id
|
||||
utilities.send_reply(self, msg, stats:chat_stats(chat_id))
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
if matches[2] == "chat" then
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
else
|
||||
utilities.send_reply(self, msg, stats:chat_stats(matches[3]))
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return stats
|
63
miku/plugins/steam.lua
Normal file
63
miku/plugins/steam.lua
Normal file
@ -0,0 +1,63 @@
|
||||
local steam = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
local http = require('socket.http')
|
||||
local json = require('dkjson')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
steam.triggers = {
|
||||
"store.steampowered.com/app/([0-9]+)",
|
||||
"steamcommunity.com/app/([0-9]+)"
|
||||
}
|
||||
|
||||
local BASE_URL = 'http://store.steampowered.com/api/appdetails/'
|
||||
local DESC_LENTH = 400
|
||||
|
||||
function steam:get_steam_data(appid)
|
||||
local url = BASE_URL
|
||||
url = url..'?appids='..appid
|
||||
url = url..'&l=german&cc=DE'
|
||||
local res,code = http.request(url)
|
||||
if code ~= 200 then return nil end
|
||||
local data = json.decode(res)[appid].data
|
||||
return data
|
||||
end
|
||||
|
||||
function steam:price_info(data)
|
||||
local price = '' -- If no data is empty
|
||||
|
||||
if data then
|
||||
local initial = data.initial
|
||||
local final = data.final or data.initial
|
||||
local min = math.min(data.initial, data.final)
|
||||
price = tostring(min/100)
|
||||
if data.discount_percent and initial ~= final then
|
||||
price = price..data.currency..' ('..data.discount_percent..'% OFF)'
|
||||
end
|
||||
price = price..' €'
|
||||
end
|
||||
|
||||
return price
|
||||
end
|
||||
|
||||
function steam:send_steam_data(data, self, msg)
|
||||
local description = string.sub(unescape(data.about_the_game:gsub("%b<>", "")), 1, DESC_LENTH) .. '...'
|
||||
local title = data.name
|
||||
local price = steam:price_info(data.price_overview)
|
||||
|
||||
local text = '*'..title..'* _'..price..'_\n'..description
|
||||
local image_url = data.header_image
|
||||
return text, image_url
|
||||
end
|
||||
|
||||
function steam:action(msg)
|
||||
local data = steam:get_steam_data(matches[1])
|
||||
if not data then utilities.send_reply(self, msg, config.errors.connection) return end
|
||||
|
||||
local text, image_url = steam:send_steam_data(data, self, msg)
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
utilities.send_photo(self, msg.chat.id, download_to_file(image_url, matches[1]..'.jpg'), nil, msg.message_id)
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
|
||||
return steam
|
53
miku/plugins/streamable.lua
Normal file
53
miku/plugins/streamable.lua
Normal file
@ -0,0 +1,53 @@
|
||||
local streamable = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
streamable.triggers = {
|
||||
"streamable.com/([A-Za-z0-9-_-]+)",
|
||||
}
|
||||
|
||||
function streamable:send_streamable_video(shortcode, self, msg)
|
||||
local BASE_URL = "https://api.streamable.com"
|
||||
local url = BASE_URL..'/videos/'..shortcode
|
||||
local res,code = https.request(url)
|
||||
if code ~= 200 then return 'HTTP-Fehler' end
|
||||
local data = json.decode(res)
|
||||
if data.status ~= 2 then utilities.send_reply(self, msg, "Video ist (noch) nicht verfügbar.") return end
|
||||
|
||||
if data.files.webm then
|
||||
if data.title == "" then title = shortcode..'.webm' else title = data.title..'.webm' end
|
||||
url = 'https:'..data.files.webm.url
|
||||
width = data.files.webm.width
|
||||
height = data.files.webm.height
|
||||
if data.files.webm.size > 50000000 then
|
||||
local size = math.floor(data.files.webm.size / 1000000)
|
||||
utilities.send_reply(self, msg, '*Video ist größer als 50 MB* ('..size..' MB)!\n[Direktlink]('..url..')', true)
|
||||
return
|
||||
end
|
||||
elseif data.files.mp4 then
|
||||
if data.title == "" then title = shortcode..'.mp4' else title = data.title..'.mp4' end
|
||||
url = 'https:'..data.files.mp4.url
|
||||
width = data.files.mp4.width
|
||||
height = data.files.mp4.height
|
||||
if data.files.mp4.size > 50000000 then
|
||||
local size = math.floor(data.files.mp4.size / 1000000)
|
||||
utilities.send_reply(self, msg, '*Video ist größer als 50 MB* ('..size..' MB)!\n[Direktlink]('..url..')', true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_video')
|
||||
local file = download_to_file(url, title)
|
||||
utilities.send_video(self, msg.chat.id, file, nil, msg.message_id, nil, width, height)
|
||||
return
|
||||
end
|
||||
|
||||
function streamable:action(msg, config, matches)
|
||||
local shortcode = matches[1]
|
||||
streamable:send_streamable_video(shortcode, self, msg)
|
||||
return
|
||||
end
|
||||
|
||||
return streamable
|
16
miku/plugins/surrogate.lua
Normal file
16
miku/plugins/surrogate.lua
Normal file
@ -0,0 +1,16 @@
|
||||
local surrogate = {}
|
||||
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
surrogate.triggers = {
|
||||
"^/s (%-%d+) +(.+)$",
|
||||
"^/s (%d+) +(.+)$"
|
||||
}
|
||||
|
||||
function surrogate:action(msg)
|
||||
-- Supergroups don't work!?
|
||||
utilities.send_message(self, matches[1], matches[2], true, nil, true)
|
||||
return
|
||||
end
|
||||
|
||||
return surrogate
|
56
miku/plugins/tagesschau.lua
Normal file
56
miku/plugins/tagesschau.lua
Normal file
@ -0,0 +1,56 @@
|
||||
local tagesschau = {}
|
||||
|
||||
local https = require('ssl.https')
|
||||
local URL = require('socket.url')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local bindings = require('miku.bindings')
|
||||
|
||||
tagesschau.triggers = {
|
||||
"tagesschau.de/([A-Za-z0-9-_-_-/]+).html"
|
||||
}
|
||||
|
||||
local BASE_URL = 'https://www.tagesschau.de/api'
|
||||
|
||||
local makeOurDate = function(dateString)
|
||||
local pattern = "(%d+)%-(%d+)%-(%d+)T(%d+)%:(%d+)%:(%d+)"
|
||||
local year, month, day, hours, minutes, seconds = dateString:match(pattern)
|
||||
return day..'.'..month..'.'..year..' um '..hours..':'..minutes..':'..seconds
|
||||
end
|
||||
|
||||
function tagesschau:get_tagesschau_article(article)
|
||||
local url = BASE_URL..'/'..article..'.json'
|
||||
local res,code = https.request(url)
|
||||
local data = json.decode(res)
|
||||
if code == 404 then return "Artikel nicht gefunden!" end
|
||||
if code ~= 200 then return "HTTP-Fehler" end
|
||||
if not data then return "HTTP-Fehler" end
|
||||
if data.type ~= "story" then
|
||||
print('Typ "'..data.type..'" wird nicht unterstützt')
|
||||
return nil
|
||||
end
|
||||
|
||||
local title = data.topline..': '..data.headline
|
||||
local news = data.shorttext
|
||||
local posted_at = makeOurDate(data.date)..' Uhr'
|
||||
|
||||
local text = '*'..title..'*\n_'..posted_at..'_\n'..news
|
||||
if data.banner[1] then
|
||||
return text, data.banner[1].variants[1].modPremium
|
||||
else
|
||||
return text
|
||||
end
|
||||
end
|
||||
|
||||
function tagesschau:action(msg, config, matches)
|
||||
local article = matches[1]
|
||||
local text, image_url = tagesschau:get_tagesschau_article(article)
|
||||
if image_url then
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(image_url)
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
|
||||
return tagesschau
|
112
miku/plugins/tagesschau_eil.lua
Normal file
112
miku/plugins/tagesschau_eil.lua
Normal file
@ -0,0 +1,112 @@
|
||||
local tagesschau_eil = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local https = require('ssl.https')
|
||||
local url = require('socket.url')
|
||||
local json = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
local redis = (loadfile "./miku/redis.lua")()
|
||||
|
||||
tagesschau_eil.command = 'eil <sub/del>'
|
||||
|
||||
function tagesschau_eil:init(config)
|
||||
tagesschau_eil.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('eil', true).table
|
||||
tagesschau_eil.doc = [[*
|
||||
]]..config.cmd_pat..[[eil* _sub_: Eilmeldungen abonnieren
|
||||
*]]..config.cmd_pat..[[eil* _del_: Eilmeldungen deabonnieren
|
||||
*]]..config.cmd_pat..[[eil* _sync_: Nach neuen Eilmeldungen prüfen (nur Superuser)]]
|
||||
end
|
||||
|
||||
local makeOurDate = function(dateString)
|
||||
local pattern = "(%d+)%-(%d+)%-(%d+)T(%d+)%:(%d+)%:(%d+)"
|
||||
local year, month, day, hours, minutes, seconds = dateString:match(pattern)
|
||||
return day..'.'..month..'.'..year..' um '..hours..':'..minutes..':'..seconds
|
||||
end
|
||||
|
||||
local url = 'http://www.tagesschau.de/api'
|
||||
local hash = 'telegram:tagesschau'
|
||||
|
||||
function tagesschau_eil:abonnieren(id)
|
||||
if redis:sismember(hash..':subs', id) == false then
|
||||
redis:sadd(hash..':subs', id)
|
||||
return '*Eilmeldungen abonniert.*'
|
||||
else
|
||||
return 'Die Eilmeldungen wurden hier bereits abonniert.'
|
||||
end
|
||||
end
|
||||
|
||||
function tagesschau_eil:deabonnieren(id)
|
||||
if redis:sismember(hash..':subs', id) == true then
|
||||
redis:srem(hash..':subs', id)
|
||||
return '*Eilmeldungen deabonniert.*'
|
||||
else
|
||||
return 'Die Eilmeldungen wurden hier noch nicht abonniert.'
|
||||
end
|
||||
end
|
||||
|
||||
function tagesschau_eil:action(msg, config)
|
||||
local input = utilities.input(msg.text)
|
||||
|
||||
if not input then
|
||||
if msg.reply_to_message and msg.reply_to_message.text then
|
||||
input = msg.reply_to_message.text
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, tagesschau_eil.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
local id = "user#id" .. msg.from.id
|
||||
if msg.chat.type == 'channel' then
|
||||
print('Kanäle werden momentan nicht unterstützt')
|
||||
end
|
||||
if msg.chat.type == 'group' or msg.chat.type == 'supergroup' then
|
||||
id = 'chat#id'..msg.chat.id
|
||||
end
|
||||
|
||||
if input:match('(sub)$') then
|
||||
local output = tagesschau_eil:abonnieren(id)
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
elseif input:match('(del)$') then
|
||||
local output = tagesschau_eil:deabonnieren(id)
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
elseif input:match('(sync)$') then
|
||||
if msg.from.id ~= config.admin then
|
||||
utilities.send_reply(self, msg, config.errors.sudo)
|
||||
return
|
||||
end
|
||||
tagesschau_eil:cron(self)
|
||||
end
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
function tagesschau_eil:cron(self_plz)
|
||||
if not self.BASE_URL then
|
||||
self = self_plz
|
||||
end
|
||||
-- print('EIL: Prüfe...')
|
||||
local last_eil = redis:get(hash..':last_entry')
|
||||
local res,code = http.request(url)
|
||||
if code ~= 200 then return end
|
||||
local data = json.decode(res)
|
||||
if not data then return end
|
||||
if data.breakingnews[1] then
|
||||
if data.breakingnews[1].date ~= last_eil then
|
||||
local title = '#EIL: *'..data.breakingnews[1].headline..'*'
|
||||
local news = data.breakingnews[1].shorttext
|
||||
local posted_at = makeOurDate(data.breakingnews[1].date)..' Uhr'
|
||||
local post_url = string.gsub(data.breakingnews[1].details, '/api/', '/')
|
||||
local post_url = string.gsub(post_url, '.json', '.html')
|
||||
local eil = title..'\n_'..posted_at..'_\n'..news
|
||||
redis:set(hash..':last_entry', data.breakingnews[1].date)
|
||||
for _,user in pairs(redis:smembers(hash..':subs')) do
|
||||
local user = string.gsub(user, 'chat%#id', '')
|
||||
local user = string.gsub(user, 'user%#id', '')
|
||||
utilities.send_message(self, user, eil, true, nil, true, '{"inline_keyboard":[[{"text":"Eilmeldung aufrufen","url":"'..post_url..'"}]]}')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return tagesschau_eil
|
34
miku/plugins/tex.lua
Normal file
34
miku/plugins/tex.lua
Normal file
@ -0,0 +1,34 @@
|
||||
local tex = {}
|
||||
|
||||
local URL = require('socket.url')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
tex.command = 'tex <LaTeX>'
|
||||
|
||||
function tex:init(config)
|
||||
tex.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('tex', true).table
|
||||
tex.doc = [[*
|
||||
]]..config.cmd_pat..[[tex* _<LaTeX>_: Konvertiert LaTeX in ein Bild]]
|
||||
end
|
||||
|
||||
function tex:action(msg, config)
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
if msg.reply_to_message and msg.reply_to_message.text then
|
||||
input = msg.reply_to_message.text
|
||||
else
|
||||
utilities.send_message(self, msg.chat.id, tex.doc, true, msg.message_id, true)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local eq = URL.escape(input)
|
||||
|
||||
local url = "http://latex.codecogs.com/png.download?"
|
||||
.."\\dpi{300}%20\\LARGE%20"..eq
|
||||
local file = download_to_file(url, 'latex.png')
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
|
||||
return tex
|
96
miku/plugins/thetvdb.lua
Normal file
96
miku/plugins/thetvdb.lua
Normal file
@ -0,0 +1,96 @@
|
||||
local tv = {}
|
||||
|
||||
local http = require('socket.http')
|
||||
local URL = require('socket.url')
|
||||
local xml = require("xml")
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
tv.command = 'tv <TV-Serie>'
|
||||
|
||||
function tv:init(config)
|
||||
tv.triggers = {
|
||||
"^/tv (.+)$"
|
||||
}
|
||||
tv.doc = [[*
|
||||
]]..config.cmd_pat..[[tv*_ <TV-Serie>_: Sendet Infos zur TV-Serie]]
|
||||
end
|
||||
|
||||
local BASE_URL = 'http://thetvdb.com/api'
|
||||
|
||||
local makeOurDate = function(dateString)
|
||||
local pattern = "(%d+)%-(%d+)%-(%d+)"
|
||||
local year, month, day = dateString:match(pattern)
|
||||
return day..'.'..month..'.'..year
|
||||
end
|
||||
|
||||
|
||||
function tv:get_tv_info(series)
|
||||
local url = BASE_URL..'/GetSeries.php?seriesname='..series..'&language=de'
|
||||
local res,code = http.request(url)
|
||||
if code ~= 200 then return "HTTP-ERROR" end
|
||||
local result = xml.load(res)
|
||||
if not xml.find(result, 'seriesid') then return "NOTFOUND" end
|
||||
return result
|
||||
end
|
||||
|
||||
function tv:send_tv_data(result, self, msg)
|
||||
local title = xml.find(result, 'SeriesName')[1]
|
||||
local id = xml.find(result, 'seriesid')[1]
|
||||
|
||||
if xml.find(result, 'AliasNames') and xml.find(result, 'AliasNames')[1] ~= title then
|
||||
alias = '\noder: '..xml.find(result, 'AliasNames')[1]
|
||||
else
|
||||
alias = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'Overview') then
|
||||
desc = '\n_'..string.sub(xml.find(result, 'Overview')[1], 1, 250) .. '..._'
|
||||
else
|
||||
desc = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'FirstAired') then
|
||||
aired = '\n*Erstausstrahlung:* '..makeOurDate(xml.find(result, 'FirstAired')[1])
|
||||
else
|
||||
aired = ''
|
||||
end
|
||||
|
||||
|
||||
if xml.find(result, 'Network') then
|
||||
publisher = '\n*Publisher:* '..xml.find(result, 'Network')[1]
|
||||
else
|
||||
publisher = ''
|
||||
end
|
||||
|
||||
if xml.find(result, 'IMDB_ID') then
|
||||
imdb = '\n[IMDB-Seite](http://www.imdb.com/title/'..xml.find(result, 'IMDB_ID')[1]..')'
|
||||
else
|
||||
imdb = ''
|
||||
end
|
||||
|
||||
local text = '*'..title..'*'..alias..aired..publisher..imdb..desc..'\n[TVDB-Seite besuchen](http://thetvdb.com/?id='..id..'&tab=series)'
|
||||
if xml.find(result, 'banner') then
|
||||
local image_url = 'http://www.thetvdb.com/banners/'..xml.find(result, 'banner')[1]
|
||||
utilities.send_typing(self, msg.chat.id, 'upload_photo')
|
||||
local file = download_to_file(image_url)
|
||||
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
|
||||
end
|
||||
utilities.send_reply(self, msg, text, true)
|
||||
end
|
||||
|
||||
|
||||
function tv:action(msg, config, matches)
|
||||
local series = URL.escape(matches[1])
|
||||
local tv_info = tv:get_tv_info(series)
|
||||
if tv_info == "NOTFOUND" then
|
||||
utilities.send_reply(self, msg, config.errors.results)
|
||||
return
|
||||
elseif tv_info == "HTTP-ERROR" then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
return
|
||||
else
|
||||
tv:send_tv_data(tv_info, self,msg)
|
||||
end
|
||||
end
|
||||
|
||||
return tv
|
94
miku/plugins/time.lua
Normal file
94
miku/plugins/time.lua
Normal file
@ -0,0 +1,94 @@
|
||||
local time = {}
|
||||
|
||||
local HTTPS = require('ssl.https')
|
||||
local JSON = require('dkjson')
|
||||
local utilities = require('miku.utilities')
|
||||
|
||||
time.command = 'time <Ort>'
|
||||
|
||||
function time:init(config)
|
||||
time.triggers = utilities.triggers(self.info.username, config.cmd_pat):t('time', true).table
|
||||
time.doc = [[*
|
||||
]]..config.cmd_pat..[[time*: Aktuelle Zeit in Deutschland
|
||||
*]]..config.cmd_pat..[[time* _<Ort>_: Gibt Zeit an diesem Ort aus]]
|
||||
end
|
||||
|
||||
function time:localize(output)
|
||||
-- Days
|
||||
local output = string.gsub(output, "Monday", "Montag")
|
||||
local output = string.gsub(output, "Tuesday", "Dienstag")
|
||||
local output = string.gsub(output, "Wednesday", "Mittwoch")
|
||||
local output = string.gsub(output, "Thursday", "Donnerstag")
|
||||
local output = string.gsub(output, "Friday", "Freitag")
|
||||
local output = string.gsub(output, "Saturday", "Samstag")
|
||||
local output = string.gsub(output, "Sunday", "Sonntag")
|
||||
|
||||
-- Months
|
||||
local output = string.gsub(output, "January", "Januar")
|
||||
local output = string.gsub(output, "February", "Februar")
|
||||
local output = string.gsub(output, "March", "März")
|
||||
local output = string.gsub(output, "April", "April")
|
||||
local output = string.gsub(output, "May", "Mai")
|
||||
local output = string.gsub(output, "June", "Juni")
|
||||
local output = string.gsub(output, "July", "Juli")
|
||||
local output = string.gsub(output, "August", "August")
|
||||
local output = string.gsub(output, "September", "September")
|
||||
local output = string.gsub(output, "October", "Oktober")
|
||||
local output = string.gsub(output, "November", "November")
|
||||
local output = string.gsub(output, "December", "Dezember")
|
||||
|
||||
-- Timezones
|
||||
local output = string.gsub(output, "Africa", "Afrika")
|
||||
local output = string.gsub(output, "America", "Amerika")
|
||||
local output = string.gsub(output, "Asia", "Asien")
|
||||
local output = string.gsub(output, "Australia", "Australien")
|
||||
local output = string.gsub(output, "Europe", "Europa")
|
||||
local output = string.gsub(output, "Indian", "Indien")
|
||||
local output = string.gsub(output, "Pacific", "Pazifik")
|
||||
|
||||
return output
|
||||
end
|
||||
|
||||
function time:action(msg, config)
|
||||
local input = utilities.input(msg.text)
|
||||
if not input then
|
||||
local output = os.date("%A, %d. %B %Y, *%H:%M:%S Uhr*")
|
||||
utilities.send_reply(self, msg, time:localize(output), true)
|
||||
return
|
||||
end
|
||||
|
||||
local coords = utilities.get_coords(input, config)
|
||||
if type(coords) == 'string' then
|
||||
utilities.send_reply(self, msg, coords)
|
||||
return
|
||||
end
|
||||
|
||||
local now = os.time()
|
||||
local utc = os.time(os.date("!*t", now))
|
||||
|
||||
local url = 'https://maps.googleapis.com/maps/api/timezone/json?location=' .. coords.lat ..','.. coords.lon .. '×tamp='..utc..'&language=de'
|
||||
local jstr, res = HTTPS.request(url)
|
||||
if res ~= 200 then
|
||||
utilities.send_reply(self, msg, config.errors.connection)
|
||||
return
|
||||
end
|
||||
|
||||
local jdat = JSON.decode(jstr)
|
||||
local timezoneid = '*'..string.gsub(jdat.timeZoneId, '_', ' ' )..'*'
|
||||
local timestamp = now + jdat.rawOffset + jdat.dstOffset
|
||||
local utcoff = (jdat.rawOffset + jdat.dstOffset) / 3600
|
||||
if utcoff == math.abs(utcoff) then
|
||||
utcoff = '+'.. utilities.pretty_float(utcoff)
|
||||
else
|
||||
utcoff = utilities.pretty_float(utcoff)
|
||||
end
|
||||
-- "%A, %d. %B %Y, %H:%M:%S Uhr"
|
||||
local output = timezoneid..':\n'..os.date('!%A, %d. %B %Y, %H:%M:%S Uhr',timestamp)
|
||||
local output = time:localize(output)
|
||||
|
||||
local output = output..'\n_'..jdat.timeZoneName .. ' (UTC' .. utcoff .. ')_'
|
||||
|
||||
utilities.send_reply(self, msg, output, true)
|
||||
end
|
||||
|
||||
return time
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user