feat: implement downloading and processing of Kick and Twitch URLs
This commit is contained in:
+37
-10
@@ -113,7 +113,7 @@ async def status(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
elif qsize > 0:
|
||||
await update.message.reply_text(f"⏳ {qsize} videos en cola, iniciando pronto...")
|
||||
else:
|
||||
await update.message.reply_text("💤 Sin actividad. Mandame un link de YouTube.")
|
||||
await update.message.reply_text("💤 Sin actividad. Mandame un link de YouTube, Twitch o Kick.")
|
||||
|
||||
|
||||
async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
@@ -125,9 +125,9 @@ async def handle_message(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||
log.warning(f" Ignoring unauthorized chat_id={chat_id}")
|
||||
return
|
||||
|
||||
if not re.search(r"(youtube\.com|youtu\.be)", text):
|
||||
log.info(" Not a YouTube URL, ignoring.")
|
||||
await update.message.reply_text("❌ Mandame un link de YouTube (youtube.com o youtu.be).")
|
||||
if not re.search(r"(youtube\.com|youtu\.be|twitch\.tv|kick\.com)", text):
|
||||
log.info(" Not a YouTube, Twitch or Kick URL, ignoring.")
|
||||
await update.message.reply_text("❌ Mandame un link de YouTube, Twitch o Kick.")
|
||||
return
|
||||
|
||||
qsize = queue.qsize()
|
||||
@@ -206,10 +206,37 @@ async def process_queue(bot):
|
||||
log.info(f"[queue] Job done. Queue size now: {queue.qsize()}")
|
||||
|
||||
|
||||
def get_yt_id(url: str) -> str:
|
||||
"""Extract YouTube video ID from URL."""
|
||||
match = re.search(r"(?:v=|\/shorts\/|\/embed\/|\/v\/|youtu\.be\/)([a-zA-Z0-9_-]{11})", url)
|
||||
return match.group(1) if match else "unknown"
|
||||
def get_video_id(url: str) -> str:
|
||||
"""Extract unique video ID from YouTube, Twitch, or Kick URL."""
|
||||
# 1. YouTube
|
||||
yt_match = re.search(r"(?:v=|\/shorts\/|\/embed\/|\/v\/|youtu\.be\/)([a-zA-Z0-9_-]{11})", url)
|
||||
if yt_match:
|
||||
return yt_match.group(1)
|
||||
|
||||
# 2. Twitch VODs
|
||||
twitch_vod_match = re.search(r"twitch\.tv\/videos\/(\d+)", url)
|
||||
if twitch_vod_match:
|
||||
return f"twitch_vod_{twitch_vod_match.group(1)}"
|
||||
|
||||
# 3. Twitch Clips
|
||||
twitch_clip_match = re.search(r"(?:clips\.twitch\.tv\/|twitch\.tv\/\w+\/clip\/)([a-zA-Z0-9_-]+)", url)
|
||||
if twitch_clip_match:
|
||||
return f"twitch_clip_{twitch_clip_match.group(1)}"
|
||||
|
||||
# 4. Kick VODs (contains UUID)
|
||||
kick_vod_match = re.search(r"kick\.com\/(?:video\/|(?:\w+\/videos\/))([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})", url)
|
||||
if kick_vod_match:
|
||||
return f"kick_vod_{kick_vod_match.group(1)}"
|
||||
|
||||
# 5. Kick Clips
|
||||
kick_clip_match = re.search(r"kick\.com\/\w+\/clips\/([a-zA-Z0-9_-]+)", url)
|
||||
if kick_clip_match:
|
||||
return f"kick_clip_{kick_clip_match.group(1)}"
|
||||
|
||||
# Fallback to md5 hash of URL to ensure uniqueness
|
||||
import hashlib
|
||||
url_hash = hashlib.md5(url.encode('utf-8')).hexdigest()[:10]
|
||||
return f"video_{url_hash}"
|
||||
|
||||
|
||||
# ─── Main video processor ─────────────────────────────────────────────────────
|
||||
@@ -218,7 +245,7 @@ async def process_video(bot, url: str):
|
||||
log.info(f"[process] URL: {url}")
|
||||
|
||||
# 1. Extract video ID and Get title
|
||||
yt_id = get_yt_id(url)
|
||||
yt_id = get_video_id(url)
|
||||
title = await get_video_title(url)
|
||||
log.info(f"[process] Video ID: {yt_id}, Title: {title!r}")
|
||||
|
||||
@@ -298,7 +325,7 @@ async def process_video(bot, url: str):
|
||||
log.debug(f"[main.py] {line[:200]}")
|
||||
|
||||
# Parse progress markers from main.py output
|
||||
if "Downloading video from YouTube" in line:
|
||||
if "Downloading video" in line:
|
||||
await edit_msg(
|
||||
f"🎬 *{title[:50] or 'Video'}*\n\n"
|
||||
f"📥 Descargando..."
|
||||
|
||||
Reference in New Issue
Block a user