Beispiel #1
0
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
Beispiel #2
0
def skip_show(wanted_item_index, season):
    log.info('Skipping a show')

    # Get wanted queue lock
    if not 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])
        WantedItemsDb().delete_wanted_item(wanted_item_to_delete)
        i -= 1
    log.info('Skipped show %s season %s', show, season)

    # Release wanted queue lock
    release_wanted_queue_lock()

    return True
Beispiel #3
0
def save_subtitle(wanted_item_index, subtitle_index):
    log.info('Saving an individual subtitle')

    # Get wanted queue lock
    if not 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 wanted subtitle
    wanted_subtitle = _get_wanted_subtitle(subtitles, subtitle_index)

    # Save subtitle (skip notify and post_process)
    download_item = _construct_download_item(wanted_item, [wanted_subtitle], language, single)
    downloaded = SubDownloader(download_item).save()

    # Release wanted queue lock
    release_wanted_queue_lock()

    return downloaded
Beispiel #4
0
def post_process_no_subtitle(wanted_item_index):
    log.info('Post processing without subtitle')

    # Get wanted queue lock
    if not 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))
        WantedItemsDb().delete_wanted_item(wanted_item)
        log.debug('Removed %s from wanted_items database', wanted_item.videopath)
    else:
        send_websocket_notification('Unable to handle post processing! Please check the log file!', type='error')

    # Release wanted queue lock
    release_wanted_queue_lock()

    return processed
Beispiel #5
0
def delete_video(wanted_item_index, cleanup):
    log.info('Deleting an individual video file')

    # Get wanted queue lock
    if not 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))
    WantedItemsDb().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=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
    release_wanted_queue_lock()

    return deleted
Beispiel #6
0
 def flush_wanted_items(self):
     if get_wanted_queue_lock():
         # Flush db and wanted queue
         WantedItemsDb().flush_wanted_items()
         autosubliminal.WANTEDQUEUE = []
         release_wanted_queue_lock()
         send_websocket_notification(
             'Flushed wanted items database. Please launch \'Scan Disk\' from the \'System\' menu.')
     else:
         send_websocket_notification('Cannot flush wanted items database when wanted queue is in use!',
                                     type='notice')
     redirect('/home')
    def update(self, force_update=False):
        log.info('Updating version')

        # Only get lock for force run because when called from run, we already have a queue lock
        if force_update and not get_wanted_queue_lock():
            return

        # Update version
        self.manager.update_version()

        # Release wanted queue lock
        if force_update:
            release_wanted_queue_lock()
    def update(self, force_update=False):
        log.info('Updating version')

        # Only get lock for force run because when called from run, we already have a queue lock
        if force_update and not get_wanted_queue_lock():
            return

        # Update version
        self.manager.update_version()

        # Release wanted queue lock
        if force_update:
            release_wanted_queue_lock()
Beispiel #9
0
def post_process(wanted_item_index, subtitle_index):
    log.info('Post processing an individual subtitle')

    # Get wanted queue lock
    if not 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:
                WantedItemsDb().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))
                WantedItemsDb().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
    release_wanted_queue_lock()

    return processed
Beispiel #10
0
    def update_wanted_item(self, wanted_item_index, **kwargs):
        if get_wanted_queue_lock():
            # Get wanted item and update all keys that are passed
            wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)]
            for key in kwargs:
                wanted_item.set_attr(key, kwargs[key])

            # Release wanted queue lock
            release_wanted_queue_lock()

            # Only return updatable fields
            # These values will be shown in the view through jquery, so apply the display_value() on it!
            return {
                'displaytitle':
                display_item_title(wanted_item),
                'title':
                display_value(wanted_item.title),
                'year':
                display_value(wanted_item.year),
                'season':
                display_value(wanted_item.season),
                'episode':
                display_value(wanted_item.episode),
                'source':
                display_value(wanted_item.source,
                              default_value='N/A',
                              uppercase=True),
                'quality':
                display_value(wanted_item.quality,
                              default_value='N/A',
                              uppercase=True),
                'codec':
                display_value(wanted_item.codec,
                              default_value='N/A',
                              uppercase=True),
                'releasegrp':
                display_value(wanted_item.releasegrp,
                              default_value='N/A',
                              uppercase=True)
            }

        # Show notification if wanted queue is in use
        send_websocket_notification(
            'Cannot update wanted item when wanted queue is in use!',
            type='notice')
Beispiel #11
0
def skip_movie(wanted_item_index):
    log.info('Skipping a movie')

    # Get wanted queue lock
    if not get_wanted_queue_lock():
        return False

    # Remove wanted item from queue and db
    wanted_item = autosubliminal.WANTEDQUEUE.pop(int(wanted_item_index))
    WantedItemsDb().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
    release_wanted_queue_lock()

    return True
Beispiel #12
0
def force_id_search(wanted_item_index):
    log.info('Force id search')

    # Get wanted queue lock
    if not 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.is_episode:
        wanted_item.tvdbid = autosubliminal.SHOWINDEXER.get_tvdb_id(title, year, force_search=True)
        WantedItemsDb().update_wanted_item(wanted_item)
    elif wanted_item.is_movie:
        wanted_item.imdbid, wanted_item.year = autosubliminal.MOVIEINDEXER.get_imdb_id_and_year(title, year,
                                                                                                force_search=True)
        WantedItemsDb().update_wanted_item(wanted_item)

    # Release wanted queue lock
    release_wanted_queue_lock()
Beispiel #13
0
    def reset_wanted_item(self, wanted_item_index, **kwargs):
        if get_wanted_queue_lock():
            # Get wanted item and reset values
            wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)]
            wanted_item_db = WantedItemsDb().get_wanted_item(
                wanted_item.videopath)
            wanted_item_db.copy_to(wanted_item)

            # Release wanted queue lock
            release_wanted_queue_lock()

            # Only return updatable fields
            # These values represent the original values, so apply default display_value() on it!
            return {
                'displaytitle':
                display_item_title(wanted_item),
                'title':
                display_value(wanted_item.title),
                'year':
                display_value(wanted_item.year),
                'season':
                display_value(wanted_item.season),
                'episode':
                display_value(wanted_item.episode),
                'source':
                display_value(wanted_item.source, default_value='N/A'),
                'quality':
                display_value(wanted_item.quality, default_value='N/A'),
                'codec':
                display_value(wanted_item.codec, default_value='N/A'),
                'releasegrp':
                display_value(wanted_item.releasegrp, default_value='N/A')
            }

        # Show notification if wanted queue is in use
        send_websocket_notification(
            'Cannot reset wanted item when wanted queue is in use!',
            type='notice')
Beispiel #14
0
def delete_subtitle(wanted_item_index):
    log.info('Deleting an individual subtitle')

    # Get wanted queue lock
    if not 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
    release_wanted_queue_lock()

    return deleted
Beispiel #15
0
    def _run_process(self, current_time):
        # Check if the run needs a lock
        run_lock = self.process.force_run_lock if self._force_run else self.process.run_lock

        # Delay process if lock cannot be acquired
        if run_lock and not get_wanted_queue_lock():
            # Increase delay with 1 second each time the process cannot yet run
            self._delay += 1
            return

        try:
            # Mark as running
            self.process.running = True
            send_websocket_event(PROCESS_STARTED, data=self.to_json())

            log.debug('Running %s thread process', self.name)
            self.process.run(self._force_run)

            # Update process properties after process run
            self.last_run = current_time
            self._delay = 0
            if self._force_run:
                self._force_run = False

            # Mark as finished
            self.process.running = False
            send_websocket_event(PROCESS_FINISHED, data=self.to_json())

        except:
            print(traceback.format_exc())
            self.process.running = False
            os._exit(1)

        finally:
            # Release lock if needed
            if run_lock:
                release_wanted_queue_lock()
Beispiel #16
0
    def _run_process(self, current_time):
        # Check if the run needs a lock
        run_lock = self.process.force_run_lock if self._force_run else self.process.run_lock

        # Delay process if lock cannot be acquired
        if run_lock and not get_wanted_queue_lock():
            # Increase delay with 1 second each time the process cannot yet run
            self._delay += 1
            return

        try:
            # Mark as running
            self.process.running = True
            send_websocket_event(PROCESS_STARTED, data=self.to_json())

            log.debug('Running %s thread process', self.name)
            self.process.run(self._force_run)

            # Update process properties after process run
            self.last_run = current_time
            self._delay = 0
            if self._force_run:
                self._force_run = False

            # Mark as finished
            self.process.running = False
            send_websocket_event(PROCESS_FINISHED, data=self.to_json())

        except:
            print(traceback.format_exc())
            self.process.running = False
            os._exit(1)

        finally:
            # Release lock if needed
            if run_lock:
                release_wanted_queue_lock()
Beispiel #17
0
    def reset_wanted_item(self, wanted_item_index, **kwargs):
        if get_wanted_queue_lock():
            # Get wanted item and reset values
            wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)]
            wanted_item_db = WantedItemsDb().get_wanted_item(wanted_item.videopath)
            wanted_item_db.copy_to(wanted_item)

            # Release wanted queue lock
            release_wanted_queue_lock()

            # Only return updatable fields
            # These values represent the original values, so apply default display_value() on it!
            return {'displaytitle': display_item_title(wanted_item),
                    'title': display_value(wanted_item.title),
                    'year': display_value(wanted_item.year),
                    'season': display_value(wanted_item.season),
                    'episode': display_value(wanted_item.episode),
                    'source': display_value(wanted_item.source, default_value='N/A'),
                    'quality': display_value(wanted_item.quality, default_value='N/A'),
                    'codec': display_value(wanted_item.codec, default_value='N/A'),
                    'releasegrp': display_value(wanted_item.releasegrp, default_value='N/A')}

        # Show notification if wanted queue is in use
        send_websocket_notification('Cannot reset wanted item when wanted queue is in use!', type='notice')
Beispiel #18
0
    def update_wanted_item(self, wanted_item_index, **kwargs):
        if get_wanted_queue_lock():
            # Get wanted item and update all keys that are passed
            wanted_item = autosubliminal.WANTEDQUEUE[int(wanted_item_index)]
            for key in kwargs:
                wanted_item.set_attr(key, kwargs[key])

            # Release wanted queue lock
            release_wanted_queue_lock()

            # Only return updatable fields
            # These values will be shown in the view through jquery, so apply the display_value() on it!
            return {'displaytitle': display_item_title(wanted_item),
                    'title': display_value(wanted_item.title),
                    'year': display_value(wanted_item.year),
                    'season': display_value(wanted_item.season),
                    'episode': display_value(wanted_item.episode),
                    'source': display_value(wanted_item.source, default_value='N/A', uppercase=True),
                    'quality': display_value(wanted_item.quality, default_value='N/A', uppercase=True),
                    'codec': display_value(wanted_item.codec, default_value='N/A', uppercase=True),
                    'releasegrp': display_value(wanted_item.releasegrp, default_value='N/A', uppercase=True)}

        # Show notification if wanted queue is in use
        send_websocket_notification('Cannot update wanted item when wanted queue is in use!', type='notice')
Beispiel #19
0
 def test_function():
     get_wanted_queue_lock()
     assert autosubliminal.WANTEDQUEUELOCK
     raise Exception('unexpected')
Beispiel #20
0
def search_subtitle(wanted_item_index, lang):
    log.info('Searching for an individual subtitle')
    subs = []

    # Get wanted queue lock
    if not 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, is_manual=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, is_manual=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
    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