diff --git a/addotherproviders.py b/addotherproviders.py new file mode 100644 index 0000000..3efbd3c --- /dev/null +++ b/addotherproviders.py @@ -0,0 +1,145 @@ +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() diff --git a/old-music.db b/old-music.db index 9191472..d336a7f 100644 Binary files a/old-music.db and b/old-music.db differ diff --git a/other-providers.txt b/other-providers.txt new file mode 100644 index 0000000..c1d3a74 --- /dev/null +++ b/other-providers.txt @@ -0,0 +1 @@ +C418 - stranger_think --- https://c418.bandcamp.com/track/stranger-think --- flac diff --git a/websitemodule.py b/websitemodule.py index fddcc9a..f27bab1 100644 --- a/websitemodule.py +++ b/websitemodule.py @@ -2,13 +2,12 @@ import os import random import requests -# Main code written by Halhadus, optimized and stylized by DeepSeek-R1 - -def randomize(listurl): # Data fetching and cleaning - musiclist = requests.get(listurl).text.split("\n") - musiclist = [m.strip() for m in musiclist if m.strip() != ""] - - # HTML base template +def randomize(base_url): + # Fetch both lists + yt_list = requests.get(f"{base_url}musiclist.txt").text.split("\n") + other_list = requests.get(f"{base_url}other-providers.txt").text.split("\n") + + # HTML template html = """<!DOCTYPE html> <html lang="en"> <head> @@ -16,12 +15,7 @@ def randomize(listurl): # Data fetching and <link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&display=swap" rel="stylesheet"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Halhadus' Music List</title> - <link rel="icon" type="image/png" href="assets/favicon.png"> - <meta name="description" content="Halhadus' Music List"> - <meta property="og:title" content="Halhadus' Music List"> - <meta property="og:description" content="Halhadus' Music List"> - <meta property="og:image" content="assets/favicon.png"> - <meta property="og:url" content="https://halhadus.rocks/musiclist.html"> + <link rel="icon" type="image/png" href="assets/favicon.png"> <meta name="description" content="Halhadus' Music List"> <meta property="og:title" content="Halhadus' Music List"> <meta property="og:description" content="Halhadus' Music List"> <meta property="og:image" content="assets/favicon.png"> <meta property="og:url" content="https://halhadus.rocks/musiclist.html"> <style> .music-card { background: #2a2a2a; @@ -31,9 +25,6 @@ def randomize(listurl): # Data fetching and transition: transform 0.2s; border: 1px solid #333333; } - .music-card:hover { - transform: translateY(-2px); - } .play-button { background: #333333; border: 1px solid #444444; @@ -45,15 +36,6 @@ def randomize(listurl): # Data fetching and font-family: 'JetBrains Mono', monospace; font-size: 0.9em; } - .play-button:hover { - background: #3a3a3a; - } - .thumbnail { - border-radius: 5px; - margin-top: 12px; - max-width: 280px; - border: 1px solid #333333; - } .source-banner { background: #2a2a2a; padding: 12px; @@ -68,8 +50,13 @@ def randomize(listurl): # Data fetching and <div style="max-width: 800px; margin: 0 auto; padding: 20px;"> <h1>Music List</h1> - <!-- Source Banner --> <div class="source-banner"> <a href="https://git.halhadus.rocks/Halhadus/my-music-list" style="color: #ffffff; text-decoration: none;"> [ 📜 Source Code & History ] - </a> </div> + <!-- Source Banner --> + <div class="source-banner"> + <a href="https://git.halhadus.rocks/Halhadus/my-music-list" + style="color: #ffffff; text-decoration: none;"> + [ 📜 Source Code & History ] + </a> + </div> <!-- Control Buttons --> <div style="margin-bottom: 30px; display: flex; gap: 10px;"> @@ -82,63 +69,75 @@ def randomize(listurl): # Data fetching and </button> </div>""" - random.shuffle(musiclist) - musiccount = 0 + total_count = 0 + sections = [ + ("YouTube Music", yt_list, True), + ("Other Providers", other_list, False) + ] - # Music cards creation - for music in musiclist: - try: - parts = music.split(" --- ") - if len(parts) != 3: - continue + # Process both sections + for section_name, musiclist, show_thumb in sections: + html += f"\n<h2 style='margin-top: 40px;'>{section_name}</h2>" + section_count = 0 + random.shuffle(musiclist) - title, vid, platform = parts - musiccount += 1 + for music in musiclist: + try: + music = music.strip() + if not music: + continue - # Thumbnail URL - thumbnail_url = f"https://img.youtube.com/vi/{vid}/hqdefault.jpg" - - # Determine URL based on platform - base_url = "music.youtube.com" if platform == "YTM" else "www.youtube.com" - yt_url = f"https://{base_url}/watch?v={vid}" + # Parse entry + if section_name == "YouTube Music": + title, vid, platform = music.split(" --- ") + yt_url = f"https://{'music.youtube.com' if platform == 'YTM' else 'www.youtube.com'}/watch?v={vid}" + btn_text = platform + else: + display_name, url, _ = music.split(" --- ") + yt_url = url + btn_text = "Other" - # HTML block - html += f""" - <div class="music-card" data-url="{yt_url}"> - <div style="margin-bottom: 10px; display: flex; align-items: center;"> - <span style="color: #888; margin-right: 10px;">#{musiccount}</span> - <span style="flex-grow: 1;">{title}</span> - <button onclick="window.open('{yt_url}')" class="play-button"> - {platform} → - </button> - </div> - <img src="{thumbnail_url}" - class="thumbnail" - alt="{title} Cover Art" - onerror="this.style.display='none'"> - </div> + # Generate HTML + html += f""" + <div class="music-card" data-url="{yt_url}"> + <div style="margin-bottom: 10px; display: flex; align-items: center;"> + <span style="color: #888; margin-right: 10px;">#{total_count+1}</span> + <span style="flex-grow: 1;">{display_name if section_name == "Other Providers" else title}</span> + <button onclick="window.open('{yt_url}')" class="play-button"> + {btn_text} → + </button> + </div>""" - <script> - function openRandomMusicCard() {{ - const cards = document.querySelectorAll('.music-card[data-url]'); - if (!cards.length) return alert('No music found!'); - const randomCard = cards[Math.floor(Math.random() * cards.length)]; - window.open(randomCard.dataset.url); - }} - </script> - """ + if show_thumb and section_name == "YouTube Music": + html += f""" + <img src="https://img.youtube.com/vi/{vid}/hqdefault.jpg" + style="border-radius: 5px; margin-top: 12px; max-width: 280px; border: 1px solid #333333;" + alt="Cover Art" + onerror="this.style.display='none'">""" - except Exception as e: - print(f"Error processing: {music} - {str(e)}") - - # Footer section + html += "\n</div>" + total_count += 1 + section_count += 1 + + except Exception as e: + print(f"Error processing: {music} - {str(e)}") + + # Footer html += f""" <div style="margin-top: 40px; text-align: center; color: #666;"> <div style="margin-bottom: 15px;"> - Total Tracks: {musiccount} + Total Tracks: {total_count} </div> </div> </div> + <script> + function openRandomMusicCard() {{ + const cards = document.querySelectorAll('.music-card[data-url]'); + if (!cards.length) return alert('No music found!'); + const randomCard = cards[Math.floor(Math.random() * cards.length)]; + window.open(randomCard.dataset.url); + }} + </script> </body> </html>"""