コード例 #1
0
def _sync_new_movies(movies):
    ''' Adds new movies from rss feed
    movies (list): dicts of movies

    Checks last sync time and pulls new imdbids from feed.

    Checks if movies are already in library and ignores.

    Executes ajax.add_wanted_movie() for each new imdbid

    Does not return
    '''

    existing_movies = [i['imdbid'] for i in core.sql.get_user_movies()]

    movies_to_add = [i for i in movies if i['imdb_id'] not in existing_movies]

    # do quick-add procedure
    for movie in movies_to_add:
        imdbid = movie['imdb_id']
        movie = TheMovieDatabase._search_imdbid(imdbid)
        if not movie:
            logging.warning('{} not found on TMDB. Cannot add.'.format(imdbid))
            continue
        else:
            movie = movie[0]
        logging.info('Adding movie {} {} from PopularMovies list.'.format(
            movie['title'], movie['imdbid']))
        movie['quality'] = 'Default'
        movie['origin'] = 'PopularMovies'
        added = Manage.add_movie(movie)

        if added['response'] and core.CONFIG['Search'][
                'searchafteradd'] and movie['year'] != 'N/A':
            searcher.search(movie)
コード例 #2
0
ファイル: trakt.py プロジェクト: scambra/Watcher3
def sync():
    ''' Syncs all enabled Trakt lists and rss lists

    Gets list of movies from each enabled Trakt lists

    Adds missing movies to library as Waiting/Default

    Returns bool for success/failure
    '''

    logging.info('Syncing Trakt lists.')

    success = True

    min_score = core.CONFIG['Search']['Watchlists']['traktscore']
    length = core.CONFIG['Search']['Watchlists']['traktlength']
    movies = []

    if core.CONFIG['Search']['Watchlists']['traktrss']:
        sync_rss()

    for k, v in core.CONFIG['Search']['Watchlists']['Traktlists'].items():
        if v is False:
            continue
        movies += [
            i for i in get_list(k, min_score=min_score, length=length)
            if i not in movies
        ]

    library = [i['imdbid'] for i in core.sql.get_user_movies()]

    movies = [
        i for i in movies
        if ((i['ids']['imdb'] not in library) and (i['ids']['imdb'] != 'N/A'))
    ]

    logging.info('Found {} new movies from Trakt lists.'.format(len(movies)))

    for i in movies:
        imdbid = i['ids']['imdb']
        logging.info('Adding movie {} {} from Trakt'.format(
            i['title'], imdbid))

        added = Manage.add_movie({
            'id': i['ids']['tmdb'],
            'imdbid': i['ids']['imdb'],
            'title': i['title'],
            'origin': 'Trakt'
        })
        try:
            if added['response'] and core.CONFIG['Search'][
                    'searchafteradd'] and i['year'] != 'N/A':
                searcher.search(imdbid, i['title'], i['year'],
                                core.config.default_profile())
        except Exception as e:
            logging.error('Movie {} did not get added.'.format(i['title']),
                          exc_info=False)
    return success
コード例 #3
0
    def addmovie(self, params):
        ''' Add movie with default quality settings
        params (dict): params passed in request url

        params must contain either 'imdbid' or 'tmdbid' key and value

        Returns dict {'status': 'success', 'message': 'X added to wanted list.'}
        '''

        if not (params.get('imdbid') or params.get('tmdbid')):
            return {'response': False, 'error': 'no movie id supplied'}
        elif (params.get('imdbid') and params.get('tmdbid')):
            return {'response': False, 'error': 'multiple movie ids supplied'}

        origin = cherrypy.request.headers.get('User-Agent', 'API')
        origin = 'API' if origin.startswith('Mozilla/') else origin

        quality = params.get('quality') or core.config.default_profile()
        category = params.get('category', 'Default')

        if params.get('imdbid'):
            imdbid = params['imdbid']
            logging.info('API request add movie imdb {}'.format(imdbid))
            movie = TheMovieDatabase._search_imdbid(imdbid)
            if not movie:
                return {
                    'response': False,
                    'error': 'Cannot find {} on TMDB'.format(imdbid)
                }
            else:
                movie = movie[0]
                movie['imdbid'] = imdbid
        elif params.get('tmdbid'):
            tmdbid = params['tmdbid']
            logging.info('API request add movie tmdb {}'.format(tmdbid))
            movie = TheMovieDatabase._search_tmdbid(tmdbid)

            if not movie:
                return {
                    'response': False,
                    'error': 'Cannot find {} on TMDB'.format(tmdbid)
                }
            else:
                movie = movie[0]

        movie['quality'] = quality
        movie['category'] = category
        movie['status'] = 'Waiting'
        movie['origin'] = origin

        response = Manage.add_movie(movie, full_metadata=True)
        if response['response'] and core.CONFIG['Search'][
                'searchafteradd'] and movie['year'] != 'N/A':
            threading.Thread(target=searcher._t_search_grab,
                             args=(movie, )).start()

        return response
コード例 #4
0
ファイル: postprocessing.py プロジェクト: devqore/Watcher3
    def complete(self, data):
        ''' Post-processes a complete, successful download
        data (dict): all gathered file information and metadata

        data must include the following keys:
            path (str): path to downloaded item. Can be file or directory
            guid (str): nzb guid or torrent hash
            downloadid (str): download id from download client

        All params can be empty strings if unknown

        In SEARCHRESULTS marks guid as Finished
        In MARKEDRESULTS:
            Creates or updates entry for guid and optional guid with status=bad
        In MOVIES updates finished_score and finished_date
        Updates MOVIES status

        Checks to see if we found a movie file. If not, ends here.

        If Renamer is enabled, renames movie file according to core.CONFIG
        If Mover is enabled, moves file to location in core.CONFIG, then...
            If Clean Up enabled, deletes path after Mover finishes.
            Clean Up will not execute without Mover success.

        Returns dict of post-processing results
        '''
        config = core.CONFIG['Postprocessing']

        # dict we will json.dump and send back to downloader
        result = {}
        result['status'] = 'incomplete'
        result['data'] = data
        result['data']['finished_date'] = str(datetime.date.today())
        result['tasks'] = {}

        # mark guid in both results tables
        logging.info('Marking guid as Finished.')
        data['guid'] = data['guid'].lower()
        guid_result = {}
        if data['guid'] and data.get('imdbid'):
            if Manage.searchresults(data['guid'], 'Finished', movie_info=data):
                guid_result['update_SEARCHRESULTS'] = True
            else:
                guid_result['update_SEARCHRESULTS'] = False

            if Manage.markedresults(data['guid'],
                                    'Finished',
                                    imdbid=data['imdbid']):
                guid_result['update_MARKEDRESULTS'] = True
            else:
                guid_result['update_MARKEDRESULTS'] = False

            # create result entry for guid
            result['tasks'][data['guid']] = guid_result

        # if we have a guid2, do it all again
        if data.get('guid2') and data.get('imdbid'):
            logging.info('Marking guid2 as Finished.')
            guid2_result = {}
            if Manage.searchresults(data['guid2'], 'Finished',
                                    movie_info=data):
                guid2_result['update_SEARCHRESULTS'] = True
            else:
                guid2_result['update_SEARCHRESULTS'] = False

            if Manage.markedresults(data['guid2'],
                                    'Finished',
                                    imdbid=data['imdbid']):
                guid2_result['update_MARKEDRESULTS'] = True
            else:
                guid2_result['update_MARKEDRESULTS'] = False

            # create result entry for guid2
            result['tasks'][data['guid2']] = guid2_result

        # set movie status and add finished date/score
        if data.get('imdbid'):
            if core.sql.row_exists('MOVIES', imdbid=data['imdbid']):
                data['category'] = core.sql.get_movie_details(
                    'imdbid', data['imdbid'])['category']
            else:
                logging.info('{} not found in library, adding now.'.format(
                    data.get('title')))
                data['status'] = 'Disabled'
                Manage.add_movie(data)

            logging.info('Setting MOVIE status.')
            r = Manage.movie_status(data['imdbid'])
            db_update = {
                'finished_date': result['data']['finished_date'],
                'finished_score': result['data'].get('finished_score')
            }
            core.sql.update_multiple_values('MOVIES', db_update, 'imdbid',
                                            data['imdbid'])

        else:
            logging.info(
                'Imdbid not supplied or found, unable to update Movie status.')
            r = ''
        result['tasks']['update_movie_status'] = r

        data.update(Metadata.convert_to_db(data))

        # mover. sets ['finished_file']
        if config['moverenabled']:
            result['tasks']['mover'] = {'enabled': True}
            response = self.mover(data)
            if not response:
                result['tasks']['mover']['response'] = False
            else:
                data['finished_file'] = response
                result['tasks']['mover']['response'] = True
        else:
            logging.info('Mover disabled.')
            data['finished_file'] = data.get('original_file')
            result['tasks']['mover'] = {'enabled': False}

        # renamer
        if config['renamerenabled']:
            result['tasks']['renamer'] = {'enabled': True}
            new_file_name = self.renamer(data)
            if new_file_name == '':
                result['tasks']['renamer']['response'] = False
            else:
                path = os.path.split(data['finished_file'])[0]
                data['finished_file'] = os.path.join(path, new_file_name)
                result['tasks']['renamer']['response'] = True
        else:
            logging.info('Renamer disabled.')
            result['tasks']['renamer'] = {'enabled': False}

        if data.get('imdbid') and data['imdbid'] is not 'N/A':
            core.sql.update('MOVIES', 'finished_file',
                            result['data'].get('finished_file'), 'imdbid',
                            data['imdbid'])

        # Delete leftover dir. Skip if file links are enabled or if mover disabled/failed
        if config['cleanupenabled']:
            result['tasks']['cleanup'] = {'enabled': True}

            if config['movermethod'] in ('copy', 'hardlink', 'symboliclink'):
                logging.info(
                    'File copy or linking enabled -- skipping Cleanup.')
                result['tasks']['cleanup']['response'] = None
                return result

            elif os.path.isfile(data['path']):
                logging.info(
                    'Download is file, not directory -- skipping Cleanup.')
                result['tasks']['cleanup']['response'] = None
                return result

            # fail if mover disabled or failed
            if config['moverenabled'] is False or result['tasks']['mover'][
                    'response'] is False:
                logging.info(
                    'Mover either disabled or failed -- skipping Cleanup.')
                result['tasks']['cleanup']['response'] = None
            else:
                if self.cleanup(data['path']):
                    r = True
                else:
                    r = False
                result['tasks']['cleanup']['response'] = r
        else:
            result['tasks']['cleanup'] = {'enabled': False}

        # all done!
        result['status'] = 'finished'
        return result
コード例 #5
0
def sync_rss():
    ''' Gets list of new movies in user's rss feed(s)

    Returns list of movie dicts
    '''

    try:
        record = json.loads(core.sql.system('trakt_sync_record'))
    except Exception as e:
        record = {}

    for url in core.CONFIG['Search']['Watchlists']['traktrss'].split(','):
        list_id = url.split('.atom')[0].split('/')[-1]

        last_sync = record.get(list_id) or 'Sat, 01 Jan 2000 00:00:00'
        last_sync = datetime.datetime.strptime(last_sync, date_format)

        logging.info('Syncing Trakt RSS watchlist {}. Last sync: {}'.format(list_id, last_sync))
        try:
            feed = Url.open(url).text
            feed = re.sub(r'xmlns=".*?"', r'', feed)
            root = ET.fromstring(feed)
        except Exception as e:
            logging.error('Trakt rss request:\n{}'.format(feed), exc_info=True)
            continue

        d = root.find('updated').text[:19]

        do = datetime.datetime.strptime(d, trakt_date_format)
        record[list_id] = datetime.datetime.strftime(do, date_format)

        for entry in root.iter('entry'):
            try:
                pub = datetime.datetime.strptime(entry.find('published').text[:19], trakt_date_format)
                if last_sync >= pub:
                    break
                else:
                    t = entry.find('title').text

                    title = ' ('.join(t.split(' (')[:-1])

                    year = ''
                    for i in t.split(' (')[-1]:
                        if i.isdigit():
                            year += i
                    year = int(year)

                    logging.info('Searching TheMovieDatabase for {} {}'.format(title, year))
                    movie = Manage.tmdb._search_title('{} {}'.format(title, year))[0]
                    if movie:
                        movie['origin'] = 'Trakt'
                        logging.info('Found new watchlist movie {} {}'.format(title, year))

                        r = Manage.add_movie(movie)

                        if r['response'] and core.CONFIG['Search']['searchafteradd'] and movie['year'] != 'N/A':
                            searcher.search(movie)
                    else:
                        logging.warning('Unable to find {} {} on TheMovieDatabase'.format(title, year))

            except Exception as e:
                logging.error('Unable to parse Trakt RSS list entry.', exc_info=True)

    logging.info('Storing last synced date.')
    if core.sql.row_exists('SYSTEM', name='trakt_sync_record'):
        core.sql.update('SYSTEM', 'data', json.dumps(record), 'name', 'trakt_sync_record')
    else:
        core.sql.write('SYSTEM', {'data': json.dumps(record), 'name': 'trakt_sync_record'})

    logging.info('Trakt RSS sync complete.')
コード例 #6
0
ファイル: imdb.py プロジェクト: sinopsysHK/Watcher3
def sync():
    ''' Syncs CSV lists from IMDB

    Does not return
    '''

    movies_to_add = []
    library = [i[2] for i in core.sql.quick_titles()]

    try:
        record = json.loads(core.sql.system('imdb_sync_record'))
    except Exception as e:
        record = {}

    for url in core.CONFIG['Search']['Watchlists']['imdbcsv']:
        if url[-6:] not in ('export', 'export/'):
            logging.warning('{} does not look like a valid imdb list'.format(url))
            continue

        list_id = 'ls' + ''.join(filter(str.isdigit, url))
        logging.info('Syncing rss IMDB watchlist {}'.format(list_id))

        last_sync = datetime.strptime((record.get(list_id) or '2000-01-01'), date_format)

        try:
            csv_text = Url.open(url).text
            watchlist = [dict(i) for i in csv.DictReader(csv_text.splitlines())][::-1]

            record[list_id] = watchlist[0]['Created']

            for movie in watchlist:
                pub_date = datetime.strptime(movie['Created'], date_format)

                if last_sync > pub_date:
                    break

                imdbid = movie['Const']
                if imdbid not in library and imdbid not in movies_to_add:
                    logging.info('Found new watchlist movie {}'.format(movie['Title']))
                    movies_to_add.append(imdbid)

        except Exception as e:
            logging.warning('Unable to sync list {}'.format(list_id))

    m = []
    for imdbid in movies_to_add:
        movie = TheMovieDatabase._search_imdbid(imdbid)
        if not movie:
            logging.warning('{} not found on TheMovieDB. Cannot add.'.format(imdbid))
            continue
        else:
            movie = movie[0]
        logging.info('Adding movie {} {} from IMDB watchlist.'.format(movie['title'], movie['imdbid']))
        movie['year'] = movie['release_date'][:4] if movie.get('release_date') else 'N/A'
        movie['origin'] = 'IMDB'

        added = Manage.add_movie(movie)
        if added['response']:
            m.append((imdbid, movie['title'], movie['year']))

    if core.CONFIG['Search']['searchafteradd']:
        for i in m:
            if i[2] != 'N/A':
                searcher.search(i[0], i[1], i[2], core.config.default_profile())

    logging.info('Storing last synced date.')
    if core.sql.row_exists('SYSTEM', name='imdb_sync_record'):
        core.sql.update('SYSTEM', 'data', json.dumps(record), 'name', 'imdb_sync_record')
    else:
        core.sql.write('SYSTEM', {'data': json.dumps(record), 'name': 'imdb_sync_record'})
    logging.info('IMDB sync complete.')