def test_wanted_queue_lock(): assert get_wanted_queue_lock() assert autosubliminal.WANTEDQUEUELOCK assert not get_wanted_queue_lock() assert autosubliminal.WANTEDQUEUELOCK release_wanted_queue_lock() assert not autosubliminal.WANTEDQUEUELOCK release_wanted_queue_lock() assert not autosubliminal.WANTEDQUEUELOCK
def save_subtitle(wanted_item_index, subtitle_index): log.info("Saving an individual subtitle") # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Get wanted item wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] found_subtitles = wanted_item['found_subtitles'] subtitles = found_subtitles['subtitles'] language = found_subtitles['language'] single = found_subtitles['single'] # Get selected subtitle wanted_subtitles = _get_wanted_subtitle(subtitles, subtitle_index) # Save subtitle (skip notify and post_process) download_item = _construct_download_item(wanted_item, wanted_subtitles, language, single) downloaded = SubDownloader(download_item).save() # Release wanted queue lock utils.release_wanted_queue_lock() return downloaded
def post_process_no_subtitle(wanted_item_index): log.info('Post processing without subtitle') # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Get wanted item wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] # Post process only (no need to check for individual or not because we are forcing post processing) processed = PostProcessor(wanted_item).run() # Remove wanted item if processed if processed: autosubliminal.WANTEDQUEUE.pop(int(wanted_item_index)) log.debug('Removed item from the wanted queue at index %s', int(wanted_item_index)) WantedItems().delete_wanted_item(wanted_item) log.debug('Removed %s from wanted_items database', wanted_item['videopath']) else: utils.add_notification_message( 'Unable to handle post processing! Please check the log file!', 'error') # Release wanted queue lock utils.release_wanted_queue_lock() return processed
def skip_show(wanted_item_index, season): log.info('Skipping a show') # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Get wanted item wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] show = wanted_item['title'] # Remove all wanted items for the same show and season to_delete_wanted_queue = [] for index, item in enumerate(autosubliminal.WANTEDQUEUE): if item['title'] == show: # Skip show all seasons if season == '00': to_delete_wanted_queue.append(index) # Skip season (and specials = season 0) elif season == item['season']: to_delete_wanted_queue.append(index) # Start at the end to delete to prevent index out of range error i = len(to_delete_wanted_queue) - 1 while i >= 0: wanted_item_to_delete = autosubliminal.WANTEDQUEUE.pop( to_delete_wanted_queue[i]) WantedItems().delete_wanted_item(wanted_item_to_delete) i -= 1 log.info('Skipped show %s season %s', show, season) # Release wanted queue lock utils.release_wanted_queue_lock() return True
def run(self, force_run): log.info("Checking version") # Wait for internet connection utils.wait_for_internet_connection() # Block version check (and update) in no force run mode when another process is using the wanted queue # We do not want to auto update the version while the application is busy with another process if not force_run and not utils.get_wanted_queue_lock(): return False # Check version self.manager.check_version(force_run) # Release wanted queue lock if not force_run: utils.release_wanted_queue_lock() # Only update and restart when: no force run, update is allowed and auto update is enabled if not force_run and self.manager.update_allowed and autosubliminal.CHECKVERSIONAUTOUPDATE: self.update() # Restart the app with exit of current process to have a clean restart scheduler.restart_app(exit=True) # Always return 'True' because we don't want to retry it until the next scheduled run return True
def post_process(wanted_item_index, subtitle_index): log.info("Post processing an individual subtitle") # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Get wanted item wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] found_subtitles = wanted_item['found_subtitles'] subtitles = found_subtitles['subtitles'] language = found_subtitles['language'] single = found_subtitles['single'] # Only execute post processing when a subtitle is present processed = False subtitle_path = _get_subtitle_path(wanted_item) if os.path.exists(subtitle_path): # Get selected subtitle wanted_subtitles = _get_wanted_subtitle(subtitles, subtitle_index) # Post process only download_item = _construct_download_item(wanted_item, wanted_subtitles, language, single) processed = SubDownloader(download_item).post_process() # Remove from wanted queue is downloaded if processed: autosubliminal.WANTEDQUEUE.pop(int(wanted_item_index)) else: log.warning("No subtitle downloaded, skipping post processing") # Release wanted queue lock utils.release_wanted_queue_lock() return processed
def run(self, force_run): log.info("Starting round of local disk checking at %s" % autosubliminal.VIDEOPATHS) # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Show info message (only when run was forced manually) if force_run: utils.add_notification_message("Scanning disk...") # Check if a directory exists to scan one_dir_exists = False for videodir in autosubliminal.VIDEOPATHS: if os.path.exists(videodir): one_dir_exists = True else: # In case of a network path, it's possible that the path is not directly found -> sleep and check again time.sleep(15) if os.path.exists(videodir): one_dir_exists = True if not one_dir_exists: # Release wanted queue lock log.error("None of the configured video paths (%s) exist, aborting..." % autosubliminal.VIDEOPATHS) utils.release_wanted_queue_lock() return True # Reset the wanted queue before walking through paths and adding the wanted items autosubliminal.WANTEDQUEUE = [] for videodir in autosubliminal.VIDEOPATHS: try: walk_dir(videodir) except Exception, e: log.error("Could not scan the video path (%s), skipping..." % videodir) log.exception(e)
def delete_video(wanted_item_index, cleanup): log.info('Deleting an individual video file') # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Remove wanted item wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] autosubliminal.WANTEDQUEUE.pop(int(wanted_item_index)) log.debug('Removed item from the wanted queue at index %s', int(wanted_item_index)) WantedItems().delete_wanted_item(wanted_item) log.debug('Removed %s from wanted_items database', wanted_item['videopath']) # Physically delete the video file (and optionally leftovers) deleted = False video_path = wanted_item['videopath'] # Delete with cleanup if cleanup: norm_video_path = os.path.normcase(os.path.normpath(video_path)) norm_video_folder = os.path.dirname(norm_video_path).rstrip(os.sep) for root_folder in autosubliminal.VIDEOPATHS: # Get root folder norm_root_folder = os.path.normcase( os.path.normpath(root_folder)).rstrip(os.sep) # Check if video is located in subfolder underneath root folder if os.path.commonprefix([norm_root_folder, norm_video_path]) == norm_root_folder: if norm_video_folder != norm_root_folder: # Move up until the first subfolder underneath the root folder to cleanup while norm_video_folder != norm_root_folder: folder_to_clean = norm_video_folder norm_video_folder = os.path.dirname( norm_video_folder).rstrip(os.sep) try: # Remove the folder of the video underneath the root folder shutil.rmtree(folder_to_clean, onerror=utils.set_rw_and_remove) log.info('Deleted video folder: %s', folder_to_clean) deleted = True # Break for loop break except Exception: log.exception('Unable to delete video folder: %s', folder_to_clean) # Delete video file only if not deleted: try: os.remove(video_path) log.info('Deleted file: %s', video_path) deleted = True except Exception: log.exception('Unable to delete file: %s', video_path) # Release wanted queue lock utils.release_wanted_queue_lock() return deleted
def post_process(wanted_item_index, subtitle_index): log.info('Post processing an individual subtitle') # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Get wanted item wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] found_subtitles = wanted_item['found_subtitles'] subtitles = found_subtitles['subtitles'] language = found_subtitles['language'] single = found_subtitles['single'] # Only execute post processing when a subtitle is present processed = False subtitle_path = _get_subtitle_path(wanted_item) if os.path.exists(subtitle_path): # Get wanted subtitle wanted_subtitle = _get_wanted_subtitle(subtitles, subtitle_index) # Handle download download_item = _construct_download_item(wanted_item, [wanted_subtitle], language, single) downloader = SubDownloader(download_item) downloader.mark_downloaded() processed = downloader.post_process() if processed: # Remove downloaded language from wanted languages wanted_item['languages'].remove(language) # Update wanted item if there are still wanted languages if len(wanted_item['languages']) > 0: WantedItems().update_wanted_item(wanted_item) # Remove wanted item if there are no more wanted languages else: # Remove wanted item autosubliminal.WANTEDQUEUE.pop(int(wanted_item_index)) log.debug('Removed item from the wanted queue at index %s', int(wanted_item_index)) WantedItems().delete_wanted_item(wanted_item) log.debug('Removed %s from wanted_items database', wanted_item['videopath']) else: log.warning('No subtitle downloaded, skipping post processing') # Release wanted queue lock utils.release_wanted_queue_lock() return processed
def run(self, force_run): log.info("Starting round of subtitle checking") to_delete_wanted_queue = [] # Wait for internet connection utils.wait_for_internet_connection() # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Show info message (only when run was forced manually) if force_run: utils.add_notification_message("Checking subtitles...") # Process all items in wanted queue for index, wanted_item in enumerate(autosubliminal.WANTEDQUEUE): # Scan wanted_item for video, skip when no video could be determined video = _scan_wanted_item_for_video(wanted_item) if not video: continue # Check subtitles for each language langs = wanted_item['lang'] for lang in langs[:]: # Search the best subtitle with the minimal score subtitles, language, single = _search_subtitles( video, lang, True) # Save when a subtitle is found for the video if subtitles[video]: download_item = _construct_download_item( wanted_item, subtitles, language, single) SubDownloader(download_item).run() # Remove from wanted queue if needed (if no additional languages are still needed) langs.remove(lang) if len(langs) == 0: to_delete_wanted_queue.append(index) # Cleanup wanted queue i = len(to_delete_wanted_queue) - 1 while i >= 0: log.debug("Removed item from the wanted queue at index %s" % to_delete_wanted_queue[i]) autosubliminal.WANTEDQUEUE.pop(to_delete_wanted_queue[i]) i -= 1 # Release wanted queue lock log.info("Finished round of subtitle checking") utils.release_wanted_queue_lock() return True
def flush_wanted_items(self): if utils.get_wanted_queue_lock(): # Flush db and wanted queue WantedItems().flush_wanted_items() autosubliminal.WANTEDQUEUE = [] utils.release_wanted_queue_lock() utils.add_notification_message( 'Flushed wanted items database. Please launch system \'Scan Disk\'.' ) else: utils.add_notification_message( 'Cannot flush wanted items database when wanted queue is in use!', 'notice') redirect('/home')
def run(self, force_run): log.info("Starting round of subtitle checking") to_delete_wanted_queue = [] # Wait for internet connection utils.wait_for_internet_connection() # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Show info message (only when run was forced manually) if force_run: utils.add_notification_message("Checking subtitles...") # Process all items in wanted queue for index, wanted_item in enumerate(autosubliminal.WANTEDQUEUE): # Scan wanted_item for video, skip when no video could be determined video = _scan_wanted_item_for_video(wanted_item) if not video: continue # Check subtitles for each language langs = wanted_item['lang'] for lang in langs[:]: # Search the best subtitle with the minimal score subtitles, language, single = _search_subtitles(video, lang, True) # Save when a subtitle is found for the video if subtitles[video]: download_item = _construct_download_item(wanted_item, subtitles, language, single) SubDownloader(download_item).run() # Remove from wanted queue if needed (if no additional languages are still needed) langs.remove(lang) if len(langs) == 0: to_delete_wanted_queue.append(index) # Cleanup wanted queue i = len(to_delete_wanted_queue) - 1 while i >= 0: log.debug("Removed item from the wanted queue at index %s" % to_delete_wanted_queue[i]) autosubliminal.WANTEDQUEUE.pop(to_delete_wanted_queue[i]) i -= 1 # Release wanted queue lock log.info("Finished round of subtitle checking") utils.release_wanted_queue_lock() return True
def update(self): log.info("Updating version") # Block update when another process is using the wanted queue # We do not want to update the version while the application is busy with another process if not utils.get_wanted_queue_lock(): return False # Update version self.manager.update_version() # Release wanted queue lock utils.release_wanted_queue_lock() return True
def force_id_search(wanted_item_index): log.info("Force id search") # Get wanted queue lock if not utils.get_wanted_queue_lock(): return # Force id search wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] title = wanted_item['title'] year = wanted_item['year'] if wanted_item['type'] == 'episode': wanted_item['tvdbid'] = utils.get_tvdb_id(title, True) elif wanted_item['type'] == 'movie': wanted_item['imdbid'], wanted_item['year'] = utils.get_imdb_info(title, year, True) # Release wanted queue lock utils.release_wanted_queue_lock()
def delete_subtitle(wanted_item_index): log.info("Deleting an individual subtitle") # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Get wanted item wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] # Delete subtitle deleted = False subtitle_path = _get_subtitle_path(wanted_item) try: os.remove(subtitle_path) deleted = True except Exception, e: log.error("Unable to delete subtitle: %s" % subtitle_path) log.error("Exception: %s" % e)
def delete_video(wanted_item_index, cleanup): log.info("Deleting an individual video file") # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Remove wanted item for queue wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] autosubliminal.WANTEDQUEUE.pop(int(wanted_item_index)) # Physically delete the video file (and optionally leftovers) deleted = False video_path = wanted_item['originalFileLocationOnDisk'] # Delete with cleanup if cleanup: norm_video_path = os.path.normcase(os.path.normpath(video_path)) norm_video_folder = os.path.dirname(norm_video_path).rstrip(os.sep) for root_folder in autosubliminal.VIDEOPATHS: # Get root folder norm_root_folder = os.path.normcase( os.path.normpath(root_folder)).rstrip(os.sep) # Check if video is located in subfolder underneath root folder if os.path.commonprefix([norm_root_folder, norm_video_path]) == norm_root_folder: if norm_video_folder != norm_root_folder: # Move up until the first subfolder underneath the root folder to cleanup while norm_video_folder != norm_root_folder: folder_to_clean = norm_video_folder norm_video_folder = os.path.dirname( norm_video_folder).rstrip(os.sep) try: # Remove the folder of the video underneath the root folder shutil.rmtree(folder_to_clean, onerror=utils.set_rw_and_remove) log.info("Deleted video folder: %s" % folder_to_clean) deleted = True # Break for loop break except Exception, e: log.error("Unable to delete video folder: %s" % folder_to_clean) log.error("Exception: %s" % e)
def skip_movie(wanted_item_index): log.info('Skipping a movie') # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Remove wanted item from queue and db wanted_item = autosubliminal.WANTEDQUEUE.pop(int(wanted_item_index)) WantedItems().delete_wanted_item(wanted_item) movie = wanted_item['title'] if wanted_item['year']: movie += ' (' + wanted_item['year'] + ')' log.info('Skipped movie %s', movie) # Release wanted queue lock utils.release_wanted_queue_lock() return True
def force_id_search(wanted_item_index): log.info("Force id search") # Get wanted queue lock if not utils.get_wanted_queue_lock(): return # Force id search wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] title = wanted_item['title'] year = wanted_item['year'] if wanted_item['type'] == 'episode': wanted_item['tvdbid'] = utils.get_tvdb_id(title, True) elif wanted_item['type'] == 'movie': wanted_item['imdbid'], wanted_item['year'] = utils.get_imdb_info( title, year, True) # Release wanted queue lock utils.release_wanted_queue_lock()
def post_process_no_subtitle(wanted_item_index): log.info("Post processing without subtitle") # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Get wanted item wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] # Post process only processed = PostProcessor(wanted_item).run() # Remove from wanted queue is downloaded if processed: autosubliminal.WANTEDQUEUE.pop(int(wanted_item_index)) # Release wanted queue lock utils.release_wanted_queue_lock() return processed
def run(self, force_run): log.info("Starting round of local disk checking at %s" % autosubliminal.VIDEOPATHS) # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Show info message (only when run was forced manually) if force_run: utils.add_notification_message("Scanning disk...") # Check if a directory exists to scan one_dir_exists = False for videodir in autosubliminal.VIDEOPATHS: if os.path.exists(videodir): one_dir_exists = True else: # In case of a network path, it's possible that the path is not directly found -> sleep and check again time.sleep(15) if os.path.exists(videodir): one_dir_exists = True if not one_dir_exists: # Release wanted queue lock log.error( "None of the configured video paths (%s) exist, aborting..." % autosubliminal.VIDEOPATHS) utils.release_wanted_queue_lock() return True # Reset the wanted queue before walking through paths and adding the wanted items autosubliminal.WANTEDQUEUE = [] for videodir in autosubliminal.VIDEOPATHS: try: walk_dir(videodir) except Exception, e: log.error("Could not scan the video path (%s), skipping..." % videodir) log.exception(e)
def delete_video(wanted_item_index, cleanup): log.info("Deleting an individual video file") # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Remove wanted item for queue wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] autosubliminal.WANTEDQUEUE.pop(int(wanted_item_index)) # Physically delete the video file (and optionally leftovers) deleted = False video_path = wanted_item['originalFileLocationOnDisk'] # Delete with cleanup if cleanup: norm_video_path = os.path.normcase(os.path.normpath(video_path)) norm_video_folder = os.path.dirname(norm_video_path).rstrip(os.sep) for root_folder in autosubliminal.VIDEOPATHS: # Get root folder norm_root_folder = os.path.normcase(os.path.normpath(root_folder)).rstrip(os.sep) # Check if video is located in subfolder underneath root folder if os.path.commonprefix([norm_root_folder, norm_video_path]) == norm_root_folder: if norm_video_folder != norm_root_folder: # Move up until the first subfolder underneath the root folder to cleanup while norm_video_folder != norm_root_folder: folder_to_clean = norm_video_folder norm_video_folder = os.path.dirname(norm_video_folder).rstrip(os.sep) try: # Remove the folder of the video underneath the root folder shutil.rmtree(folder_to_clean, onerror=utils.set_rw_and_remove) log.info("Deleted video folder: %s" % folder_to_clean) deleted = True # Break for loop break except Exception, e: log.error("Unable to delete video folder: %s" % folder_to_clean) log.error("Exception: %s" % e)
def force_id_search(wanted_item_index): log.info('Force id search') # Get wanted queue lock if not utils.get_wanted_queue_lock(): return # Force id search wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] title = wanted_item['title'] year = wanted_item['year'] if wanted_item['type'] == 'episode': wanted_item['tvdbid'] = autosubliminal.SHOWINDEXER.get_tvdb_id( title, year, force_search=True) WantedItems().update_wanted_item(wanted_item) elif wanted_item['type'] == 'movie': wanted_item['imdbid'], wanted_item[ 'year'] = autosubliminal.MOVIEINDEXER.get_imdb_id_and_year( title, year, True) WantedItems().update_wanted_item(wanted_item) # Release wanted queue lock utils.release_wanted_queue_lock()
def delete_subtitle(wanted_item_index): log.info('Deleting an individual subtitle') # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Get wanted item wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] # Delete subtitle deleted = False subtitle_path = _get_subtitle_path(wanted_item) try: os.remove(subtitle_path) deleted = True except Exception: log.exception('Unable to delete subtitle: %s', subtitle_path) # Release wanted queue lock utils.release_wanted_queue_lock() return deleted
def search_subtitle(wanted_item_index, lang): log.info("Searching for an individual subtitle") subs = [] # Get wanted queue lock if not utils.get_wanted_queue_lock(): return subs, "Skipping! Cannot get a wanted queue lock because another threat is using the queues!" # Get wanted_item wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] # Scan wanted_item for video video = _scan_wanted_item_for_video(wanted_item) if video: # Search the subtitles with the default minimal score (to get all the possibilities to select from) subtitles, language, single = _search_subtitles(video, lang, False) # Check if subtitles are found for the video if subtitles[video]: # Add found subtitles to wanted_item wanted_item['found_subtitles'] = {'subtitles': subtitles, 'language': language, 'single': single} # Order subtitles by score and create new dict # Use subliminal scoring (scores=None) for index, subtitle, score in sorted([(index, s, subliminal.compute_score( s.get_matches(video, hearing_impaired=utils.include_hearing_impaired()), video, scores=None)) for index, s in enumerate(subtitles[video])], key=operator.itemgetter(2), reverse=True): # Only add subtitle when content is found if subtitle.content: # Create new sub dict for showing result sub = {'subtitle_index': index, 'score': score, 'provider_name': subtitle.provider_name, 'content': subtitle.content, 'language': language, 'single': single, 'page_link': subtitle.page_link, 'releases': _get_releases(subtitle), 'wanted_item_index': wanted_item_index, 'playvideo_url': _construct_playvideo_url(wanted_item)} # Get content preview (the first 28 lines and last 30 lines of the subtitle) content_split = subtitle.content.splitlines(False) if len(content_split) < 58: content_preview = "This seems to be an invalid subtitle." content_preview += "<br> It has less than 58 lines to preview." else: try: # First 28 lines content_preview = "<br>".join( x.replace('"', "'") for x in content_split[:28]) # Separator content_preview += "<br>" content_preview += "<br>" content_preview += "..." content_preview += "<br>" content_preview += "<br>" # Last 30 lines content_preview += "<br>".join( x.replace('"', "'") for x in content_split[len(content_split) - 30:]) except: content_preview = "Problem with parsing the first 28 and/or last 30 lines of the file." sub['content_preview'] = content_preview subs.append(sub) # Release wanted queue lock utils.release_wanted_queue_lock() if not len(subs): return subs, "No subtitles could be found or downloaded!" return subs, None
def search_subtitle(wanted_item_index, lang): log.info('Searching for an individual subtitle') subs = [] # Get wanted queue lock if not utils.get_wanted_queue_lock(): return subs, 'Skipping! Cannot get a wanted queue lock because another thread is using the queues!' # Setup provider pool provider_pool = _get_provider_pool() if provider_pool: log.info('Searching subtitles with providers: %s', ', '.join(provider_pool.providers)) # Get wanted_item wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] log.info('Searching subtitles for video: %s', wanted_item['videopath']) # Scan wanted_item for video video = _scan_wanted_item_for_video(wanted_item, True) if video: # Search the subtitles with the default minimal score (to get all the possibilities to select from) default_min_score = _get_min_match_score(video, True) subtitles, language, single = _search_subtitles( video, lang, False, provider_pool) # Check if subtitles are found for the video if subtitles: # Add found subtitles to wanted_item wanted_item['found_subtitles'] = { 'subtitles': subtitles, 'language': language, 'single': single } # Order subtitles by score and create new dict # Use subliminal default compute_score for index, subtitle, score in sorted( [(index, s, subliminal.compute_score( s, video, autosubliminal.PREFERHEARINGIMPAIRED)) for index, s in enumerate(subtitles)], key=operator.itemgetter(2), reverse=True): # Filter out subtitles that do not match the default score if score < default_min_score: log.debug('Skipping subtitle %s with score below %d', subtitle, default_min_score) break # Only add subtitle when content is found if subtitle.content: # Create new sub dict for showing result sub = { 'subtitle_index': index, 'score': score, 'provider_name': subtitle.provider_name, 'content': subtitle.content, 'language': language, 'single': single, 'page_link': subtitle.page_link, 'releases': _get_releases(subtitle), 'wanted_item_index': wanted_item_index, 'playvideo_url': _construct_playvideo_url(wanted_item) } # Get content preview (the first 28 lines and last 30 lines of the subtitle) # Use the subtitle text (decoded content) instead of content to generate the preview content_split = subtitle.text.splitlines(False) if len(content_split) < 58: content_preview = 'This seems to be an invalid subtitle.' content_preview += '<br> It has less than 58 lines to preview.' else: try: # First 28 lines content_preview = '<br>'.join( x.replace('"', '\'') for x in content_split[:28]) # Separator content_preview += '<br>' content_preview += '<br>' content_preview += '...' content_preview += '<br>' content_preview += '<br>' # Last 30 lines content_preview += '<br>'.join( x.replace('"', '\'') for x in content_split[len(content_split) - 30:]) except Exception: content_preview = 'Problem with parsing the first 28 and/or last 30 lines of the file.' sub['content_preview'] = content_preview subs.append(sub) # Release wanted queue lock utils.release_wanted_queue_lock() if not provider_pool: return subs, 'Skipping! No subliminal providers are configured!' if not len(subs): return subs, 'No subtitles could be found or downloaded!' return subs, None
def run(self, force_run): # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False log.info('Starting round of local disk checking at %r', autosubliminal.VIDEOPATHS) # Show info message (only when run was forced manually) if force_run: utils.add_notification_message('Scanning disk...') # Check if a directory exists to scan one_dir_exists = False for videodir in autosubliminal.VIDEOPATHS: if os.path.exists(videodir): one_dir_exists = True else: # In case of a network path, it's possible that the path is not directly found -> sleep and check again time.sleep(15) if os.path.exists(videodir): one_dir_exists = True if not one_dir_exists: # Release wanted queue lock log.error( 'None of the configured video paths (%r) exists, aborting...', autosubliminal.VIDEOPATHS) utils.release_wanted_queue_lock() return True # Walk through paths to search for wanted items new_wanted_items = [] db = WantedItems() old_wanted_items = db.get_wanted_items() for videodir in autosubliminal.VIDEOPATHS: try: new_wanted_items.extend(walk_dir(videodir)) except Exception: log.exception( 'Could not scan the video path (%s), skipping it', videodir) # Cleanup wanted items that have been removed from disk manually but are still stored in the db log.debug( 'Checking for non existing wanted items in wanted_items database') for item in old_wanted_items: if item not in new_wanted_items: db.delete_wanted_item(item) log.debug('Deleted non existing wanted item: %s', item['videopath']) # Populate WANTEDQUEUE with all items from wanted_items database log.info('Listing videos with missing subtitles:') autosubliminal.WANTEDQUEUE = [] for item in db.get_wanted_items(): log.info('%s %s', item['videopath'], item['languages']) autosubliminal.WANTEDQUEUE.append(item) # Release wanted queue lock log.info('Finished round of local disk checking') utils.release_wanted_queue_lock() # Send home page reload event utils.add_event_message('HOME_PAGE_RELOAD') return True
def search_subtitle(wanted_item_index, lang): log.info("Searching for an individual subtitle") subs = [] # Get wanted queue lock if not utils.get_wanted_queue_lock(): return subs, "Skipping! Cannot get a wanted queue lock because another threat is using the queues!" # Get wanted_item wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)] # Scan wanted_item for video video = _scan_wanted_item_for_video(wanted_item) if video: # Search the subtitles with the default minimal score (to get all the possibilities to select from) subtitles, language, single = _search_subtitles(video, lang, False) # Check if subtitles are found for the video if subtitles[video]: # Add found subtitles to wanted_item wanted_item['found_subtitles'] = { 'subtitles': subtitles, 'language': language, 'single': single } # Order subtitles by score and create new dict # Use subliminal scoring (scores=None) for index, subtitle, score in sorted([ (index, s, subliminal.compute_score(s.get_matches( video, hearing_impaired=utils.include_hearing_impaired()), video, scores=None)) for index, s in enumerate(subtitles[video]) ], key=operator.itemgetter(2), reverse=True): # Only add subtitle when content is found if subtitle.content: # Create new sub dict for showing result sub = { 'subtitle_index': index, 'score': score, 'provider_name': subtitle.provider_name, 'content': subtitle.content, 'language': language, 'single': single, 'page_link': subtitle.page_link, 'releases': _get_releases(subtitle), 'wanted_item_index': wanted_item_index, 'playvideo_url': _construct_playvideo_url(wanted_item) } # Get content preview (the first 28 lines and last 30 lines of the subtitle) content_split = subtitle.content.splitlines(False) if len(content_split) < 58: content_preview = "This seems to be an invalid subtitle." content_preview += "<br> It has less than 58 lines to preview." else: try: # First 28 lines content_preview = "<br>".join( x.replace('"', "'") for x in content_split[:28]) # Separator content_preview += "<br>" content_preview += "<br>" content_preview += "..." content_preview += "<br>" content_preview += "<br>" # Last 30 lines content_preview += "<br>".join( x.replace('"', "'") for x in content_split[len(content_split) - 30:]) except: content_preview = "Problem with parsing the first 28 and/or last 30 lines of the file." sub['content_preview'] = content_preview subs.append(sub) # Release wanted queue lock utils.release_wanted_queue_lock() if not len(subs): return subs, "No subtitles could be found or downloaded!" return subs, None
def run(self, force_run): # Get wanted queue lock if not utils.get_wanted_queue_lock(): return False # Wait for internet connection utils.wait_for_internet_connection() log.info('Starting round of subtitle checking') to_delete_wanted_queue = [] # Show info message (only when run was forced manually) if force_run: utils.add_notification_message('Checking subtitles...') # Setup provider pool provider_pool = _get_provider_pool() if provider_pool: log.info('Searching subtitles with providers: %s', ', '.join(provider_pool.providers)) # Process all items in wanted queue db = WantedItems() for index, wanted_item in enumerate(autosubliminal.WANTEDQUEUE): log.info('Searching subtitles for video: %s', wanted_item['videopath']) # Check if the search is currently active for the wanted_item if not WantedItem(wanted_item).search_active: log.info('Search not active in this run for video: %s', wanted_item['videopath']) continue # Scan wanted_item for video, skip when no video could be determined video = _scan_wanted_item_for_video(wanted_item) if not video: continue # Clear discarded providers for each new wanted_item provider_pool.discarded_providers.clear() # Check subtitles for each language languages = wanted_item['languages'] for lang in languages[:]: # Search the best subtitle with the minimal score try: subtitles, language, single = _search_subtitles( video, lang, True, provider_pool) except Exception: log.exception( 'Error while searching subtitles for video %r', wanted_item['videopath']) continue # Subtitle is found for the video if subtitles: # Handle download download_item = _construct_download_item( wanted_item, subtitles, language, single) SubDownloader(download_item).run() # Remove downloaded language from wanted languages languages.remove(lang) # Update wanted item if there are still wanted languages if len(languages) > 0: db.update_wanted_item(wanted_item) # Mark wanted item as deleted if there are no more wanted languages else: to_delete_wanted_queue.append(index) # Cleanup wanted item(s) i = len(to_delete_wanted_queue) - 1 while i >= 0: wanted_item_to_delete = autosubliminal.WANTEDQUEUE.pop( to_delete_wanted_queue[i]) log.debug('Removed item from the wanted queue at index %s', to_delete_wanted_queue[i]) db.delete_wanted_item(wanted_item_to_delete) log.debug('Removed %s from wanted_items database', wanted_item_to_delete['videopath']) i -= 1 else: log.info('No subliminal providers configured, skipping') # Release wanted queue lock log.info('Finished round of subtitle checking') utils.release_wanted_queue_lock() # Send home page reload event utils.add_event_message('HOME_PAGE_RELOAD') return True