Beispiel #1
0
    def createFromSearch(self, search_results, media, quality_type):

        available_status = fireEvent('status.get', ['available'], single=True)

        try:
            db = get_session()

            found_releases = []

            for rel in search_results:

                rel_identifier = md5(rel['url'])
                found_releases.append(rel_identifier)

                rls = db.query(Relea).filter_by(
                    identifier=rel_identifier).first()
                if not rls:
                    rls = Relea(
                        identifier=rel_identifier,
                        movie_id=media.get('id'),
                        #media_id = media.get('id'),
                        quality_id=quality_type.get('quality_id'),
                        status_id=available_status.get('id'))
                    db.add(rls)
                else:
                    [db.delete(old_info) for old_info in rls.info]
                    rls.last_edit = int(time.time())

                db.commit()

                for info in rel:
                    try:
                        if not isinstance(rel[info],
                                          (str, unicode, int, long, float)):
                            continue

                        rls_info = ReleaseInfo(identifier=info,
                                               value=toUnicode(rel[info]))
                        rls.info.append(rls_info)
                    except InterfaceError:
                        log.debug('Couldn\'t add %s to ReleaseInfo: %s',
                                  (info, traceback.format_exc()))

                db.commit()

                rel['status_id'] = rls.status_id

            return found_releases
        except:
            log.error('Failed: %s', traceback.format_exc())
            db.rollback()
        finally:
            db.close()

        return []
Beispiel #2
0
    def single(self, movie):

        done_status = fireEvent('status.get', 'done', single=True)

        if not movie['profile'] or movie['status_id'] == done_status.get('id'):
            log.debug(
                'Movie doesn\'t have a profile or already done, assuming in manage tab.'
            )
            return

        db = get_session()

        pre_releases = fireEvent('quality.pre_releases', single=True)
        release_dates = fireEvent('library.update_release_date',
                                  identifier=movie['library']['identifier'],
                                  merge=True)
        available_status = fireEvent('status.get', 'available', single=True)
        ignored_status = fireEvent('status.get', 'ignored', single=True)

        default_title = getTitle(movie['library'])
        if not default_title:
            log.error(
                'No proper info found for movie, removing it from library to cause it from having more issues.'
            )
            fireEvent('movie.delete', movie['id'], single=True)
            return

        fireEvent('notify.frontend',
                  type='searcher.started.%s' % movie['id'],
                  data=True,
                  message='Searching for "%s"' % default_title)

        ret = False
        for quality_type in movie['profile']['types']:
            if not self.couldBeReleased(quality_type['quality']['identifier'],
                                        release_dates, pre_releases):
                log.info(
                    'Too early to search for %s, %s',
                    (quality_type['quality']['identifier'], default_title))
                continue

            has_better_quality = 0

            # See if better quality is available
            for release in movie['releases']:
                if release['quality']['order'] <= quality_type['quality'][
                        'order'] and release['status_id'] not in [
                            available_status.get('id'),
                            ignored_status.get('id')
                        ]:
                    has_better_quality += 1

            # Don't search for quality lower then already available.
            if has_better_quality is 0:

                log.info('Search for %s in %s',
                         (default_title, quality_type['quality']['label']))
                quality = fireEvent(
                    'quality.single',
                    identifier=quality_type['quality']['identifier'],
                    single=True)

                results = fireEvent('yarr.search', movie, quality, merge=True)

                sorted_results = sorted(results,
                                        key=lambda k: k['score'],
                                        reverse=True)
                if len(sorted_results) == 0:
                    log.debug(
                        'Nothing found for %s in %s',
                        (default_title, quality_type['quality']['label']))

                download_preference = self.conf('preferred_method')
                if download_preference != 'both':
                    sorted_results = sorted(
                        sorted_results,
                        key=lambda k: k['type'],
                        reverse=(download_preference == 'torrent'))

                # Check if movie isn't deleted while searching
                if not db.query(Movie).filter_by(id=movie.get('id')).first():
                    break

                # Add them to this movie releases list
                for nzb in sorted_results:

                    rls = db.query(Release).filter_by(
                        identifier=md5(nzb['url'])).first()
                    if not rls:
                        rls = Release(
                            identifier=md5(nzb['url']),
                            movie_id=movie.get('id'),
                            quality_id=quality_type.get('quality_id'),
                            status_id=available_status.get('id'))
                        db.add(rls)
                        db.commit()
                    else:
                        [db.delete(info) for info in rls.info]
                        db.commit()

                    for info in nzb:
                        try:
                            if not isinstance(
                                    nzb[info],
                                (str, unicode, int, long, float)):
                                continue

                            rls_info = ReleaseInfo(identifier=info,
                                                   value=toUnicode(nzb[info]))
                            rls.info.append(rls_info)
                            db.commit()
                        except InterfaceError:
                            log.debug('Couldn\'t add %s to ReleaseInfo: %s',
                                      (info, traceback.format_exc()))

                    nzb['status_id'] = rls.status_id

                for nzb in sorted_results:
                    if nzb['status_id'] == ignored_status.get('id'):
                        log.info('Ignored: %s', nzb['name'])
                        continue

                    if nzb['score'] <= 0:
                        log.info('Ignored, score to low: %s', nzb['name'])
                        continue

                    downloaded = self.download(data=nzb, movie=movie)
                    if downloaded is True:
                        ret = True
                        break
                    elif downloaded != 'try_next':
                        break
            else:
                log.info(
                    'Better quality (%s) already available or snatched for %s',
                    (quality_type['quality']['label'], default_title))
                fireEvent('movie.restatus', movie['id'])
                break

            # Break if CP wants to shut down
            if self.shuttingDown() or ret:
                break

        fireEvent('notify.frontend',
                  type='searcher.ended.%s' % movie['id'],
                  data=True)

        #db.close()
        return ret
    def download(self, data, media, manual=False):

        if not data.get('protocol'):
            data['protocol'] = data['type']
            data['type'] = 'movie'

        # Test to see if any downloaders are enabled for this type
        downloader_enabled = fireEvent('download.enabled',
                                       manual,
                                       data,
                                       single=True)

        if downloader_enabled:
            snatched_status, done_status, active_status = fireEvent(
                'status.get', ['snatched', 'done', 'active'], single=True)

            # Download release to temp
            filedata = None
            if data.get('download') and (ismethod(data.get('download'))
                                         or isfunction(data.get('download'))):
                filedata = data.get('download')(url=data.get('url'),
                                                nzb_id=data.get('id'))
                if filedata == 'try_next':
                    return filedata

            download_result = fireEvent('download',
                                        data=data,
                                        movie=media,
                                        manual=manual,
                                        filedata=filedata,
                                        single=True)
            log.debug('Downloader result: %s', download_result)

            if download_result:
                try:
                    # Mark release as snatched
                    db = get_session()
                    rls = db.query(Relea).filter_by(
                        identifier=md5(data['url'])).first()
                    if rls:
                        renamer_enabled = Env.setting('enabled', 'renamer')

                        # Save download-id info if returned
                        if isinstance(download_result, dict):
                            for key in download_result:
                                rls_info = ReleaseInfo(
                                    identifier='download_%s' % key,
                                    value=toUnicode(download_result.get(key)))
                                rls.info.append(rls_info)
                        db.commit()

                        log_movie = '%s (%s) in %s' % (getTitle(
                            media['library']), media['library']['year'],
                                                       rls.quality.label)
                        snatch_message = 'Snatched "%s": %s' % (
                            data.get('name'), log_movie)
                        log.info(snatch_message)
                        fireEvent('%s.snatched' % data['type'],
                                  message=snatch_message,
                                  data=rls.to_dict())

                        # If renamer isn't used, mark media done
                        if not renamer_enabled:
                            try:
                                if media['status_id'] == active_status.get(
                                        'id'):
                                    for profile_type in media['profile'][
                                            'types']:
                                        if profile_type[
                                                'quality_id'] == rls.quality.id and profile_type[
                                                    'finish']:
                                            log.info(
                                                'Renamer disabled, marking media as finished: %s',
                                                log_movie)

                                            # Mark release done
                                            self.updateStatus(
                                                rls.id, status=done_status)

                                            # Mark media done
                                            mdia = db.query(Media).filter_by(
                                                id=media['id']).first()
                                            mdia.status_id = done_status.get(
                                                'id')
                                            mdia.last_edit = int(time.time())
                                            db.commit()
                            except:
                                log.error(
                                    'Failed marking media finished, renamer disabled: %s',
                                    traceback.format_exc())
                        else:
                            self.updateStatus(rls.id, status=snatched_status)

                except:
                    log.error('Failed marking media finished: %s',
                              traceback.format_exc())

                return True

        log.info(
            'Tried to download, but none of the "%s" downloaders are enabled or gave an error',
            (data.get('protocol')))

        return False
Beispiel #4
0
    def single(self, movie):

        available_status = fireEvent('status.get', 'available', single=True)

        for type in movie['profile']['types']:

            has_better_quality = 0
            default_title = movie['library']['titles'][0]['title']

            # See if beter quality is available
            for release in movie['releases']:
                if release['quality']['order'] <= type['quality'][
                        'order'] and release[
                            'status_id'] is not available_status.get('id'):
                    has_better_quality += 1

            # Don't search for quality lower then already available.
            if has_better_quality is 0:

                log.info('Search for %s in %s' %
                         (default_title, type['quality']['label']))
                results = fireEvent('provider.yarr.search',
                                    movie,
                                    type['quality'],
                                    merge=True)
                sorted_results = sorted(results,
                                        key=lambda k: k['score'],
                                        reverse=True)

                # Add them to this movie releases list
                for nzb in sorted_results:
                    db = get_session()

                    rls = db.query(Release).filter_by(
                        identifier=md5(nzb['url'])).first()
                    if not rls:
                        rls = Release(identifier=md5(nzb['url']),
                                      movie_id=movie.get('id'),
                                      quality_id=type.get('quality_id'),
                                      status_id=available_status.get('id'))
                        db.add(rls)
                        db.commit()

                        for info in nzb:
                            try:
                                if not isinstance(nzb[info],
                                                  (str, unicode, int, long)):
                                    continue

                                rls_info = ReleaseInfo(identifier=info,
                                                       value=nzb[info])
                                rls.info.append(rls_info)
                                db.commit()
                            except InterfaceError:
                                log.debug(
                                    'Couldn\'t add %s to ReleaseInfo: %s' %
                                    (info, traceback.format_exc()))

                for nzb in sorted_results:
                    return self.download(data=nzb, movie=movie)
            else:
                log.info(
                    'Better quality (%s) already available or snatched for %s'
                    % (type['quality']['label'], default_title))
                break

            # Break if CP wants to shut down
            if self.shuttingDown():
                break

        return False
Beispiel #5
0
    def single(self, movie, search_protocols=None, manual=False):

        # Find out search type
        try:
            if not search_protocols:
                search_protocols = fireEvent('searcher.protocols', single=True)
        except SearchSetupError:
            return

        done_status = fireEvent('status.get', 'done', single=True)

        if not movie['profile'] or (movie['status_id'] == done_status.get('id')
                                    and not manual):
            log.debug(
                'Movie doesn\'t have a profile or already done, assuming in manage tab.'
            )
            return

        db = get_session()

        pre_releases = fireEvent('quality.pre_releases', single=True)
        release_dates = fireEvent('library.update.movie.release_date',
                                  identifier=movie['library']['identifier'],
                                  merge=True)
        available_status, ignored_status, failed_status = fireEvent(
            'status.get', ['available', 'ignored', 'failed'], single=True)

        found_releases = []
        too_early_to_search = []

        default_title = getTitle(movie['library'])
        if not default_title:
            log.error(
                'No proper info found for movie, removing it from library to cause it from having more issues.'
            )
            fireEvent('movie.delete', movie['id'], single=True)
            return

        fireEvent('notify.frontend',
                  type='movie.searcher.started.%s' % movie['id'],
                  data=True,
                  message='Searching for "%s"' % default_title)

        ret = False
        for quality_type in movie['profile']['types']:
            if not self.conf('always_search') and not self.couldBeReleased(
                    quality_type['quality']['identifier'] in pre_releases,
                    release_dates, movie['library']['year']):
                too_early_to_search.append(
                    quality_type['quality']['identifier'])
                continue

            has_better_quality = 0

            # See if better quality is available
            for release in movie['releases']:
                if release['quality']['order'] <= quality_type['quality'][
                        'order'] and release['status_id'] not in [
                            available_status.get('id'),
                            ignored_status.get('id'),
                            failed_status.get('id')
                        ]:
                    has_better_quality += 1

            # Don't search for quality lower then already available.
            if has_better_quality is 0:

                log.info('Search for %s in %s',
                         (default_title, quality_type['quality']['label']))
                quality = fireEvent(
                    'quality.single',
                    identifier=quality_type['quality']['identifier'],
                    single=True)

                results = []
                for search_protocol in search_protocols:
                    protocol_results = fireEvent('provider.search.%s.movie' %
                                                 search_protocol,
                                                 movie,
                                                 quality,
                                                 merge=True)
                    if protocol_results:
                        results += protocol_results

                sorted_results = sorted(results,
                                        key=lambda k: k['score'],
                                        reverse=True)
                if len(sorted_results) == 0:
                    log.debug(
                        'Nothing found for %s in %s',
                        (default_title, quality_type['quality']['label']))

                download_preference = self.conf('preferred_method',
                                                section='searcher')
                if download_preference != 'both':
                    sorted_results = sorted(
                        sorted_results,
                        key=lambda k: k['protocol'][:3],
                        reverse=(download_preference == 'torrent'))

                # Check if movie isn't deleted while searching
                if not db.query(Media).filter_by(id=movie.get('id')).first():
                    break

                # Add them to this movie releases list
                for nzb in sorted_results:

                    nzb_identifier = md5(nzb['url'])
                    found_releases.append(nzb_identifier)

                    rls = db.query(Release).filter_by(
                        identifier=nzb_identifier).first()
                    if not rls:
                        rls = Release(
                            identifier=nzb_identifier,
                            movie_id=movie.get('id'),
                            quality_id=quality_type.get('quality_id'),
                            status_id=available_status.get('id'))
                        db.add(rls)
                    else:
                        [db.delete(old_info) for old_info in rls.info]
                        rls.last_edit = int(time.time())

                    db.commit()

                    for info in nzb:
                        try:
                            if not isinstance(
                                    nzb[info],
                                (str, unicode, int, long, float)):
                                continue

                            rls_info = ReleaseInfo(identifier=info,
                                                   value=toUnicode(nzb[info]))
                            rls.info.append(rls_info)
                        except InterfaceError:
                            log.debug('Couldn\'t add %s to ReleaseInfo: %s',
                                      (info, traceback.format_exc()))

                    db.commit()

                    nzb['status_id'] = rls.status_id

                for nzb in sorted_results:
                    if not quality_type.get(
                            'finish', False) and quality_type.get(
                                'wait_for',
                                0) > 0 and nzb.get('age') <= quality_type.get(
                                    'wait_for', 0):
                        log.info('Ignored, waiting %s days: %s',
                                 (quality_type.get('wait_for'), nzb['name']))
                        continue

                    if nzb['status_id'] in [
                            ignored_status.get('id'),
                            failed_status.get('id')
                    ]:
                        log.info('Ignored: %s', nzb['name'])
                        continue

                    if nzb['score'] <= 0:
                        log.info('Ignored, score to low: %s', nzb['name'])
                        continue

                    downloaded = fireEvent('searcher.download',
                                           data=nzb,
                                           movie=movie,
                                           manual=manual,
                                           single=True)
                    if downloaded is True:
                        ret = True
                        break
                    elif downloaded != 'try_next':
                        break

                # Remove releases that aren't found anymore
                for release in movie.get('releases', []):
                    if release.get('status_id') == available_status.get(
                            'id') and release.get(
                                'identifier') not in found_releases:
                        fireEvent('release.delete',
                                  release.get('id'),
                                  single=True)

            else:
                log.info(
                    'Better quality (%s) already available or snatched for %s',
                    (quality_type['quality']['label'], default_title))
                fireEvent('movie.restatus', movie['id'])
                break

            # Break if CP wants to shut down
            if self.shuttingDown() or ret:
                break

        if len(too_early_to_search) > 0:
            log.info2('Too early to search for %s, %s',
                      (too_early_to_search, default_title))

        fireEvent('notify.frontend',
                  type='movie.searcher.ended.%s' % movie['id'],
                  data=True)

        return ret