KaraokeVideoDownloader/utilities/add_manual_video.py

198 lines
6.1 KiB
Python

#!/usr/bin/env python3
"""
Helper script to add manual videos to the manual videos collection.
"""
import json
import re
from pathlib import Path
from typing import Dict, List, Optional
from karaoke_downloader.data_path_manager import get_data_path_manager
def extract_video_id(url: str) -> Optional[str]:
"""Extract video ID from YouTube URL."""
patterns = [
r'(?:youtube\.com/watch\?v=|youtu\.be/|youtube\.com/embed/)([a-zA-Z0-9_-]{11})',
r'youtube\.com/watch\?.*v=([a-zA-Z0-9_-]{11})'
]
for pattern in patterns:
match = re.search(pattern, url)
if match:
return match.group(1)
return None
def add_manual_video(title: str, url: str, manual_file: str = None):
if manual_file is None:
manual_file = str(get_data_path_manager().get_manual_videos_path())
"""
Add a manual video to the collection.
Args:
title: Video title (e.g., "Artist - Song (Karaoke Version)")
url: YouTube URL
manual_file: Path to manual videos JSON file
"""
manual_path = Path(manual_file)
# Load existing data or create new
if manual_path.exists():
with open(manual_path, 'r', encoding='utf-8') as f:
data = json.load(f)
else:
data = {
"channel_name": "@ManualVideos",
"channel_url": "manual://static",
"description": "Manual collection of individual karaoke videos",
"videos": [],
"parsing_rules": {
"format": "artist_title_separator",
"separator": " - ",
"artist_first": true,
"title_cleanup": {
"remove_suffix": {
"suffixes": ["(Karaoke)", "(Karaoke Version)", "(Karaoke Version) Lyrics"]
}
}
}
}
# Extract video ID
video_id = extract_video_id(url)
if not video_id:
print(f"❌ Could not extract video ID from URL: {url}")
return False
# Check if video already exists
existing_ids = [video.get("id") for video in data["videos"]]
if video_id in existing_ids:
print(f"⚠️ Video already exists: {title}")
return False
# Add new video
new_video = {
"title": title,
"url": url,
"id": video_id,
"upload_date": "2024-01-01", # Default date
"duration": 180, # Default duration
"view_count": 1000 # Default view count
}
data["videos"].append(new_video)
# Save updated data
manual_path.parent.mkdir(parents=True, exist_ok=True)
with open(manual_path, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
print(f"✅ Added video: {title}")
print(f" URL: {url}")
print(f" ID: {video_id}")
return True
def list_manual_videos(manual_file: str = None):
if manual_file is None:
manual_file = str(get_data_path_manager().get_manual_videos_path())
"""List all manual videos."""
manual_path = Path(manual_file)
if not manual_path.exists():
print("❌ No manual videos file found")
return
with open(manual_path, 'r', encoding='utf-8') as f:
data = json.load(f)
print(f"📋 Manual Videos ({len(data['videos'])} videos):")
print("=" * 60)
for i, video in enumerate(data['videos'], 1):
print(f"{i:2d}. {video['title']}")
print(f" URL: {video['url']}")
print(f" ID: {video['id']}")
print()
def remove_manual_video(video_id: str, manual_file: str = None):
if manual_file is None:
manual_file = str(get_data_path_manager().get_manual_videos_path())
"""Remove a manual video by ID."""
manual_path = Path(manual_file)
if not manual_path.exists():
print("❌ No manual videos file found")
return False
with open(manual_path, 'r', encoding='utf-8') as f:
data = json.load(f)
# Find and remove video
for i, video in enumerate(data['videos']):
if video['id'] == video_id:
removed_video = data['videos'].pop(i)
with open(manual_path, 'w', encoding='utf-8') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
print(f"✅ Removed video: {removed_video['title']}")
return True
print(f"❌ Video with ID '{video_id}' not found")
return False
def main():
"""Interactive mode for adding manual videos."""
print("🎤 Manual Video Manager")
print("=" * 30)
print("1. Add video")
print("2. List videos")
print("3. Remove video")
print("4. Exit")
while True:
choice = input("\nSelect option (1-4): ").strip()
if choice == "1":
title = input("Enter video title (e.g., 'Artist - Song (Karaoke Version)'): ").strip()
url = input("Enter YouTube URL: ").strip()
if title and url:
add_manual_video(title, url)
else:
print("❌ Title and URL are required")
elif choice == "2":
list_manual_videos()
elif choice == "3":
video_id = input("Enter video ID to remove: ").strip()
if video_id:
remove_manual_video(video_id)
else:
print("❌ Video ID is required")
elif choice == "4":
print("👋 Goodbye!")
break
else:
print("❌ Invalid option")
if __name__ == "__main__":
import sys
if len(sys.argv) > 1:
# Command line mode
if sys.argv[1] == "add" and len(sys.argv) >= 4:
add_manual_video(sys.argv[2], sys.argv[3])
elif sys.argv[1] == "list":
list_manual_videos()
elif sys.argv[1] == "remove" and len(sys.argv) >= 3:
remove_manual_video(sys.argv[2])
else:
print("Usage:")
print(" python add_manual_video.py add 'Title' 'URL'")
print(" python add_manual_video.py list")
print(" python add_manual_video.py remove VIDEO_ID")
else:
# Interactive mode
main()