many fix
commit
5b9232a937
@ -0,0 +1,5 @@
|
||||
*.tmp
|
||||
*.zip
|
||||
*.tar
|
||||
__pycache__/
|
||||
music/
|
@ -0,0 +1,12 @@
|
||||
Welcome to celaigia
|
||||
|
||||
an app to gently query youtube music, and possibly download only if you don't have already locally
|
||||
|
||||
|
||||
- gitignore music
|
||||
- standardize postprocess
|
||||
- parametrize and make config
|
||||
- fix ui and reduce number of searches
|
||||
- add direct download with url
|
||||
- place query on ui
|
||||
- document
|
@ -0,0 +1,12 @@
|
||||
import importlib
|
||||
import config
|
||||
importlib.reload(config)
|
||||
import utils
|
||||
importlib.reload(utils)
|
||||
import database
|
||||
importlib.reload(database)
|
||||
import ui
|
||||
importlib.reload(ui)
|
||||
import app
|
||||
importlib.reload(app)
|
||||
|
@ -0,0 +1,9 @@
|
||||
from config import music_path
|
||||
from ui import UIEngine
|
||||
from database import Database
|
||||
|
||||
if __name__ == "__main__":
|
||||
# Add your main code here
|
||||
db = Database(base_path=music_path)
|
||||
ui = UIEngine(db)
|
||||
ui.run()
|
@ -0,0 +1,11 @@
|
||||
music_path = "./music"
|
||||
|
||||
yt_dlp_opts = {
|
||||
'format': 'bestaudio/best',
|
||||
'default_search': 'ytsearch5',
|
||||
'postprocessors': [{
|
||||
'key': 'FFmpegExtractAudio',
|
||||
'preferredcodec': 'mp3',
|
||||
'preferredquality': '192',
|
||||
}],
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
# Updated database.py
|
||||
import json
|
||||
import datetime
|
||||
|
||||
class Database:
|
||||
def __init__(self, base_path):
|
||||
self.base_path = base_path
|
||||
self.file_path = f'{base_path}/index.json'
|
||||
try:
|
||||
with open(self.file_path, 'r') as file:
|
||||
self.data = json.load(file)
|
||||
except FileNotFoundError:
|
||||
self.data = []
|
||||
|
||||
def add_entry(self, entry):
|
||||
entry['timestamp'] = datetime.datetime.now().strftime('%d/%m/%Y')
|
||||
self.data.append(entry)
|
||||
with open(self.file_path, 'w') as file:
|
||||
json.dump(self.data, file, indent=4)
|
||||
|
||||
def downloadable(self, url, title):
|
||||
idx = url.split('https://www.youtube.com/watch?v=')[-1]
|
||||
for entry in self.data:
|
||||
if entry['id'] == idx or entry['title'] == title:
|
||||
return False
|
||||
return True
|
@ -0,0 +1,86 @@
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
import tkinter.simpledialog as sd
|
||||
import time
|
||||
import os
|
||||
from utils import search_youtube, download_audio
|
||||
|
||||
class UIEngine:
|
||||
def __init__(self, db):
|
||||
self.db = db
|
||||
self.root = tk.Tk()
|
||||
self.root.title("celaigia")
|
||||
self.root.geometry("400x300") # Set a fixed size
|
||||
|
||||
self.status_label = tk.Label(self.root, text="Ready")
|
||||
self.status_label.pack()
|
||||
|
||||
self.search_frame = ttk.Frame(self.root)
|
||||
self.search_frame.pack()
|
||||
|
||||
self.search_status_label = tk.Label(self.search_frame, text="Enter search query:")
|
||||
self.search_status_label.grid(row=0, column=0)
|
||||
self.search_entry = tk.Entry(self.search_frame)
|
||||
self.search_entry.grid(row=0, column=1)
|
||||
self.search_button = tk.Button(self.search_frame, text="Search", command=lambda: self.search_and_display())
|
||||
self.search_button.grid(row=0, column=2)
|
||||
|
||||
self.results_frame = ttk.Frame(self.root)
|
||||
self.results_frame.pack()
|
||||
|
||||
self.download_status_label = tk.Label(self.root, text="Enter URL to download:")
|
||||
self.download_status_label.pack()
|
||||
self.download_entry = tk.Entry(self.root)
|
||||
self.download_entry.pack()
|
||||
self.download_button = tk.Button(self.root, text="Download", command=lambda: self.handle_download(self.download_entry.get()))
|
||||
self.download_button.pack()
|
||||
|
||||
def search_and_display(self):
|
||||
self.set_status("searching")
|
||||
query = self.search_entry.get()
|
||||
# Clear the existing results
|
||||
for widget in self.results_frame.winfo_children():
|
||||
widget.destroy()
|
||||
results = search_youtube(query)
|
||||
self.display_results(results)
|
||||
self.set_status("Enter search query or select item to download")
|
||||
|
||||
def set_status(self, status):
|
||||
self.status_label.config(text=status)
|
||||
self.root.update() # Force GUI update
|
||||
|
||||
def display_results(self, results):
|
||||
for i, result in enumerate(results):
|
||||
result_button = ttk.Button(self.results_frame, text=result['title'], command=lambda url=result['webpage_url'], filename=result['title']: self.handle_download(url, filename))
|
||||
result_button.pack()
|
||||
|
||||
def handle_download(self, url, filename):
|
||||
|
||||
if self.db.downloadable(url, filename):
|
||||
self.set_status("Downloading...")
|
||||
success = download_audio(url, self.db.base_path)
|
||||
if success:
|
||||
self.set_status("Download completed, adding to db")
|
||||
self.prompt_user_for_details(url, filename)
|
||||
self.set_status("Enter search query or select item to download")
|
||||
|
||||
# Modify the prompt_user_for_details method
|
||||
def prompt_user_for_details(self,url, filename):
|
||||
title = sd.askstring("Enter Title", "Enter Title:", initialvalue=filename)
|
||||
artist = sd.askstring("Enter Artist", "Enter Artist:")
|
||||
tags = sd.askstring("Enter Tags", "Enter Tags (comma separated):")
|
||||
entry = {
|
||||
"id": url.split('https://www.youtube.com/watch?v=')[-1].strip(),
|
||||
"title": title.strip(),
|
||||
"artist": artist.strip(),
|
||||
"filename": filename.strip(),
|
||||
"tags": [tag.strip() for tag in tags.split(",")] if tags else [],
|
||||
"timestamp": time.time()
|
||||
}
|
||||
self.add_to_db(entry)
|
||||
|
||||
def add_to_db(self, entry):
|
||||
self.db.add_entry(entry)
|
||||
|
||||
def run(self):
|
||||
self.root.mainloop()
|
@ -0,0 +1,28 @@
|
||||
import yt_dlp
|
||||
from config import yt_dlp_opts
|
||||
|
||||
|
||||
# Function to search YouTube
|
||||
def search_youtube(query, opts = yt_dlp_opts):
|
||||
with yt_dlp.YoutubeDL(opts) as ydl:
|
||||
info = ydl.extract_info(query, download=False)
|
||||
return info['entries']
|
||||
|
||||
|
||||
def download_audio(url, base_path, opts = yt_dlp_opts):
|
||||
|
||||
opts['outtmpl'] = f'{base_path}/audios/%(title)s.%(ext)s'
|
||||
if not isinstance(url, list):
|
||||
url = [url]
|
||||
|
||||
success = False
|
||||
|
||||
try:
|
||||
with yt_dlp.YoutubeDL(opts) as ydl:
|
||||
ydl.download(url)
|
||||
success = True
|
||||
except:
|
||||
success = False
|
||||
return success
|
||||
|
||||
|
Loading…
Reference in New Issue