my-music-list/addotherproviders.py

145 lines
4.6 KiB
Python

import os
import sqlite3
import tinytag
import yt_dlp
from urllib.parse import urlparse
def initialize_database():
conn = sqlite3.connect('music.db')
c = conn.cursor()
c.execute('''CREATE TABLE IF NOT EXISTS music
(listmusicname TEXT, listvideoid TEXT, listprovider TEXT,
filelocation TEXT, fileartistname TEXT, filealbumname TEXT,
filemusictitle TEXT, fileduration REAL)''')
conn.commit()
conn.close()
def get_download_path():
locations = [
'/mnt/sdcard/Music',
'/storage/emulated/0/Music',
'/sdcard/Music',
os.path.join(os.environ.get('HOME', ''), 'Music'),
os.path.join(os.getcwd(), 'music')
]
for loc in locations:
if os.path.exists(loc):
return loc
default = os.path.join(os.environ['HOME'], 'Music') if 'HOME' in os.environ else os.path.join(os.getcwd(), 'music')
os.makedirs(default, exist_ok=True)
return default
def clean_url(url):
parsed = urlparse(url)
return parsed.netloc + parsed.path
def collect_entries():
entries = []
print("\nAdd new music (enter 'q' to quit)")
while True:
name = input("\nDisplay name: ").strip()
if name.lower() == 'q':
break
url = input("URL: ").strip()
fmt = input("Download format (e.g., bestaudio): ").strip()
if not all([name, url, fmt]):
print("Invalid input! All fields required.")
continue
entries.append(f"{name} --- {url} --- {fmt}")
if entries:
with open('other-providers.txt', 'a') as f:
f.write('\n'.join(entries) + '\n')
print("\nEntries saved to file!")
def process_downloads():
download_path = get_download_path()
conn = sqlite3.connect('music.db')
c = conn.cursor()
if not os.path.exists('other-providers.txt'):
print("No input file found!")
return
with open('other-providers.txt', 'r') as f:
lines = [line.strip() for line in f if line.strip() and not line.startswith('#')]
success_count = 0
errors = []
for idx, line in enumerate(lines, 1):
try:
parts = line.split(' --- ')
if len(parts) != 3:
raise ValueError("Invalid line format")
display_name, url, fmt = parts
print(f"\nProcessing ({idx}/{len(lines)}): {display_name}")
# Configure yt-dlp
ydl_opts = {
'format': fmt,
'outtmpl': '%(title)s.%(ext)s',
'writethumbnail': True,
'postprocessors': [
{'key': 'EmbedThumbnail'},
{'key': 'FFmpegMetadata'}
],
'quiet': True,
'nooverwrites': True,
'restrictfilenames': True
}
# Download and get filename
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url)
filename = ydl.prepare_filename(info)
final_path = os.path.join(download_path, os.path.basename(filename))
if os.path.exists(final_path):
print("File exists, skipping...")
continue
# Download and move file
ydl.download([url])
os.system(f'mv "{filename}" "{final_path}"')
# Extract metadata
tag = tinytag.TinyTag.get(final_path)
metadata = {
'artist': tag.artist or 'Unknown',
'album': tag.album or 'Unknown',
'title': tag.title or display_name,
'duration': tag.duration or 0
}
# Prepare database entry
cleaned_url = clean_url(url)
c.execute('''INSERT INTO music VALUES
(?,?,?,?,?,?,?,?)''',
(display_name, cleaned_url, 'other', final_path,
metadata['artist'], metadata['album'],
metadata['title'], metadata['duration']))
conn.commit()
success_count += 1
except Exception as e:
errors.append((line, str(e)))
print(f"Error: {str(e)}")
continue
conn.close()
# Print summary
print(f"\nProcessing complete!\nSuccess: {success_count}\nErrors: {len(errors)}")
if errors:
print("\nError details:")
for error in errors:
print(f"- {error[0]}: {error[1]}")
if __name__ == "__main__":
initialize_database()
collect_entries()
process_downloads()