diff --git a/otouto/plugins/images.lua b/otouto/plugins/images.lua index a546ba4..74de865 100644 --- a/otouto/plugins/images.lua +++ b/otouto/plugins/images.lua @@ -7,10 +7,16 @@ images.triggers = { } function images:action(msg) - utilities.send_typing(self, msg.chat.id, 'upload_photo') - local url = matches[1] - local file = download_to_file(url) - utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id) + utilities.send_typing(self, msg.chat.id, 'upload_photo') + 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 diff --git a/otouto/plugins/media.lua b/otouto/plugins/media.lua index f566995..b082f40 100644 --- a/otouto/plugins/media.lua +++ b/otouto/plugins/media.lua @@ -29,58 +29,10 @@ media.triggers = { function media:action(msg) local url = matches[1] local ext = matches[2] - local hash = 'telegram:cache:sent_file' - local cached_file_id = redis:hget(hash..':'..url, 'file_id') - local cached_last_modified = redis:hget(hash..':'..url, 'last_modified') local receiver = msg.chat.id - - -- Last-Modified-Header auslesen - local doer = HTTP - local do_redir = true - if url:match('^https') then - doer = HTTPS - do_redir = false - end - local _, c, h = doer.request { - method = "HEAD", - url = url, - redirect = do_redir - } - - if c ~= 200 then - if cached_file_id then - redis:del(hash..':'..url) - end - return - end - - utilities.send_typing(self, receiver, 'upload_document') - if not h["last-modified"] and not h["Last-Modified"] then - nocache = true - last_modified = nil - else - nocache = false - last_modified = h["last-modified"] - if not last_modified then - last_modified = h["Last-Modified"] - end - end + 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 not nocache then - if last_modified == cached_last_modified then - print('File not modified and already cached') - nocache = true - file = cached_file_id - else - print('File cached, but modified or not already cached. (Re)downloading...') - file = download_to_file(url) - end - else - print('No Last-Modified header!') - file = download_to_file(url) - end if ext == 'gif' then print('send gif') @@ -100,20 +52,7 @@ function media:action(msg) if not result then return end -- Cache File-ID und Last-Modified-Header in Redis - if result.result.video then - file_id = result.result.video.file_id - elseif result.result.audio then - file_id = result.result.audio.file_id - elseif result.result.voice then - file_id = result.result.voice.file_id - else - file_id = result.result.document.file_id - end - redis:hset(hash..':'..url, 'file_id', file_id) - redis:hset(hash..':'..url, 'last_modified', last_modified) - -- Why do we set a TTL? Because Telegram recycles outgoing file_id's - -- See: https://core.telegram.org/bots/faq#can-i-count-on-file-ids-to-be-persistent - redis:expire(hash..':'..url, 5259600) -- 2 months + cache_file(result, url, last_modified) end return media diff --git a/otouto/utilities.lua b/otouto/utilities.lua index 484a895..025b85e 100644 --- a/otouto/utilities.lua +++ b/otouto/utilities.lua @@ -724,6 +724,91 @@ function cache_data(plugin, query, data, timeout, typ) end end +-- Caches file_id and last_modified +-- result = result of send_X() (see media.lua) +function cache_file(result, url, last_modified) + local hash = 'telegram:cache:sent_file' + if result.result.video then + file_id = result.result.video.file_id + elseif result.result.audio then + file_id = result.result.audio.file_id + elseif result.result.voice then + file_id = result.result.voice.file_id + elseif result.result.document then + file_id = result.result.document.file_id + elseif result.result.photo then + local lv = #result.result.photo + file_id = result.result.photo[lv].file_id + end + print('Caching File...') + redis:hset(hash..':'..url, 'file_id', file_id) + redis:hset(hash..':'..url, 'last_modified', last_modified) + -- Why do we set a TTL? Because Telegram recycles outgoing file_id's + -- See: https://core.telegram.org/bots/faq#can-i-count-on-file-ids-to-be-persistent + redis:expire(hash..':'..url, 5259600) -- 2 months +end + +function get_last_modified_header(url) + local doer = HTTP + local do_redir = true + if url:match('^https') then + doer = HTTPS + do_redir = false + end + local _, code, header = doer.request { + method = "HEAD", + url = url, + redirect = do_redir + } + if header["last-modified"] then + last_modified = header["last-modified"] + elseif header["Last-Modified"] then + last_modified = header["Last-Modified"] + end + return last_modified, code +end + +-- only url is needed! +function get_cached_file(url, file_name, receiver, chat_action, self) + local hash = 'telegram:cache:sent_file' + local cached_file_id = redis:hget(hash..':'..url, 'file_id') + local cached_last_modified = redis:hget(hash..':'..url, 'last_modified') + + -- get last-modified header + local last_modified, code = get_last_modified_header(url) + if code ~= 200 then + if cached_file_id then + redis:del(hash..':'..url) + end + return + end + + if not last_modified then + nocache = true + else + nocache = false + end + + if receiver and chat_action and self then + utilities.send_typing(self, receiver, chat_action) + end + + if not nocache then + if last_modified == cached_last_modified then + print('File not modified and already cached') + nocache = true + file = cached_file_id + else + print('File cached, but modified or not already cached. (Re)downloading...') + file = download_to_file(url, file_name) + end + else + print('No Last-Modified header!') + file = download_to_file(url, file_name) + end + return file, last_modified, nocache +end + -- converts total amount of seconds (e.g. 65 seconds) to human redable time (e.g. 1:05 minutes) function makeHumanTime(totalseconds) local seconds = totalseconds % 60