diff --git a/otouto/plugins/settings.lua b/otouto/plugins/settings.lua index f0af030..b0997dc 100644 --- a/otouto/plugins/settings.lua +++ b/otouto/plugins/settings.lua @@ -1,19 +1,11 @@ --- SWITCH YOUR EDITOR TO UTF-8 (Notepad++ sets this file to ANSI) local settings = {} settings.triggers = { "^(⚙ [Ee]instellungen)$", "^(/settings)$", - "^(↩️ [Zz]urück)$", - "^(💤 [Aa][Ff][Kk]%-[Kk]eyboard einschalten)$", - "^(💤 [Aa][Ff][Kk]%-[Kk]eyboard ausschalten)$", - "^(❌ [Ee]instellungen verstecken)$", - "^(▶️ [Vv]ideoauflösung für [Yy]ou[Tt]ube%-[Dd][Ll] einstellen)$", - "^(▶️ 144p)$", - "^(▶️ 180p)$", - "^(▶️ 360p [Ww]eb[Mm])$", - "^(▶️ 360p [Mm][Pp]4)$", - "^(▶️ 720p)$" + "^(💤 [Aa][Ff][Kk]%-[Kk]eyboard einschalten)", + "^(💤 [Aa][Ff][Kk]%-[Kk]eyboard ausschalten)", + "^(❌ [Ee]instellungen verstecken)" } --[[ @@ -31,25 +23,12 @@ function settings:keyboard(user_id) else afk_button = '{"text":"💤 AFK-Keyboard einschalten"}' end - local youtube_dl_res_button = '{"text":"▶️ Videoauflösung für YouTube-DL einstellen"}' local hide_settings_button = '{"text":"❌ Einstellungen verstecken"}' - local settings_keyboard = '[['..afk_button..','..youtube_dl_res_button..'],['..hide_settings_button..']]' + local settings_keyboard = '[['..afk_button..','..hide_settings_button..']]' return settings_keyboard end -function settings:youtube_dl_keyboard() - local worst = '{"text":"▶️ 144p"}' - local still_worse = '{"text":"▶️ 180p"}' - local better_webm = '{"text":"▶️ 360p WebM"}' - local better_mp4 = '{"text":"▶️ 360p MP4"}' - local best = '{"text":"▶️ 720p"}' - local back = '{"text":"↩️ Zurück"}' - - local youtube_dl_keyboard = '[['..best..','..better_mp4..','..better_webm..'],['..still_worse..','..worst..'],['..back..']]' - return youtube_dl_keyboard -end - function settings:action(msg, config, matches) if msg.chat.type ~= "private" then return @@ -57,17 +36,10 @@ function settings:action(msg, config, matches) local hash = 'user:'..msg.from.id - -- General - if matches[1] == '⚙ Einstellungen' or matches[1] == '/settings' or matches[1] == '↩️ Zurück' then + if matches[1] == '⚙ Einstellungen' or matches[1] == '/settings' then utilities.send_reply(self, msg, 'Was möchtest du einstellen?', false, '{"keyboard":'..settings:keyboard(msg.from.id)..', "one_time_keyboard":true, "selective":true, "resize_keyboard":true}') return - elseif matches[1] == '❌ Einstellungen verstecken' then - utilities.send_reply(self, msg, 'Um die Einstellungen wieder einzublenden, führe /settings aus.', true, '{"hide_keyboard":true}') - return - end - - -- AFK keyboard - if matches[1] == '💤 AFK-Keyboard einschalten' then + elseif matches[1] == '💤 AFK-Keyboard einschalten' then redis:hset(hash, 'afk_keyboard', 'true') utilities.send_reply(self, msg, 'Das AFK-Keyboard wurde erfolgreich *eingeschaltet*.', true, '{"keyboard":'..settings:keyboard(msg.from.id)..', "one_time_keyboard":true, "selective":true, "resize_keyboard":true}') return @@ -75,43 +47,10 @@ function settings:action(msg, config, matches) redis:hset(hash, 'afk_keyboard', 'false') utilities.send_reply(self, msg, 'Das AFK-Keyboard wurde erfolgreich *ausgeschaltet*.', true, '{"keyboard":'..settings:keyboard(msg.from.id)..', "one_time_keyboard":true, "selective":true, "resize_keyboard":true}') return - end - - -- YouTube-DL video resolution - -- 144p: 17 - -- 180p: 36 - -- 360p WebM: 43 - -- 360p MP4: 18 - -- 720p: 22 - if matches[1] == '▶️ Videoauflösung für YouTube-DL einstellen' then - utilities.send_reply(self, msg, 'Welche Videoauflösung bevorzugst du?\nHINWEIS: Dies gilt nur für /mp4. Wenn die gewählte Auflösung nicht zur Verfügung steht, wird die nächsthöhere bzw. bei 720p die nächstniedrigere genommen.', 'HTML', '{"keyboard":'..settings:youtube_dl_keyboard()..', "one_time_keyboard":true, "selective":true, "resize_keyboard":true}') - elseif matches[1] == '▶️ 144p' then - local resolution_order = '17/36/43/18/22' - redis:hset(hash, 'yt_dl_res_ordner', resolution_order) - utilities.send_reply(self, msg, 'Die Reihenfolge ist jetzt folgende:\n1) 144p\n2) 180p\n3) 360p WebM\n4) 360p MP4\n5) 720p', true, '{"keyboard":'..settings:keyboard(msg.from.id)..', "one_time_keyboard":true, "selective":true, "resize_keyboard":true}') - return - elseif matches[1] == '▶️ 180p' then - local resolution_order = '36/17/43/18/22' - redis:hset(hash, 'yt_dl_res_ordner', resolution_order) - utilities.send_reply(self, msg, 'Die Reihenfolge ist jetzt folgende:\n1) 180p\n2) 144p\n3) 360p WebM\n4) 360p MP4\n5) 720p', true, '{"keyboard":'..settings:keyboard(msg.from.id)..', "one_time_keyboard":true, "selective":true, "resize_keyboard":true}') - return - elseif matches[1] == '▶️ 360p WebM' then - local resolution_order = '43/18/36/17/22' - redis:hset(hash, 'yt_dl_res_ordner', resolution_order) - utilities.send_reply(self, msg, 'Die Reihenfolge ist jetzt folgende:\n1) 360p WebM\n2) 360p MP4\n3) 180p\n4) 144p\n5) 720p', true, '{"keyboard":'..settings:keyboard(msg.from.id)..', "one_time_keyboard":true, "selective":true, "resize_keyboard":true}') - return - elseif matches[1] == '▶️ 360p MP4' then - local resolution_order = '18/43/36/17/22' - redis:hset(hash, 'yt_dl_res_ordner', resolution_order) - utilities.send_reply(self, msg, 'Die Reihenfolge ist jetzt folgende:\n1) 360p MP4\n2) 360p WebM\n3) 180p\n4) 144p\n5) 720p', true, '{"keyboard":'..settings:keyboard(msg.from.id)..', "one_time_keyboard":true, "selective":true, "resize_keyboard":true}') - return - elseif matches[1] == '▶️ 720p' then - local resolution_order = '22/18/43/36/17' - redis:hset(hash, 'yt_dl_res_ordner', resolution_order) - utilities.send_reply(self, msg, 'Die Reihenfolge ist jetzt folgende:\n1) 720p\n2) 360p MP4\n3) 360p WebM\n4) 180p\n5) 144p', true, '{"keyboard":'..settings:keyboard(msg.from.id)..', "one_time_keyboard":true, "selective":true, "resize_keyboard":true}') + elseif matches[1] == '❌ Einstellungen verstecken' then + utilities.send_reply(self, msg, 'Um die Einstellungen wieder einzublenden, führe /settings aus.', true, '{"hide_keyboard":true}') return end - end return settings \ No newline at end of file diff --git a/otouto/plugins/youtube_dl.lua b/otouto/plugins/youtube_dl.lua index 7ceaa15..3ee8fa1 100644 --- a/otouto/plugins/youtube_dl.lua +++ b/otouto/plugins/youtube_dl.lua @@ -18,11 +18,62 @@ end youtube_dl.command = 'mp3 , /mp4 ' -function youtube_dl:convert_video(id, chosen_res) - local ytdl_json = io.popen('youtube-dl -f '..chosen_res..' --max-filesize 49m -j https://www.youtube.com/watch/?v='..id):read('*all') +function youtube_dl:get_availabe_formats(id, hash) + local ytdl_json = io.popen('youtube-dl -j https://www.youtube.com/watch/?v='..id):read('*all') if not ytdl_json then return end local data = json.decode(ytdl_json) - return data + + local available_formats = {} + redis:hset(hash, 'duration', data.duration) + + -- Building table with infos + for n=1, #data.formats do + local vid_format = data.formats[n].format + local format_num = vid_format:match('^(%d+) ') + local valid_nums = {['17'] = true, ['36'] = true, ['43'] = true, ['18'] = true, ['22'] = true} + if not vid_format:match('DASH') and valid_nums[format_num] then -- We don't want DASH videos! + local format_info = {} + format_info.format = format_num + local hash = hash..':'..format_num + if format_num == '17' then + format_info.pretty_format = '144p' + elseif format_num == '36' then + format_info.pretty_format = '180p' + elseif format_num == '43' then + format_info.pretty_format = '360p WebM' + elseif format_num == '18' then + format_info.pretty_format = '360p MP4' + elseif format_num == '22' then + format_info.pretty_format = '720p' + end + format_info.ext = data.formats[n].ext + local url = data.formats[n].url + local headers = get_http_header(url) + local full_url = headers.location + local headers = get_http_header(full_url) -- first was for 302, this get's use the size + if headers.location then -- There are some videos where there is a "chain" of 302... repeat this, until we get the LAST url! + repeat + headers = get_http_header(headers.location) + until not headers.location + end + + format_info.url = full_url + local size = tonumber(headers["content-length"]) + format_info.size = size + format_info.pretty_size = string.gsub(tostring(round(size / 1048576, 2)), '%.', ',')..' MB' -- 1048576 = 1024*1024 + available_formats[#available_formats+1] = format_info + redis:hset(hash, 'ext', format_info.ext) + redis:hset(hash, 'format', format_info.pretty_format) + redis:hset(hash, 'url', full_url) + redis:hset(hash, 'size', size) + redis:hset(hash, 'height', data.formats[n].height) + redis:hset(hash, 'width', data.formats[n].width) + redis:hset(hash, 'pretty_size', format_info.pretty_size) + redis:expire(hash, 7889400) + end + end + + return available_formats end function youtube_dl:convert_audio(id) @@ -34,45 +85,89 @@ function youtube_dl:convert_audio(id) return '/tmp/'..audio..'.mp3' end -function youtube_dl:action(msg, config, matches) - local id = matches[2] - local hash = 'user:'..msg.from.id - local chosen_res = redis:hget(hash, 'yt_dl_res_ordner') - if not chosen_res then - chosen_res = '22/18/43/36/17' +function youtube_dl:callback(callback, msg, self, config, input) + utilities.answer_callback_query(self, callback, 'Informationen werden verarbeitet...') + local video_id = input:match('(.+)@') + local vid_format = input:match('@(%d+)') + local hash = 'telegram:cache:youtube_dl:mp4:'..video_id + local format_hash = hash..':'..vid_format + if not redis:exists(format_hash) then + youtube_dl:get_availabe_formats(video_id, hash) end + + local duration = redis:hget(hash, 'duration') + local format_info = redis:hgetall(format_hash) + + local full_url = format_info.url + local width = format_info.width + local height = format_info.height + local ext = format_info.ext + local pretty_size = format_info.pretty_size + local size = tonumber(format_info.size) + local format = format_info.format + + if size > 52420000 then + utilities.edit_message(self, msg.chat.id, msg.message_id, 'Direktlink zum Video ('..format..', '..pretty_size..')', nil, 'HTML') + return + end + + utilities.edit_message(self, msg.chat.id, msg.message_id, 'Video wird hochgeladen', nil, 'HTML') + utilities.send_typing(self, msg.chat.id, 'upload_video') + + local file = download_to_file(full_url, video_id..'.'..ext) + if not file then return end + utilities.send_video(self, msg.chat.id, file, nil, msg.message_id, duration, width, height) + utilities.edit_message(self, msg.chat.id, msg.message_id, 'Direktlink zum Video ('..format..', '..pretty_size..')', nil, 'HTML') +end + +function youtube_dl:action(msg, config, matches) + if msg.chat.type ~= 'private' then + utilities.send_reply(self, msg, 'Dieses Plugin kann nur im Privatchat benutzt werden') + return + end + local id = matches[2] if matches[1] == 'mp4' then - local first_msg = utilities.send_reply(self, msg, 'Video wird heruntergeladen...', 'HTML') - utilities.send_typing(self, msg.chat.id, 'upload_video') - local data = youtube_dl:convert_video(id, chosen_res) - if not data then - utilities.edit_message(self, msg.chat.id, first_msg.result.message_id, config.errors.results) - return - end + local hash = 'telegram:cache:youtube_dl:mp4:'..id + local first_msg = utilities.send_reply(self, msg, 'Verfügbare Videoformate werden ausgelesen...', 'HTML') + local callback_keyboard = redis:hget(hash, 'keyboard') + if not callback_keyboard then + utilities.send_typing(self, msg.chat.id, 'typing') + local available_formats = youtube_dl:get_availabe_formats(id, hash) + if not available_formats then + utilities.edit_message(self, msg.chat.id, first_msg.result.message_id, config.errors.results) + return + end - local ext = data.ext - local resolution = data.resolution - local url = data.url - local headers = get_http_header(url) -- need to get full url, because first url is actually a 302 - local full_url = headers.location - if not full_url then - utilities.edit_message(self, msg.chat.id, first_msg.result.message_id, config.errors.connection) - return + local callback_buttons = {} + for n=1, #available_formats do + local video = available_formats[n] + local format = video.format + local size = video.size + local pretty_size = video.pretty_size + if size > 52420000 then + pretty_format = video.pretty_format..' ('..pretty_size..', nur Link)' + else + pretty_format = video.pretty_format..' ('..pretty_size..')' + end + local button = '{"text":"'..pretty_format..'","callback_data":"@'..self.info.username..' youtube_dl:'..id..'@'..format..'"}' + callback_buttons[#callback_buttons+1] = button + end + + local keyboard = '{"inline_keyboard":[' + for button in pairs(callback_buttons) do + keyboard = keyboard..'['..callback_buttons[button]..']' + if button < #callback_buttons then + keyboard = keyboard..',' + end + end + + callback_keyboard = keyboard..']}' + redis:hset(hash, 'keyboard', callback_keyboard) + redis:expire(hash, 7889400) end - - local headers = get_http_header(full_url) -- YES TWO FCKING HEAD REQUESTS - if tonumber(headers["content-length"]) > 52420000 then - utilities.edit_message(self, msg.chat.id, first_msg.result.message_id, 'Das Video überschreitet die Grenze von 50 MB!\nDirektlink zum Video ('..resolution..')', nil, 'HTML') - return - end - local file = download_to_file(full_url, id..'.'..ext) - local width = data.width - local height = data.width - local duration = data.duration - utilities.edit_message(self, msg.chat.id, first_msg.result.message_id, 'Direktlink zum Video ('..resolution..')', nil, 'HTML') - utilities.send_video(self, msg.chat.id, file, nil, msg.message_id, duration, width, height) - return + utilities.edit_message(self, msg.chat.id, first_msg.result.message_id, 'Wähle die gewünschte Auflösung.', nil, nil, callback_keyboard) + return end if matches[1] == 'mp3' then