Exemplo n.º 1
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
Exemplo n.º 2
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)
Exemplo n.º 3
0
    def search_movie(self, params):
        ''' Search indexers for specific movie
        params(dict): params passed in request url, must include q

        Returns dict ajax-style response
        '''
        if not params.get('q'):
            return {'response': False, 'error': 'no query supplied'}

        results = TheMovieDatabase.search(params['q'])
        if results:
            Manage.add_status_to_search_movies(results)
        else:
            return {
                'response': False,
                'error': 'No Results found for {}'.format(params['q'])
            }

        return {'response': True, 'results': results}
Exemplo n.º 4
0
    def add_movie(movie, full_metadata=False):
        ''' Adds movie to Wanted list.
        movie (dict): movie info to add to database.
        full_metadata (bool): if data is complete and ready for write

        movie MUST inlcude tmdb id as data['id']

        Writes data to MOVIES table.

        If full_metadata is False, searches tmdb for data['id'] and updates data
            full_metadata should only be True when passing movie as data pulled
            directly from a tmdbid search

        If Search on Add enabled,
            searches for movie immediately in separate thread.
            If Auto Grab enabled, will snatch movie if found.

        Returns dict ajax-style response
        '''

        logging.info('Adding {} to library.'.format(movie.get('title')))

        response = {}
        tmdbid = movie['id']

        if not full_metadata:
            logging.debug(
                'More information needed, searching TheMovieDB for {}'.format(
                    tmdbid))
            tmdb_data = TheMovieDatabase._search_tmdbid(tmdbid)
            if not tmdb_data:
                response['error'] = _('Unable to find {} on TMDB.').format(
                    tmdbid)
                return response
            else:
                tmdb_data = tmdb_data[0]
            tmdb_data.pop('status')
            movie.update(tmdb_data)

        if core.sql.row_exists('MOVIES', imdbid=movie['imdbid']):
            logging.info('{} already exists in library.'.format(
                movie['title']))

            response['response'] = False

            response['error'] = _('{} already exists in library.').format(
                movie['title'])
            return response

        if not movie.get('category', None) and movie.get(
                'finished_file', None):
            movie['category'] = Metadata.get_category_from_path(
                (movie['finished_file']))
        movie.setdefault('quality', 'Default')
        movie.setdefault('category', 'Default')
        movie.setdefault('status', 'Waiting')
        movie.setdefault('origin', 'Search')

        poster_path = movie.get('poster_path')

        movie = Metadata.convert_to_db(movie)

        if not core.sql.write('MOVIES', movie):
            response['response'] = False
            response['error'] = _('Could not write to database.')
        else:
            if poster_path:
                poster_url = 'http://image.tmdb.org/t/p/w300/{}'.format(
                    poster_path)
                threading.Thread(target=Poster.save,
                                 args=(movie['imdbid'], poster_url)).start()

            response['response'] = True
            response['message'] = _('{} {} added to library.').format(
                movie['title'], movie['year'])
            plugins.added(movie['title'], movie['year'], movie['imdbid'],
                          movie['quality'])

        return response
Exemplo n.º 5
0
    def update(imdbid, tmdbid=None, force_poster=True):
        ''' Updates metadata from TMDB
        imdbid (str): imdb id #
        tmdbid (str): or int tmdb id #                                  <optional - default None>
        force_poster (bool): whether or not to always redownload poster <optional - default True>

        If tmdbid is None, looks in database for tmdbid using imdbid.
        If that fails, looks on tmdb api for imdbid
        If that fails returns error message

        If force_poster is True, the poster will be re-downloaded.
        If force_poster is False, the poster will only be redownloaded if the local
            database does not have a 'poster' filepath stored. In other words, this
            will only grab missing posters.

        Returns dict ajax-style response
        '''

        logging.info('Updating metadata for {}'.format(imdbid))
        movie = core.sql.get_movie_details('imdbid', imdbid)

        if force_poster:
            get_poster = True
        elif not movie.get('poster'):
            get_poster = True
        elif not os.path.isfile(os.path.join(core.PROG_PATH, movie['poster'])):
            get_poster = True
        else:
            logging.debug('Poster will not be redownloaded.')
            get_poster = False

        if tmdbid is None:
            tmdbid = movie.get('tmdbid')

            if not tmdbid:
                logging.debug(
                    'TMDB id not found in local database, searching TMDB for {}'
                    .format(imdbid))
                tmdb_data = TheMovieDatabase._search_imdbid(imdbid)
                tmdbid = tmdb_data[0].get('id') if tmdb_data else None
            if not tmdbid:
                logging.debug('Unable to find {} on TMDB.'.format(imdbid))
                return {
                    'response': False,
                    'error': 'Unable to find {} on TMDB.'.format(imdbid)
                }

        new_data = TheMovieDatabase._search_tmdbid(tmdbid)

        if not new_data:
            logging.warning('Empty response from TMDB.')
            return
        else:
            new_data = new_data[0]

        new_data.pop('status')

        target_poster = os.path.join(Poster.folder, '{}.jpg'.format(imdbid))

        if new_data.get('poster_path'):
            poster_path = 'http://image.tmdb.org/t/p/w300{}'.format(
                new_data['poster_path'])
            movie['poster'] = '{}.jpg'.format(movie['imdbid'])
        else:
            poster_path = None

        movie.update(new_data)
        movie = Metadata.convert_to_db(movie)

        core.sql.update_multiple_values('MOVIES', movie, 'imdbid', imdbid)

        if poster_path and get_poster:
            if os.path.isfile(target_poster):
                try:
                    os.remove(target_poster)
                except FileNotFoundError:
                    pass
                except Exception as e:
                    logging.warning('Unable to remove existing poster.',
                                    exc_info=True)
                    return {
                        'response': False,
                        'error': 'Unable to remove existing poster.'
                    }

            Poster.save(imdbid, poster_path)

        return {'response': True, 'message': 'Metadata updated.'}
Exemplo n.º 6
0
    def from_file(filepath, imdbid=None):
        ''' Gets video metadata using hachoir.parser
        filepath (str): absolute path to movie file
        imdbid (str): imdb id #             <optional - Default None>

        On failure can return empty dict

        Returns dict
        '''

        logging.info('Gathering metadata for {}.'.format(filepath))

        data = {
            'title': None,
            'year': None,
            'resolution': None,
            'rated': None,
            'imdbid': imdbid,
            'videocodec': None,
            'audiocodec': None,
            'releasegroup': None,
            'source': None,
            'quality': None,
            'category': None,
            'path': filepath,
            'edition': []
        }

        titledata = Metadata.parse_filename(filepath)
        data.update(titledata)

        filedata = Metadata.parse_media(filepath)
        data.update(filedata)

        if data.get('resolution'):
            if data['resolution'].upper() in ('4K', '1080P', '720P'):
                data['resolution'] = '{}-{}'.format(data['source'] or 'BluRay',
                                                    data['resolution'].upper())
            else:
                data['resolution'] = 'DVD-SD'

        if data.get('title') and not data.get('imdbid'):
            title_date = '{} {}'.format(
                data['title'],
                data['year']) if data.get('year') else data['title']
            tmdbdata = TheMovieDatabase.search(title_date, single=True)
            if not tmdbdata:
                logging.warning(
                    'Unable to get data from TheMovieDB for {}'.format(
                        data['title']))
                return data

            tmdbdata = tmdbdata[0]
            tmdbid = tmdbdata.get('id')

            if not tmdbid:
                logging.warning(
                    'Unable to get data from TheMovieDB for {}'.format(
                        data['imdbid']))
                return data

            tmdbdata = tmdbdata = TheMovieDatabase._search_tmdbid(tmdbid)
            if tmdbdata:
                tmdbdata = tmdbdata[0]
            else:
                logging.warning('Unable to get data from TMDB for {}'.format(
                    data['imdbid']))
                return data

            data['year'] = tmdbdata['release_date'][:4]
            data.update(tmdbdata)

        if data.get('3d'):
            data['edition'].append('3D')

        data['edition'] = ' '.join(sorted(data['edition']))

        return data
Exemplo n.º 7
0
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.')