From 80f45020ff9090905cb68b86c95e4bc0c82ee22d Mon Sep 17 00:00:00 2001 From: projectdx Date: Wed, 31 Dec 2025 21:58:37 +0900 Subject: [PATCH] feat: Refine Discord embed UI and enhance video extraction by adding iframe cookie acquisition and in-session m3u8 resolution parsing. --- mod_ohli24.py | 80 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/mod_ohli24.py b/mod_ohli24.py index d849da0..a773f45 100644 --- a/mod_ohli24.py +++ b/mod_ohli24.py @@ -1266,32 +1266,36 @@ class LogicOhli24(PluginModuleBase): author_name = f"{season_ep_str} โ€ข Ohli24" embed = { - "title": title, + "title": f"๐Ÿ“บ {title}", "description": desc, - "color": 5763719, # Green (0x57F287) + "color": 0x5865F2, # Discord Blurple "author": { "name": author_name, - "icon_url": "https://i.imgur.com/4M34hi2.png" # Optional generic icon + "icon_url": "https://i.imgur.com/4M34hi2.png" }, "fields": [ { - "name": "ํŒŒ์ผ๋ช…", - "value": filename if filename else "์•Œ ์ˆ˜ ์—†์Œ", + "name": "๐Ÿ“ ํŒŒ์ผ๋ช…", + "value": f"`{filename}`" if filename else "์•Œ ์ˆ˜ ์—†์Œ", "inline": False } ], "footer": { - "text": f"FlaskFarm Ohli24 โ€ข {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}" - } + "text": "FlaskFarm Ohli24", + "icon_url": "https://i.imgur.com/4M34hi2.png" + }, + "timestamp": datetime.now().isoformat() } if image_url: - embed["thumbnail"] = { - "url": image_url - } + # image๋Š” ํฐ ์ด๋ฏธ์ง€ (ํ•˜๋‹จ ์ „์ฒด ๋„ˆ๋น„) + embed["image"] = {"url": image_url} + # thumbnail์€ ์ž‘์€ ์šฐ์ธก ์ƒ๋‹จ ์ด๋ฏธ์ง€ (์„ ํƒ์ ) + # embed["thumbnail"] = {"url": image_url} message = { "username": "Ohli24 Downloader", + "avatar_url": "https://i.imgur.com/4M34hi2.png", "embeds": [embed] } @@ -1593,11 +1597,21 @@ class Ohli24QueueEntity(FfmpegQueueEntity): if proxies: scraper.proxies = {"http": proxies["http"], "https": proxies["https"]} - # getVideo API ํ˜ธ์ถœ # iframe ๋„๋ฉ”์ธ ์ž๋™ ๊ฐ์ง€ (cdndania.com -> michealcdn.com ๋“ฑ) parsed_iframe = parse.urlparse(iframe_src) iframe_domain = f"{parsed_iframe.scheme}://{parsed_iframe.netloc}" + # [CRITICAL] iframe ํŽ˜์ด์ง€ ๋จผ์ € ๋ฐฉ๋ฌธํ•˜์—ฌ ์„ธ์…˜ ์ฟ ํ‚ค ํš๋“ + encoded_referer = parse.quote(referer_url, safe=":/?#[]@!$&'()*+,;=%") + iframe_headers = { + "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", + "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8", + "referer": encoded_referer, + } + logger.debug(f"Visiting iframe page for cookies: {iframe_src}") + scraper.get(iframe_src, headers=iframe_headers, timeout=30, proxies=proxies) + + # getVideo API ํ˜ธ์ถœ api_url = f"{iframe_domain}/player/index.php?data={video_id}&do=getVideo" headers = { "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36", @@ -1625,6 +1639,28 @@ class Ohli24QueueEntity(FfmpegQueueEntity): if video_url: logger.info(f"Found video URL via API: {video_url}") + # [RESOLUTION PARSING] - ๊ฐ™์€ ์„ธ์…˜์œผ๋กœ m3u8 ํŒŒ์‹ฑ (์ฟ ํ‚ค ์œ ์ง€) + try: + m3u8_headers = { + "referer": iframe_src, + "origin": iframe_domain, + "accept": "*/*", + } + m3u8_resp = scraper.get(video_url, headers=m3u8_headers, timeout=10, proxies=proxies) + m3u8_content = m3u8_resp.text + logger.debug(f"m3u8 content (first 300 chars): {m3u8_content[:300]}") + + if "#EXT-X-STREAM-INF" in m3u8_content: + for line in m3u8_content.strip().split('\n'): + if line.startswith('#EXT-X-STREAM-INF'): + res_match = re.search(r'RESOLUTION=(\d+)x(\d+)', line) + if res_match: + resolution = int(res_match.group(2)) # height + if resolution: + logger.info(f"Detected resolution from m3u8: {resolution}p") + except Exception as res_err: + logger.warning(f"Resolution parsing failed: {res_err}") + # VTT ์ž๋ง‰ ํ™•์ธ (์žˆ๋Š” ๊ฒฝ์šฐ) vtt_url = data.get("videoSubtitle") if vtt_url: @@ -1696,28 +1732,6 @@ class Ohli24QueueEntity(FfmpegQueueEntity): logger.error(f"Error in extract_video_from_cdndania: {e}") logger.error(traceback.format_exc()) - # m3u8 master playlist์—์„œ ํ•ด์ƒ๋„ ํŒŒ์‹ฑ (์ถ”๊ฐ€ ์š”์ฒญ 1ํšŒ) - if video_url and not resolution: - try: - from curl_cffi import requests as cffi_requests - scraper = cffi_requests.Session(impersonate="chrome120") - proxies = LogicOhli24.get_proxies() - m3u8_headers = {"referer": iframe_src} - m3u8_resp = scraper.get(video_url, headers=m3u8_headers, timeout=10, proxies=proxies) - m3u8_content = m3u8_resp.text - - if "#EXT-X-STREAM-INF" in m3u8_content: - # ๋งˆ์ง€๋ง‰(์ตœ๊ณ  ํ’ˆ์งˆ) ์ŠคํŠธ๋ฆผ์˜ ํ•ด์ƒ๋„ ์ถ”์ถœ - for line in m3u8_content.strip().split('\n'): - if line.startswith('#EXT-X-STREAM-INF'): - res_match = re.search(r'RESOLUTION=(\d+)x(\d+)', line) - if res_match: - resolution = int(res_match.group(2)) # height - if resolution: - logger.info(f"Detected resolution from m3u8: {resolution}p") - except Exception as res_err: - logger.warning(f"Failed to parse resolution from m3u8: {res_err}") - return video_url, vtt_url, cookies_file, resolution