checkpoint
This commit is contained in:
		
							parent
							
								
									bd263b2ed7
								
							
						
					
					
						commit
						90eedca0d7
					
				
					 9 changed files with 138 additions and 55 deletions
				
			
		
							
								
								
									
										13
									
								
								download_thumbnails.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								download_thumbnails.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,13 @@ | ||||||
|  | import os | ||||||
|  | import ycdl_easy | ||||||
|  | from voussoirkit import downloady | ||||||
|  | 
 | ||||||
|  | DIRECTORY = 'C:\\users\\owner\\youtube thumbnails' | ||||||
|  | 
 | ||||||
|  | videos = ycdl_easy.youtube.get_videos() | ||||||
|  | for video in videos: | ||||||
|  |     thumbnail_path = os.path.join(DIRECTORY, video['id']) + '.jpg' | ||||||
|  |     if os.path.exists(thumbnail_path): | ||||||
|  |         continue | ||||||
|  |     result = downloady.download_file(video['thumbnail'], thumbnail_path) | ||||||
|  |     print(result) | ||||||
|  | @ -11,9 +11,14 @@ | ||||||
| #content_body | #content_body | ||||||
| { | { | ||||||
|     display: flex; |     display: flex; | ||||||
|  |     flex-grow: 1; | ||||||
|  |     flex-shrink: 0; | ||||||
|  |     flex-basis: auto; | ||||||
|     flex-direction: column; |     flex-direction: column; | ||||||
|  |     width: 1440px; | ||||||
|  |     margin: auto; | ||||||
|  |     max-width: 100%; | ||||||
| } | } | ||||||
| 
 |  | ||||||
| .video_card_downloaded, | .video_card_downloaded, | ||||||
| .video_card_ignored, | .video_card_ignored, | ||||||
| .video_card_pending | .video_card_pending | ||||||
|  | @ -67,8 +72,10 @@ | ||||||
| <body> | <body> | ||||||
| {{header.make_header()}} | {{header.make_header()}} | ||||||
| <div id="content_body"> | <div id="content_body"> | ||||||
|     <button class="refresh_button" onclick="refresh_channel('{{channel['id']}}', false, function(){location.reload()})">Refresh new videos</button> |     <button class="refresh_button" | ||||||
|     <button class="refresh_button" onclick="refresh_channel('{{channel['id']}}', true, function(){location.reload()})">Refresh everything</button> |     onclick="refresh_channel('{{channel['id']}}', false, function(){location.reload()})">Refresh new videos</button> | ||||||
|  |     <button class="refresh_button" | ||||||
|  |     onclick="refresh_channel('{{channel['id']}}', true, function(){location.reload()})">Refresh everything</button> | ||||||
|     <span><a href="/channel/{{channel['id']}}">All</a></span> |     <span><a href="/channel/{{channel['id']}}">All</a></span> | ||||||
|     <span><a href="/channel/{{channel['id']}}/pending">Pending</a></span> |     <span><a href="/channel/{{channel['id']}}/pending">Pending</a></span> | ||||||
|     <span><a href="/channel/{{channel['id']}}/ignored">Ignored</a></span> |     <span><a href="/channel/{{channel['id']}}/ignored">Ignored</a></span> | ||||||
|  | @ -107,7 +114,6 @@ | ||||||
|             class="video_action_ignore" |             class="video_action_ignore" | ||||||
|             onclick="mark_video_state('{{video['id']}}', 'ignored', receive_action_response);" |             onclick="mark_video_state('{{video['id']}}', 'ignored', receive_action_response);" | ||||||
|             >Ignore</button> |             >Ignore</button> | ||||||
| 
 |  | ||||||
|             {% endif %} |             {% endif %} | ||||||
|         </div> |         </div> | ||||||
|     </div> |     </div> | ||||||
|  | @ -208,17 +214,5 @@ function start_download(video_id, callback) | ||||||
|     data.append("video_id", video_id); |     data.append("video_id", video_id); | ||||||
|     return post(url, data, callback);     |     return post(url, data, callback);     | ||||||
| } | } | ||||||
| 
 |  | ||||||
| function toggle_dropdown(dropdown) |  | ||||||
| { |  | ||||||
|     if (dropdown.style.display != "inline-flex") |  | ||||||
|     { |  | ||||||
|         dropdown.style.display = "inline-flex"; |  | ||||||
|     } |  | ||||||
|     else |  | ||||||
|     { |  | ||||||
|         dropdown.style.display = "none"; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| </script> | </script> | ||||||
| </html> | </html> | ||||||
|  |  | ||||||
|  | @ -11,7 +11,13 @@ | ||||||
| #content_body | #content_body | ||||||
| { | { | ||||||
|     display: flex; |     display: flex; | ||||||
|  |     flex-grow: 1; | ||||||
|  |     flex-shrink: 0; | ||||||
|  |     flex-basis: auto; | ||||||
|     flex-direction: column; |     flex-direction: column; | ||||||
|  |     width: 1440px; | ||||||
|  |     margin: auto; | ||||||
|  |     max-width: 100%; | ||||||
| } | } | ||||||
| #new_channel_textbox, | #new_channel_textbox, | ||||||
| #new_channel_button | #new_channel_button | ||||||
|  | @ -85,6 +91,7 @@ function refresh_channel(channel_id, force, callback) | ||||||
|     data.append("force", force) |     data.append("force", force) | ||||||
|     return post(url, data, callback);     |     return post(url, data, callback);     | ||||||
| } | } | ||||||
|  | 
 | ||||||
| function refresh_all_channels(force, callback) | function refresh_all_channels(force, callback) | ||||||
| { | { | ||||||
|     var url = "/refresh_all_channels"; |     var url = "/refresh_all_channels"; | ||||||
|  |  | ||||||
							
								
								
									
										90
									
								
								ycdl.py
									
									
									
									
									
								
							
							
						
						
									
										90
									
								
								ycdl.py
									
									
									
									
									
								
							|  | @ -4,16 +4,15 @@ import sqlite3 | ||||||
| 
 | 
 | ||||||
| import ytapi | import ytapi | ||||||
| 
 | 
 | ||||||
| # AVAILABLE FORMATTERS: | def YOUTUBE_DL_COMMAND(video_id): | ||||||
| # url, id |     path = 'C:\\Incoming\\ytqueue\\{id}.ytqueue'.format(id=video_id) | ||||||
| # Note that if the channel has a value in the `directory` column, the bot will |     open(path, 'w') | ||||||
| # chdir there before executing. |  | ||||||
| YOUTUBE_DL_COMMAND = 'touch C:\\Incoming\\ytqueue\\{id}.ytqueue' |  | ||||||
| 
 | 
 | ||||||
| logging.basicConfig(level=logging.DEBUG) | logging.basicConfig(level=logging.DEBUG) | ||||||
| log = logging.getLogger(__name__) | log = logging.getLogger(__name__) | ||||||
| logging.getLogger('googleapiclient.discovery').setLevel(logging.WARNING) | logging.getLogger('googleapiclient.discovery').setLevel(logging.WARNING) | ||||||
| logging.getLogger('requests.packages.urllib3.connectionpool').setLevel(logging.WARNING) | logging.getLogger('requests.packages.urllib3.connectionpool').setLevel(logging.WARNING) | ||||||
|  | logging.getLogger('requests.packages.urllib3.util.retry').setLevel(logging.WARNING) | ||||||
| 
 | 
 | ||||||
| SQL_CHANNEL_COLUMNS = [ | SQL_CHANNEL_COLUMNS = [ | ||||||
|     'id', |     'id', | ||||||
|  | @ -64,6 +63,7 @@ DEFAULT_DBNAME = 'ycdl.db' | ||||||
| 
 | 
 | ||||||
| ERROR_DATABASE_OUTOFDATE = 'Database is out-of-date. {current} should be {new}' | ERROR_DATABASE_OUTOFDATE = 'Database is out-of-date. {current} should be {new}' | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| def verify_is_abspath(path): | def verify_is_abspath(path): | ||||||
|     ''' |     ''' | ||||||
|     TO DO: Determine whether this is actually correct. |     TO DO: Determine whether this is actually correct. | ||||||
|  | @ -71,8 +71,16 @@ def verify_is_abspath(path): | ||||||
|     if os.path.abspath(path) != path: |     if os.path.abspath(path) != path: | ||||||
|         raise ValueError('Not an abspath') |         raise ValueError('Not an abspath') | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|  | class InvalidVideoState(Exception): | ||||||
|  |     pass | ||||||
|  | 
 | ||||||
|  | class NoSuchVideo(Exception): | ||||||
|  |     pass | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| class YCDL: | class YCDL: | ||||||
|     def __init__(self, youtube, database_filename=None): |     def __init__(self, youtube, database_filename=None, youtube_dl_function=None): | ||||||
|         self.youtube = youtube |         self.youtube = youtube | ||||||
|         if database_filename is None: |         if database_filename is None: | ||||||
|             database_filename = DEFAULT_DBNAME |             database_filename = DEFAULT_DBNAME | ||||||
|  | @ -90,6 +98,11 @@ class YCDL: | ||||||
|                 print(message) |                 print(message) | ||||||
|                 raise SystemExit |                 raise SystemExit | ||||||
| 
 | 
 | ||||||
|  |         if youtube_dl_function: | ||||||
|  |             self.youtube_dl_function = youtube_dl_function | ||||||
|  |         else: | ||||||
|  |             self.youtube_dl_function = YOUTUBE_DL_COMMAND | ||||||
|  | 
 | ||||||
|         statements = DB_INIT.split(';') |         statements = DB_INIT.split(';') | ||||||
|         for statement in statements: |         for statement in statements: | ||||||
|             self.cur.execute(statement) |             self.cur.execute(statement) | ||||||
|  | @ -134,28 +147,46 @@ class YCDL: | ||||||
|         return fetch[SQL_CHANNEL['directory']] |         return fetch[SQL_CHANNEL['directory']] | ||||||
| 
 | 
 | ||||||
|     def download_video(self, video, force=False): |     def download_video(self, video, force=False): | ||||||
|         if not isinstance(video, ytapi.Video): |         ''' | ||||||
|             video = self.youtube.get_video(video) |         Execute the `YOUTUBE_DL_COMMAND`, within the channel's associated | ||||||
|  |         directory if applicable. | ||||||
|  |         ''' | ||||||
|  |         # This logic is a little hazier than I would like, but it's all in the | ||||||
|  |         # interest of minimizing unnecessary API calls. | ||||||
|  |         if isinstance(video, ytapi.Video): | ||||||
|  |             video_id = video.id | ||||||
|  |         else: | ||||||
|  |             video_id = video | ||||||
|  |         self.cur.execute('SELECT * FROM videos WHERE id == ?', [video_id]) | ||||||
|  |         video_row = self.cur.fetchone() | ||||||
|  |         if video_row is None: | ||||||
|  |             # Since the video was not in the db, we may not know about the channel either. | ||||||
|  |             if not isinstance(video, ytapi.Video): | ||||||
|  |                 print('get video') | ||||||
|  |                 video = self.youtube.get_video(video) | ||||||
|  |             channel_id = video.author_id | ||||||
|  |             self.cur.execute('SELECT * FROM channels WHERE id == ?', [channel_id]) | ||||||
|  |             if self.cur.fetchone() is None: | ||||||
|  |                 print('add channel') | ||||||
|  |                 self.add_channel(channel_id, get_videos=False, commit=False) | ||||||
|  |             video_row = self.insert_video(video, commit=False)['row'] | ||||||
|  |         else: | ||||||
|  |             channel_id = video_row[SQL_VIDEO['author_id']] | ||||||
| 
 | 
 | ||||||
|         self.add_channel(video.author_id, get_videos=False, commit=False) |         if video_row[SQL_VIDEO['download']] != 'pending' and not force: | ||||||
|         status = self.insert_video(video, commit=True) |  | ||||||
| 
 |  | ||||||
|         if status['row'][SQL_VIDEO['download']] != 'pending' and not force: |  | ||||||
|             print('That video does not need to be downloaded.') |             print('That video does not need to be downloaded.') | ||||||
|             return |             return | ||||||
| 
 | 
 | ||||||
|         download_directory = self.channel_directory(video.author_id) |         download_directory = self.channel_directory(channel_id) | ||||||
|         download_directory = download_directory or os.getcwd() |         download_directory = download_directory or os.getcwd() | ||||||
| 
 | 
 | ||||||
|         current_directory = os.getcwd() |         current_directory = os.getcwd() | ||||||
|         os.makedirs(download_directory, exist_ok=True) |         os.makedirs(download_directory, exist_ok=True) | ||||||
|         os.chdir(download_directory) |         os.chdir(download_directory) | ||||||
|         url = 'https://www.youtube.com/watch?v={id}'.format(id=video.id) |         self.youtube_dl_function(video_id) | ||||||
|         command = YOUTUBE_DL_COMMAND.format(url=url, id=video.id) |  | ||||||
|         os.system(command) |  | ||||||
|         os.chdir(current_directory) |         os.chdir(current_directory) | ||||||
| 
 | 
 | ||||||
|         self.cur.execute('UPDATE videos SET download = "downloaded" WHERE id == ?', [video.id]) |         self.cur.execute('UPDATE videos SET download = "downloaded" WHERE id == ?', [video_id]) | ||||||
|         self.sql.commit() |         self.sql.commit() | ||||||
| 
 | 
 | ||||||
|     def get_channel(self, channel_id): |     def get_channel(self, channel_id): | ||||||
|  | @ -173,14 +204,29 @@ class YCDL: | ||||||
|         channels.sort(key=lambda x: x['name'].lower()) |         channels.sort(key=lambda x: x['name'].lower()) | ||||||
|         return channels |         return channels | ||||||
| 
 | 
 | ||||||
|     def get_videos(self, channel_id=None): |     def get_videos(self, channel_id=None, download_filter=None): | ||||||
|  |         wheres = [] | ||||||
|  |         bindings = [] | ||||||
|         if channel_id is not None: |         if channel_id is not None: | ||||||
|             self.cur.execute('SELECT * FROM videos WHERE author_id == ?', [channel_id]) |             wheres.append('author_id') | ||||||
|  |             bindings.append(channel_id) | ||||||
|  | 
 | ||||||
|  |         if download_filter is not None: | ||||||
|  |             wheres.append('download') | ||||||
|  |             bindings.append(download_filter) | ||||||
|  | 
 | ||||||
|  |         if wheres: | ||||||
|  |             wheres = [x + ' == ?' for x in wheres] | ||||||
|  |             wheres = ' WHERE ' + ' AND '.join(wheres) | ||||||
|         else: |         else: | ||||||
|             self.cur.execute('SELECT * FROM videos ') |             wheres = '' | ||||||
|  | 
 | ||||||
|  |         query = 'SELECT * FROM videos' + wheres | ||||||
|  |         self.cur.execute(query, bindings) | ||||||
|         videos = self.cur.fetchall() |         videos = self.cur.fetchall() | ||||||
|         if not videos: |         if not videos: | ||||||
|             return [] |             return [] | ||||||
|  | 
 | ||||||
|         videos = [{key: video[SQL_VIDEO[key]] for key in SQL_VIDEO} for video in videos] |         videos = [{key: video[SQL_VIDEO[key]] for key in SQL_VIDEO} for video in videos] | ||||||
|         videos.sort(key=lambda x: x['published'], reverse=True) |         videos.sort(key=lambda x: x['published'], reverse=True) | ||||||
|         return videos |         return videos | ||||||
|  | @ -214,10 +260,10 @@ class YCDL: | ||||||
|         Mark the video as ignored, pending, or downloaded. |         Mark the video as ignored, pending, or downloaded. | ||||||
|         ''' |         ''' | ||||||
|         if state not in ['ignored', 'pending', 'downloaded']: |         if state not in ['ignored', 'pending', 'downloaded']: | ||||||
|             raise ValueError(state) |             raise InvalidVideoState(state) | ||||||
|         self.cur.execute('SELECT * FROM videos WHERE id == ?', [video_id]) |         self.cur.execute('SELECT * FROM videos WHERE id == ?', [video_id]) | ||||||
|         if self.cur.fetchone() is None: |         if self.cur.fetchone() is None: | ||||||
|             raise KeyError(video_id) |             raise NoSuchVideo(video_id) | ||||||
|         self.cur.execute('UPDATE videos SET download = ? WHERE id == ?', [state, video_id]) |         self.cur.execute('UPDATE videos SET download = ? WHERE id == ?', [state, video_id]) | ||||||
|         if commit: |         if commit: | ||||||
|             self.sql.commit() |             self.sql.commit() | ||||||
|  |  | ||||||
|  | @ -4,6 +4,7 @@ gevent.monkey.patch_all() | ||||||
| import gevent.pywsgi | import gevent.pywsgi | ||||||
| import gevent.wsgi | import gevent.wsgi | ||||||
| import sys | import sys | ||||||
|  | 
 | ||||||
| import ycdl_site | import ycdl_site | ||||||
| 
 | 
 | ||||||
| if len(sys.argv) == 2: | if len(sys.argv) == 2: | ||||||
|  | @ -25,5 +26,5 @@ else: | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| print('Starting server') | print('Starting server on port %d' % port) | ||||||
| http.serve_forever() | http.serve_forever() | ||||||
|  |  | ||||||
							
								
								
									
										2
									
								
								ycdl_refresh.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								ycdl_refresh.py
									
									
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,2 @@ | ||||||
|  | import ycdl_easy | ||||||
|  | ycdl_easy.youtube.refresh_all_channels() | ||||||
							
								
								
									
										27
									
								
								ycdl_site.py
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								ycdl_site.py
									
									
									
									
									
								
							|  | @ -128,9 +128,8 @@ def get_channel(channel_id, download_filter=None): | ||||||
|     channel = youtube.get_channel(channel_id) |     channel = youtube.get_channel(channel_id) | ||||||
|     if channel is None: |     if channel is None: | ||||||
|         flask.abort(404) |         flask.abort(404) | ||||||
|     videos = youtube.get_videos(channel_id=channel_id) |     videos = youtube.get_videos(channel_id=channel_id, download_filter=download_filter) | ||||||
|     if download_filter is not None: | 
 | ||||||
|         videos = [video for video in videos if video['download'] == download_filter] |  | ||||||
|     for video in videos: |     for video in videos: | ||||||
|         published = video['published'] |         published = video['published'] | ||||||
|         published = datetime.datetime.utcfromtimestamp(published) |         published = datetime.datetime.utcfromtimestamp(published) | ||||||
|  | @ -153,10 +152,13 @@ def post_mark_video_state(): | ||||||
|     state = request.form['state'] |     state = request.form['state'] | ||||||
|     try: |     try: | ||||||
|         youtube.mark_video_state(video_id, state) |         youtube.mark_video_state(video_id, state) | ||||||
|     except KeyError: | 
 | ||||||
|  |     except ycdl.NoSuchVideo: | ||||||
|         flask.abort(404) |         flask.abort(404) | ||||||
|     except ValueError: | 
 | ||||||
|  |     except ycdl.InvalidVideoState: | ||||||
|         flask.abort(400) |         flask.abort(400) | ||||||
|  | 
 | ||||||
|     return make_json_response({'video_id': video_id, 'state': state}) |     return make_json_response({'video_id': video_id, 'state': state}) | ||||||
| 
 | 
 | ||||||
| @site.route('/refresh_all_channels', methods=['POST']) | @site.route('/refresh_all_channels', methods=['POST']) | ||||||
|  | @ -174,6 +176,13 @@ def post_refresh_channel(): | ||||||
|     channel_id = channel_id.strip() |     channel_id = channel_id.strip() | ||||||
|     if not channel_id: |     if not channel_id: | ||||||
|         flask.abort(400) |         flask.abort(400) | ||||||
|  |     if not (len(channel_id) == 24 and channel_id.startswith('UC')): | ||||||
|  |         # It seems they have given us a username instead. | ||||||
|  |         try: | ||||||
|  |             channel_id = youtube.youtube.get_user_id(username=channel_id) | ||||||
|  |         except IndexError: | ||||||
|  |             flask.abort(404) | ||||||
|  | 
 | ||||||
|     force = request.form.get('force', False) |     force = request.form.get('force', False) | ||||||
|     force = helpers.truthystring(force) |     force = helpers.truthystring(force) | ||||||
|     youtube.refresh_channel(channel_id, force=force) |     youtube.refresh_channel(channel_id, force=force) | ||||||
|  | @ -184,11 +193,11 @@ def post_start_download(): | ||||||
|     if 'video_id' not in request.form: |     if 'video_id' not in request.form: | ||||||
|         flask.abort(400) |         flask.abort(400) | ||||||
|     video_id = request.form['video_id'] |     video_id = request.form['video_id'] | ||||||
|     video_info = youtube_core.get_video([video_id]) |     try: | ||||||
|     if video_info == []: |         youtube.download_video(video_id) | ||||||
|  |     except ytapi.VideoNotFound: | ||||||
|         flask.abort(404) |         flask.abort(404) | ||||||
|     for video in video_info: | 
 | ||||||
|         youtube.download_video(video) |  | ||||||
|     return make_json_response({'video_id': video_id, 'state': 'downloaded'}) |     return make_json_response({'video_id': video_id, 'state': 'downloaded'}) | ||||||
| 
 | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|  |  | ||||||
							
								
								
									
										20
									
								
								ytapi.py
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								ytapi.py
									
									
									
									
									
								
							|  | @ -3,6 +3,9 @@ import datetime | ||||||
| 
 | 
 | ||||||
| import helpers | import helpers | ||||||
| 
 | 
 | ||||||
|  | class VideoNotFound(Exception): | ||||||
|  |     pass | ||||||
|  | 
 | ||||||
| class Video: | class Video: | ||||||
|     def __init__(self, snippet): |     def __init__(self, snippet): | ||||||
|         self.id = snippet['id'] |         self.id = snippet['id'] | ||||||
|  | @ -33,6 +36,10 @@ class Youtube: | ||||||
|         ) |         ) | ||||||
|         self.youtube = youtube |         self.youtube = youtube | ||||||
| 
 | 
 | ||||||
|  |     def get_user_id(self, username): | ||||||
|  |         user = self.youtube.channels().list(part='snippet', forUsername=username).execute() | ||||||
|  |         return user['items'][0]['id'] | ||||||
|  | 
 | ||||||
|     def get_user_name(self, uid): |     def get_user_name(self, uid): | ||||||
|         user = self.youtube.channels().list(part='snippet', id=uid).execute() |         user = self.youtube.channels().list(part='snippet', id=uid).execute() | ||||||
|         return user['items'][0]['snippet']['title'] |         return user['items'][0]['snippet']['title'] | ||||||
|  | @ -67,15 +74,18 @@ class Youtube: | ||||||
|             video_ids = [video_ids] |             video_ids = [video_ids] | ||||||
|         else: |         else: | ||||||
|             singular = False |             singular = False | ||||||
|         video_ids = helpers.chunk_sequence(video_ids, 50) | 
 | ||||||
|         results = [] |         results = [] | ||||||
|         for chunk in video_ids: |         chunks = helpers.chunk_sequence(video_ids, 50) | ||||||
|  |         for chunk in chunks: | ||||||
|             chunk = ','.join(chunk) |             chunk = ','.join(chunk) | ||||||
|             data = self.youtube.videos().list(part='snippet', id=chunk).execute() |             data = self.youtube.videos().list(part='snippet', id=chunk).execute() | ||||||
|             items = data['items'] |             items = data['items'] | ||||||
|             results += items |             results += items | ||||||
|             #print('Found %d more, %d total' % (len(items), len(results))) |  | ||||||
|         results = [Video(snippet) for snippet in results] |         results = [Video(snippet) for snippet in results] | ||||||
|         if singular and len(results) == 1: |         if singular: | ||||||
|             return results[0] |             if len(results) == 1: | ||||||
|  |                 return results[0] | ||||||
|  |             elif len(results) == 0: | ||||||
|  |                 raise VideoNotFound(video_ids[0]) | ||||||
|         return results |         return results | ||||||
|  |  | ||||||
|  | @ -18,6 +18,7 @@ while True: | ||||||
|     for filename in queue: |     for filename in queue: | ||||||
|         yt_id = filename.split('.')[0] |         yt_id = filename.split('.')[0] | ||||||
|         command = YOUTUBE_DL.format(id=yt_id) |         command = YOUTUBE_DL.format(id=yt_id) | ||||||
|         os.system(command) |         exit_code = os.system(command) | ||||||
|         os.remove(filename) |         if exit_code == 0: | ||||||
|  |             os.remove(filename) | ||||||
|     time.sleep(10) |     time.sleep(10) | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue