diff --git a/miku/bindings.lua b/miku/bindings.lua index 2005064..15af11b 100644 --- a/miku/bindings.lua +++ b/miku/bindings.lua @@ -29,7 +29,7 @@ function bindings:request(method, parameters, file) if file and next(file) ~= nil then local file_type, file_name = next(file) if not file_name then return false end - if string.match(file_name, '/home/pi/Mikubot-V2/tmp/') then + if string.match(file_name, '/tmp/') then local file_file = io.open(file_name, 'r') local file_data = { filename = file_name, diff --git a/miku/bot.lua b/miku/bot.lua index d4a040a..2d1087c 100644 --- a/miku/bot.lua +++ b/miku/bot.lua @@ -5,7 +5,7 @@ local bindings -- Load Telegram bindings. local utilities -- Load miscellaneous and cross-plugin functions. local redis = (loadfile "./miku/redis.lua")() -bot.version = '2.1' +bot.version = '160717 function bot:init(config) -- The function run when the bot is started or reloaded. @@ -78,7 +78,7 @@ end function bot:on_msg_receive(msg, config) -- The fn run whenever a message is received. -- remove comment to enable debugging - -- vardump(msg) + -- vardump(msg) -- Cache user info for those involved. if msg.date < os.time() - 5 then return end -- Do not process old messages. @@ -97,6 +97,10 @@ function bot:on_msg_receive(msg, config) -- The fn run whenever a message is rec msg = utilities.enrich_message(msg) + if msg.reply_to_message then + msg.reply_to_message.text = msg.reply_to_message.text or msg.reply_to_message.caption or '' + end + -- Support deep linking. if msg.text:match('^'..config.cmd_pat..'start .+') then msg.text = config.cmd_pat .. utilities.input(msg.text) @@ -108,7 +112,6 @@ function bot:on_msg_receive(msg, config) -- The fn run whenever a message is rec msg.text = string.gsub(msg.text, config.cmd_pat..'([A-Za-z0-9-_-]+)@'..self.info.username, "/%1") msg.text_lower = msg.text:lower() end - msg = pre_process_msg(self, msg, config) for _, plugin in ipairs(self.plugins) do @@ -155,11 +158,9 @@ function bot:process_inline_query(inline_query, config) -- When an inline query if not is_whitelisted then return end end - if inline_query.query == '' then return end if inline_query.query:match('"') then inline_query.query = inline_query.query:gsub('"', '\\"') end - for _, plugin in ipairs(self.plugins) do match_inline_plugins(self, inline_query, config, plugin) end @@ -169,7 +170,6 @@ function bot:run(config) bot.init(self, config) -- Actually start the script. while self.is_started do -- Start a loop while the bot should be running. - local res = bindings.getUpdates(self, { timeout=20, offset = self.last_update+1 } ) if res then for _,v in ipairs(res.result) do -- Go through every new message. @@ -221,7 +221,7 @@ function pre_process_msg(self, msg, config) end function match_inline_plugins(self, inline_query, config, plugin) - for _, trigger in pairs(plugin.inline_triggers or {}) do + for _, trigger in ipairs(plugin.inline_triggers or {}) do if string.match(string.lower(inline_query.query), trigger) then local success, result = pcall(function() for k, pattern in pairs(plugin.inline_triggers) do @@ -241,7 +241,7 @@ function match_inline_plugins(self, inline_query, config, plugin) end function match_plugins(self, msg, config, plugin) - for _, trigger in pairs(plugin.triggers or {}) do + for _, trigger in ipairs(plugin.triggers or {}) do if string.match(msg.text_lower, trigger) then -- Check if Plugin is disabled if is_plugin_disabled_on_chat(plugin.name, msg) then return end diff --git a/miku/plugins/9gag.lua b/miku/plugins/9gag.lua index 015451c..d843898 100644 --- a/miku/plugins/9gag.lua +++ b/miku/plugins/9gag.lua @@ -10,22 +10,45 @@ 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.inline_triggers = { + "^9gag" + } ninegag.doc = [[* ]]..config.cmd_pat..[[9gag*: Gibt ein zufälliges Bild von den momentan populärsten 9GAG-Posts aus]] end +local url = "http://api-9gag.herokuapp.com/" + 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 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:inline_callback(inline_query, config) + local res, code = HTTP.request(url) + if code ~= 200 then return end + local gag = JSON.decode(res) + + local results = '[' + for n in pairs(gag) do + local title = gag[n].title:gsub('"', '\\"') + results = results..'{"type":"photo","id":"'..math.random(100000000000000000)..'","photo_url":"'..gag[n].src..'","thumb_url":"'..gag[n].src..'","caption":"'..title..'","reply_markup":{"inline_keyboard":[[{"text":"9GAG aufrufen","url":"'..gag[n].url..'"}]]}}' + if n < #gag then + results = results..',' + end + end + local results = results..']' + utilities.answer_inline_query(self, inline_query, results, 300) +end + function ninegag:action(msg, config) utilities.send_typing(self, msg.chat.id, 'upload_photo') local url, title, post_url = ninegag:get_9GAG() diff --git a/miku/plugins/adfly.lua b/miku/plugins/adfly.lua index 51d8d55..27de474 100644 --- a/miku/plugins/adfly.lua +++ b/miku/plugins/adfly.lua @@ -8,6 +8,7 @@ function adfly:init(config) adfly.triggers = { 'adf.ly/([A-Za-z0-9-_-]+)' } + adfly.inline_triggers = adfly.triggers adfly.doc = [[*adf.ly-Link*: Postet vollen Link]] end @@ -21,13 +22,24 @@ function adfly:expand_adfly_link(adfly_code) return res end -function adfly:action(msg) - local input = msg.text - if not input:match('adf.ly/([A-Za-z0-9-_-]+)') then - return +function adfly:inline_callback(inline_query, config, matches) + local adfly_code = matches[1] + local hash = 'telegram:cache:adfly:'..adfly_code + if redis:exists(hash) == false then + url = adfly:expand_adfly_link(adfly_code) + else + url = redis:get(hash) end - local adfly_code = input:match('adf.ly/([A-Za-z0-9-_-]+)') + if not url then return end + if url == 'NOTFOUND' then return end + + local results = '[{"type":"article","id":"'..math.random(100000000000000000)..'","title":"Verlängerte URL","description":"'..url..'","url":"'..url..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/generic/internet.jpg","thumb_width":165,"thumb_height":150,"hide_url":true,"input_message_content":{"message_text":"'..url..'"}}]' + utilities.answer_inline_query(self, inline_query, results, 3600, true) +end + +function adfly:action(msg, config, matches) + local adfly_code = matches[1] local hash = 'telegram:cache:adfly:'..adfly_code if redis:exists(hash) == false then local expanded_url = adfly:expand_adfly_link(adfly_code) diff --git a/miku/plugins/bImages.lua b/miku/plugins/bImages.lua index 0389e9b..0015216 100644 --- a/miku/plugins/bImages.lua +++ b/miku/plugins/bImages.lua @@ -48,7 +48,7 @@ function bImages:getImages(query) 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..'"}]]}},' + results = results..'{"type":"photo","id":"'..math.random(100000000000000000)..'","photo_url":"'..photo_url..'","thumb_url":"'..thumb_url..'","photo_width":'..images[n].width..',"photo_height":'..images[n].height..',"reply_markup":{"inline_keyboard":[[{"text":"Bing aufrufen","url":"'..images[n].webSearchUrl..'"},{"text":"Bild öffnen","url":"'..photo_url..'"}]]}},' end end diff --git a/miku/plugins/bitly.lua b/miku/plugins/bitly.lua index 0b01102..fe29d5b 100644 --- a/miku/plugins/bitly.lua +++ b/miku/plugins/bitly.lua @@ -18,6 +18,7 @@ function bitly:init(config) "j.mp/([A-Za-z0-9-_-]+)", "andib.tk/([A-Za-z0-9-_-]+)" } + bitly.inline_triggers = bitly.triggers end local BASE_URL = 'https://api-ssl.bitly.com/v3/expand' @@ -25,18 +26,39 @@ 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 res, code = https.request(url) + if code ~= 200 then return nil end local data = json.decode(res).data.expand[1] cache_data('bitly', shorturl, data) return data.long_url end +function bitly:inline_callback(inline_query, config, matches) + local shorturl = matches[1] + local hash = 'telegram:cache:bitly:'..shorturl + if redis:exists(hash) == false then + url = bitly:expand_bitly_link(shorturl) + else + local data = redis:hgetall(hash) + url = data.long_url + end + + if not url then return end + + local results = '[{"type":"article","id":"'..math.random(100000000000000000)..'","title":"Verlängerte URL","description":"'..url..'","url":"'..url..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/generic/internet.jpg","thumb_width":165,"thumb_height":150,"hide_url":true,"input_message_content":{"message_text":"'..url..'"}}]' + utilities.answer_inline_query(self, inline_query, results, 3600) +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)) + local longurl = bitly:expand_bitly_link(shorturl) + if not longurl then + utilities.send_reply(self, msg, config.errors.connection) + return + end + utilities.send_reply(self, msg, longurl) return else local data = redis:hgetall(hash) diff --git a/miku/plugins/control.lua b/miku/plugins/control.lua index db8e800..9389992 100644 --- a/miku/plugins/control.lua +++ b/miku/plugins/control.lua @@ -28,9 +28,11 @@ function control:action(msg, config) 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 + if not 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 diff --git a/miku/plugins/expand.lua b/miku/plugins/expand.lua index 4435394..476ef2f 100644 --- a/miku/plugins/expand.lua +++ b/miku/plugins/expand.lua @@ -7,6 +7,9 @@ function expand:init(config) expand.triggers = { "^/expand (https?://[%w-_%.%?%.:/%+=&]+)$" } + expand.inline_triggers = { + "^ex (https?://[%w-_%.%?%.:/%+=&]+)$" + } expand.doc = [[* ]]..config.cmd_pat..[[expand* __: Verlängert Kurz-URL (301er/302er)]] @@ -14,10 +17,26 @@ end expand.command = 'expand ' -function expand:action(msg, config, matches) +function expand:inline_callback(inline_query, config, matches) + local ok, response_headers = expand:url(matches[1]) + if not response_headers.location then + title = 'Konnte nicht erweitern' + url = matches[1] + description = 'Sende stattdessen die kurze URL' + else + title = 'Verlängerte URL' + url = response_headers.location + description = url + end + + local results = '[{"type":"article","id":"'..math.random(100000000000000000)..'","title":"'..title..'","description":"'..description..'","url":"'..url..'","thumb_url":"https://anditest.perseus.uberspace.de/inlineQuerys/generic/internet.jpg","thumb_width":165,"thumb_height":150,"hide_url":true,"input_message_content":{"message_text":"'..url..'"}}]' + utilities.answer_inline_query(self, inline_query, results, 3600) +end + +function expand:url(long_url) local response_body = {} local request_constructor = { - url = matches[1], + url = long_url, method = "HEAD", sink = ltn12.sink.table(response_body), headers = {}, @@ -25,6 +44,11 @@ function expand:action(msg, config, matches) } local ok, response_code, response_headers, response_status_line = http.request(request_constructor) + return ok, response_headers +end + +function expand:action(msg, config, matches) + local ok, response_headers = expand:url(matches[1]) if ok and response_headers.location then utilities.send_reply(self, msg, response_headers.location) return diff --git a/miku/plugins/giphy.lua b/miku/plugins/giphy.lua new file mode 100644 index 0000000..a19377d --- /dev/null +++ b/miku/plugins/giphy.lua @@ -0,0 +1,55 @@ +local giphy = {} + +local http = require('socket.http') +local URL = require('socket.url') +local JSON = require('dkjson') +local utilities = require('miku.utilities') + +function giphy:init(config) + giphy.triggers = { + "/nil" + } + giphy.inline_triggers = { + "^(gif) (.+)", + "^(gif)$" + } +end + +local BASE_URL = 'http://api.giphy.com/v1/gifs' +local apikey = 'dc6zaTOxFJmzC' -- public beta key + +function giphy:get_gifs(query) + if not query then + url = BASE_URL..'/trending?api_key='..apikey + else + url = BASE_URL..'/search?q='..URL.escape(query)..'&api_key='..apikey + end + local res, code = http.request(url) + if code ~= 200 then return nil end + return JSON.decode(res).data +end + +function giphy:inline_callback(inline_query, config, matches) + if not matches[2] then + data = giphy:get_gifs() + else + data = giphy:get_gifs(matches[2]) + end + if not data then return end + if not data[1] then return end + local results = '[' + + for n in pairs(data) do + results = results..'{"type":"mpeg4_gif","id":"'..math.random(100000000000000000)..'","mpeg4_url":"'..data[n].images.original.mp4..'","thumb_url":"'..data[n].images.fixed_height.url..'","mpeg4_width":'..data[n].images.original.width..',"mp4_height":'..data[n].images.original.height..'}' + if n < #data then + results = results..',' + end + end + local results = results..']' + utilities.answer_inline_query(self, inline_query, results, 3600) +end + +function giphy:action() +end + +return giphy \ No newline at end of file diff --git a/miku/plugins/qr.lua b/miku/plugins/qr.lua index f50fe75..a4589f6 100644 --- a/miku/plugins/qr.lua +++ b/miku/plugins/qr.lua @@ -9,6 +9,9 @@ function qr:init(config) '^/qr "(%w+)" "(%w+)" (.+)$', "^/qr (.+)$" } + qr.inline_triggers = { + "^qr (https?://[%w-_%.%?%.:/%+=&]+)" + } qr.doc = [[* ]]..config.cmd_pat..[[qr* __: Sendet QR-Code mit diesem Text *]]..config.cmd_pat..[[qr* _"[Hintergrundfarbe]"_ _"[Datenfarbe]"_ _[Text]_ @@ -40,11 +43,15 @@ function qr:get_hex(str) return str end -function qr:qr(text, color, bgcolor) +function qr:qr(text, color, bgcolor, img_format) 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 img_format then + url = url..'&format='..img_format + end if color then url = url.."&color="..qr:get_hex(color) @@ -66,6 +73,30 @@ function qr:qr(text, color, bgcolor) return nil end +function qr:inline_callback(inline_query, config, matches) + local text = matches[1] + if string.len(text) > 200 then return end + local image_url = qr:qr(text, nil, nil, 'jpg') + if not image_url then return end + + local results = '[{"type":"photo","id":"'..math.random(100000000000000000)..'","photo_url":"'..image_url..'","thumb_url":"'..image_url..'","photo_width":600,"photo_height":600,"caption":"'..text..'"},' + + local i = 0 + while i < 29 do + i = i+1 + local color = math.random(255) + local bgcolor = math.random(255) + local image_url = qr:qr(text, color, bgcolor, 'jpg') + results = results..'{"type":"photo","id":"'..math.random(100000000000000000)..'","photo_url":"'..image_url..'","thumb_url":"'..image_url..'","photo_width":600,"photo_height":600,"caption":"'..text..'"}' + if i < 29 then + results = results..',' + end + end + + local results = results..']' + utilities.answer_inline_query(self, inline_query, results, 10000) +end + function qr:action(msg, config, matches) local text = matches[1] local color diff --git a/miku/plugins/reddit.lua b/miku/plugins/reddit.lua index fcb1ef9..6653747 100644 --- a/miku/plugins/reddit.lua +++ b/miku/plugins/reddit.lua @@ -66,7 +66,7 @@ function reddit:action(msg, config) end local jstr, res = https.request(url) if res ~= 200 then - utilities.send_reply(self, msg, config.errors.connection) + utilities.send_reply(self, msg, config.errors.results) else local jdat = JSON.decode(jstr) if #jdat.data.children == 0 then diff --git a/miku/plugins/rss.lua b/miku/plugins/rss.lua index 74a23ba..aeb0e30 100644 --- a/miku/plugins/rss.lua +++ b/miku/plugins/rss.lua @@ -344,7 +344,7 @@ function rss:cron(self_plz) else content = '' end - text = text..'\n[[#RSS]] *'..title..'*\n'..utilities.trim(utilities.markdown_escape_simple(content))..' [Weiterlesen]('..link..')\n' + 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 diff --git a/miku/plugins/twitter.lua b/miku/plugins/twitter.lua index 10e6173..067fe0f 100644 --- a/miku/plugins/twitter.lua +++ b/miku/plugins/twitter.lua @@ -27,7 +27,8 @@ function twitter:init(config) end twitter.triggers = { - 'twitter.com/[^/]+/statuse?s?/([0-9]+)' + 'twitter.com/[^/]+/statuse?s?/([0-9]+)', + 'twitter.com/statuse?s?/([0-9]+)' } twitter.doc = [[*Twitter-Link*: Postet Tweet]] end @@ -46,12 +47,13 @@ local client = OAuth.new(consumer_key, consumer_secret, { OAuthTokenSecret = access_token_secret }) -function twitter:action(msg) +function twitter:action(msg, config, matches) - if not msg.text:match('twitter.com/[^/]+/statuse?s?/([0-9]+)') then - return + if not matches[2] then + id = matches[1] + else + id = matches[2] end - local id = msg.text:match('twitter.com/[^/]+/statuse?s?/([0-9]+)') local twitter_url = "https://api.twitter.com/1.1/statuses/show/" .. id.. ".json" local response_code, response_headers, response_status_line, response_body = client:PerformRequest("GET", twitter_url) diff --git a/miku/plugins/youtube.lua b/miku/plugins/youtube.lua index 2fa3e59..cbb1c38 100644 --- a/miku/plugins/youtube.lua +++ b/miku/plugins/youtube.lua @@ -98,9 +98,7 @@ function get_yt_thumbnail(data) end function send_youtube_data(data, msg, self, link, sendpic) - local title = data.snippet.localized.title - local title = title:gsub('%*', '\\*') - local title = title:gsub('`', '\\`') + local title = utilities.markdown_escape_simple(data.snippet.localized.title) -- local description = data.snippet.localized.description local uploader = data.snippet.channelTitle local upload_date = makeOurDate(data.snippet.publishedAt) diff --git a/miku/utilities.lua b/miku/utilities.lua index fd5a211..bf04b8f 100644 --- a/miku/utilities.lua +++ b/miku/utilities.lua @@ -56,7 +56,7 @@ end -- https://core.telegram.org/bots/api#sendphoto function utilities:send_photo(chat_id, file, text, reply_to_message_id, reply_markup) if not file then return false end - local output, error = bindings.request(self, 'sendPhoto', { + local output = bindings.request(self, 'sendPhoto', { chat_id = chat_id, caption = text or nil, reply_to_message_id = reply_to_message_id, @@ -66,7 +66,6 @@ function utilities:send_photo(chat_id, file, text, reply_to_message_id, reply_ma os.remove(file) print("Deleted: "..file) end -vardump(error) return output end @@ -497,12 +496,12 @@ function utilities.markdown_escape(text) text = text:gsub('`', '\\`') return text end - + function utilities.markdown_escape_simple(text) text = text:gsub('_', '\\_') - text = text:gsub('%*', '\\*') - text = text:gsub('`', '\\`') - return text + text = text:gsub('%*', '\\*') + text = text:gsub('`', '\\`') + return text end utilities.md_escape = utilities.markdown_escape @@ -999,4 +998,4 @@ function table.contains(table, element) return false end -return utilities +return utilities \ No newline at end of file