- File-ID-Caching ausgegliedert

- Images cached jetzt auch File-IDs
This commit is contained in:
Andreas Bielawski 2016-07-05 19:21:37 +02:00
parent 77515f6cdb
commit 153da30435
3 changed files with 97 additions and 67 deletions

View File

@ -9,8 +9,14 @@ images.triggers = {
function images:action(msg) function images:action(msg)
utilities.send_typing(self, msg.chat.id, 'upload_photo') utilities.send_typing(self, msg.chat.id, 'upload_photo')
local url = matches[1] local url = matches[1]
local file = download_to_file(url) local file, last_modified, nocache = get_cached_file(url, nil, msg.chat.id, 'upload_photo', self)
utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id) local result = utilities.send_photo(self, msg.chat.id, file, nil, msg.message_id)
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 end
return images return images

View File

@ -29,59 +29,11 @@ media.triggers = {
function media:action(msg) function media:action(msg)
local url = matches[1] local url = matches[1]
local ext = matches[2] 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 local receiver = msg.chat.id
-- Last-Modified-Header auslesen local file, last_modified, nocache = get_cached_file(url, nil, msg.chat.id, 'upload_document', self)
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 mime_type = mimetype.get_content_type_no_sub(ext) 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 if ext == 'gif' then
print('send gif') print('send gif')
result = utilities.send_document(self, receiver, file, nil, msg.message_id) result = utilities.send_document(self, receiver, file, nil, msg.message_id)
@ -100,20 +52,7 @@ function media:action(msg)
if not result then return end if not result then return end
-- Cache File-ID und Last-Modified-Header in Redis -- Cache File-ID und Last-Modified-Header in Redis
if result.result.video then cache_file(result, url, last_modified)
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
end end
return media return media

View File

@ -724,6 +724,91 @@ function cache_data(plugin, query, data, timeout, typ)
end end
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) -- converts total amount of seconds (e.g. 65 seconds) to human redable time (e.g. 1:05 minutes)
function makeHumanTime(totalseconds) function makeHumanTime(totalseconds)
local seconds = totalseconds % 60 local seconds = totalseconds % 60