From 5992b328e43b0b4ee60f158fccb78b67399837bb Mon Sep 17 00:00:00 2001 From: Xevion Date: Tue, 24 Dec 2019 00:55:32 -0600 Subject: [PATCH] begin clearing out old sound functions, add downloader function most of these are untested and definitely very buggy, just moving stuff around for now --- app/sound.py | 76 --------------------------------------------- app/sound_models.py | 10 +++++- 2 files changed, 9 insertions(+), 77 deletions(-) diff --git a/app/sound.py b/app/sound.py index 4465ff5..a48e1dd 100644 --- a/app/sound.py +++ b/app/sound.py @@ -6,41 +6,6 @@ import os import re import json import subprocess -import shutil - -# Services => Expected Data -# YouTube => Video ID -# Soundcloud => - -# Filenaming/API Convention Examples -# Original URL/URI => API Path => Connected File -# https://www.youtube.com/watch?v=awtYiVGXiaY => /stream/youtube/awtYiVGXiaY => youtube/awtYiVGXiaY.mp3 -# https://soundcloud.com/yungraredeath/fall-in-line-w-kxng-prod-mars-mission => /stream/soundcloud/fall-in-line-w-kxng-prod-mars-mission---yungraredeath => soundcloud/fall-in-line-w-kxng-prod-mars-mission---yungraredeath.mp3 -# spotify:track:16PmczUxlX7dpr6ror6pXd => /duration/spotify/16PmczUxlX7dpr6ror6pXd => spotify/16PmczUxlX7dpr6ror6pXd.mp3 - -class YouTubeHandler: - @staticmethod - def url(videoid): - return f'https://www.youtube.com/watch?v={videoid}' - - @staticmethod - def getConfig(videoid): - with open(os.path.join('app', 'sounds', 'filenames.json'), 'r') as file: - return json.load(file)['youtube'][videoid] - - @staticmethod - def filename(videoid): - try: - config = YouTubeHandler.getConfig(videoid) - return config['filename'] - except KeyError: - # Use stdout=PIPE, [Python 3.6] production server support instead of 'capture_output=True' => 'process.stdout' - process = subprocess.Popen( - ['youtube-dl', '-x', '--audio-format', 'mp3', '--restrict-filenames', '--get-filename', YouTubeHandler.url(videoid)], - encoding='utf-8', stdout=subprocess.PIPE) - filename = process.communicate()[0].split('.') - filename[-1] = 'mp3' - return '.'.join(filename) @staticmethod def path(videoid): @@ -68,47 +33,6 @@ class YouTubeHandler: subprocess.run(['youtube-dl', '-x', '--restrict-filenames', '--audio-format', 'mp3', YouTubeHandler.url(videoid)]) os.rename(config['filename'], config['path']) -service_functions = { - 'youtube' : YouTubeHandler, - 'spotify' : SpotifyHandler, - 'soundcloud' : SoundcloudHandler -} - -# Default JSON format, will be used in case of corruption -JSONDefault = {'youtube' : {}, 'soundcloud' : {}, 'spotify' : {}} - -if not os.path.exists(os.path.join('app', 'sounds')): - print('Sounds folder not found. Creating.') - os.mkdir(os.path.join('app', 'sounds')) - -# Test JSON file existence -if not os.path.exists(os.path.join('app', 'sounds', 'filenames.json')): - print('JSON database file not found. Creating with default data structure.') - with open(os.path.join('app', 'sounds', 'filenames.json'), 'w+') as file: - json.dump({'youtube' : {} }, file) -else: - # File exists, but is it valid JSON? - try: - print('Testing JSON database file.') - with open(os.path.join('app', 'sounds', 'filenames.json'), 'r') as file: - json.load(file) - except json.JSONDecodeError: - # Corruption or other has occurred. Clearing all service folders. Resetting and clearing all services - print('Corruption/Invalid formatting in JSON file detected, clearing all config/media.') - print('Clearing JSON database file.') - with open(os.path.join('app', 'sounds', 'filenames.json'), 'w+') as file: - json.dump(JSONDefault, file) - - for service in service_functions.keys(): - print(f"Clearing '{service}' folder.") - servicePath = os.path.join('app', 'sounds', service) - if os.path.exists(servicePath): - shutil.rmtree(servicePath) - os.mkdir(servicePath) - else: - os.mkdir(servicePath) - -# Streams a prepared MP3 back to the client @app.route('/stream//') def stream(service, mediaid): prepare(service, mediaid) diff --git a/app/sound_models.py b/app/sound_models.py index 895af34..cda2eda 100644 --- a/app/sound_models.py +++ b/app/sound_models.py @@ -15,10 +15,14 @@ class YouTubeAudio(db.Model): download_timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) last_access_timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) + def getPath(self): + return os.path.join('app', 'sounds', 'youtube', self.filename) + def file_exists(self): - return os.path.exists(os.path.join('app', 'sounds', 'youtube', self.filename)) + return os.path.exists(self.getPath()) def fill_metadata(self): + # Use stdout=PIPE, [Python 3.6] production server support instead of 'capture_output=True' => 'process.stdout' self.url = f'https://www.youtube.com/watch?v={self.id}' processFilename = subprocess.Popen(['youtube-dl', '-x', '--audio-format', 'mp3', '--restrict-filenames', '--get-filename', self.url], encoding='utf-8', stdout=subprocess.PIPE) @@ -31,6 +35,10 @@ class YouTubeAudio(db.Model): self.uploader = data['uploader'] or data['creator'] self.title = data['title'] or data['alt_title'] # Do not trust alt-title ; it is volatile and uploader set, e.x. https://i.imgur.com/Tgff4rI.png + def download(self): + subprocess.run(['youtube-dl', '-x', '--restrict-filenames', '--audio-format', 'mp3', self.id]) + os.rename(self.filename, self.getPath()) + class SoundcloudAudio(db.Model): id = db.Column(db.Integer, primary_key=True) # hidden API-accessible only ID url = db.Column(db.String(256))