def main():
    log.info('launched')

    with open('config.json') as file:
        global config
        config = json.load(file)

    monitor = mpv.MpvMonitor.create(on_connected, on_event,
                                    on_command_response, on_disconnected)
    try:
        trakt_v2_oauth.get_access_token(
        )  # prompts authentication, if necessary
        while True:
            if monitor.can_open():
                # call monitor.run() as a daemon thread, so that all SIGTERMs are handled here
                # Daemon threads die automatically, when the main process ends
                thread = threading.Thread(target=monitor.run, daemon=True)
                thread.start()
                thread.join()
                # If thread joins, mpv was closed.
                log.info('mpv closed')
            else:
                # mpv not open
                # sleep before next attempt
                time.sleep(config['seconds_between_mpv_running_checks'])
    except KeyboardInterrupt:
        log.info('terminating')
        logging.shutdown()
Exemple #2
0
def delete_all_movies_from_history():
    access_token = trakt_v2_oauth.get_access_token()

    movie_history_request = requests.get(
        'https://api-v2launch.trakt.tv/sync/history/movies',
        headers={
            'Authorization': 'Bearer ' + access_token,
            'trakt-api-version': '2',
            'trakt-api-key': trakt_v2_oauth.client_id
        },
        json={
            'username': '******',
            'limit': 999999
        })

    if movie_history_request.status_code != 200:
        sys.exit(
            'Getting watched movies from trakt failed with http code %d.\n%s' %
            (movie_history_request.status_code, movie_history_request.text))

    trakt_history_ids = list(
        reduce(lambda output, current: output + [current['id']],
               movie_history_request.json(), []))

    print('Are you sure, you want to delete %d movies from your history?' %
          len(trakt_history_ids))
    answer = raw_input('Type "y" to proceed: ')
    if answer != 'y':
        sys.exit('aborted')

    movies_remove_request = requests.post(
        'http://api-v2launch.trakt.tv/sync/history/remove',
        headers={
            'Authorization': 'Bearer ' + access_token,
            'trakt-api-version': '2',
            'trakt-api-key': trakt_v2_oauth.client_id
        },
        json={'ids': trakt_history_ids})

    if movies_remove_request.status_code == 200:
        movies_sync_request_response = movies_remove_request.json()
        print('Successfully removed %s movie%s from trakt history.' %
              (movies_sync_request_response['deleted']['movies'], 's' if
               movies_sync_request_response['deleted']['movies'] != 1 else ''))
    else:
        sys.exit(
            'Deleting movies failed with http code %d.\n%s' %
            (movies_remove_request.status_code, movies_remove_request.text))
def delete_all_movies_from_history():
    access_token = trakt_v2_oauth.get_access_token()

    movie_history_request = requests.get('https://api-v2launch.trakt.tv/sync/history/movies', headers={
        'Authorization': 'Bearer ' + access_token,
        'trakt-api-version': '2',
        'trakt-api-key': trakt_v2_oauth.client_id
    }, json={
        'username': '******',
        'limit': 999999
    })

    if movie_history_request.status_code != 200:
        sys.exit('Getting watched movies from trakt failed with http code %d.\n%s' %
                 (movie_history_request.status_code, movie_history_request.text))

    trakt_history_ids = list(reduce(
        lambda output, current: output + [current['id']],
        movie_history_request.json(), []))

    print('Are you sure, you want to delete %d movies from your history?' % len(trakt_history_ids))
    answer = raw_input('Type "y" to proceed: ')
    if answer != 'y':
        sys.exit('aborted')

    movies_remove_request = requests.post('http://api-v2launch.trakt.tv/sync/history/remove', headers={
        'Authorization': 'Bearer ' + access_token,
        'trakt-api-version': '2',
        'trakt-api-key': trakt_v2_oauth.client_id
    }, json={
        'ids': trakt_history_ids
    })

    if movies_remove_request.status_code == 200:
        movies_sync_request_response = movies_remove_request.json()
        print('Successfully removed %s movie%s from trakt history.' %
              (movies_sync_request_response['deleted']['movies'],
               's' if movies_sync_request_response['deleted']['movies'] != 1 else ''))
    else:
        sys.exit('Deleting movies failed with http code %d.\n%s' %
                 (movies_remove_request.status_code, movies_remove_request.text))
def sync_to_trakt(is_paused, playback_position, working_dir, path, duration,
                  start_time, mpv_closed):
    log.debug('sync_to_trakt(%s, %d, %s, %s, %d, %d, %s)' %
              (is_paused, playback_position, working_dir, path, duration,
               start_time, mpv_closed))
    do_sync = False
    if not is_url(path) and not os.path.isabs(path):
        # If mpv is not started via double click from a file manager, but rather from a terminal,
        # the path to the video file is relative and not absolute. For the monitored_directories thing
        # to work, we need an absolute path. that's why we need the working dir
        path = os.path.join(working_dir, path)

    for monitored_directory in config['monitored_directories']:
        if path.startswith(monitored_directory):
            do_sync = True
            break

    # empty monitored_directories means: always sync
    if len(config['monitored_directories']) == 0:
        do_sync = True

    for excluded_directory in config['excluded_directories']:
        if path.startswith(excluded_directory):
            do_sync = False
            break

    log.debug('do_sync = %s' % (do_sync))
    if do_sync:
        guess = guessit.guessit(path)
        log.debug(guess)

        data = get_cached_trakt_data(guess)

        if data is not None:
            data['progress'] = playback_position
            data['app_version'] = '1.0.3'

            finished = is_finished(playback_position, duration, start_time)

            # closed  finished  paused  trakt action
            # False   False     False   start
            # False   False     True    pause
            # False   True      False   start
            # False   True      True    pause
            # True    False     False   pause
            # True    False     True    pause
            # True    True      False   stop
            # True    True      True    stop

            # is equal to:

            if mpv_closed:
                if finished:
                    # trakt is closing and finished watching
                    # trakt action: stop
                    url = 'https://api.trakt.tv/scrobble/stop'
                else:
                    # closed before finished watching
                    # trakt action: pause
                    url = 'https://api.trakt.tv/scrobble/pause'
            elif is_paused:
                # paused, while still open
                # trakt action: pause
                url = 'https://api.trakt.tv/scrobble/pause'
            else:
                # watching right now
                # trakt action: start
                url = 'https://api.trakt.tv/scrobble/start'

            req = requests.post(url,
                                json=data,
                                headers={
                                    'trakt-api-version':
                                    '2',
                                    'trakt-api-key':
                                    trakt_key_holder.get_id(),
                                    'Authorization':
                                    'Bearer ' +
                                    trakt_v2_oauth.get_access_token()
                                })
            log.info('%s %s %s', url, req.status_code, req.text)
            if 200 <= req.status_code < 300:
                global is_local_state_dirty
                is_local_state_dirty = False
def sync_imdb_to_trakt():
    arguments = docopt.docopt(__doc__, version='1.0.1')

    if arguments['--print-timezones']:
        for timezone in pytz.all_timezones:
            print(timezone)
        sys.exit()

    user_timezone = pytz.timezone(arguments['--timezone'])

    imdb_movies = get_imdb_movies(arguments['--watchlist'])

    untested_movies = list(
        filter(lambda movie: movie['title_type'] not in ['Feature Film', 'Documentary', 'TV Movie'], imdb_movies))

    if len(untested_movies) > 0:
        print('Warning: There are some entries of an untested type in your IMDB watchlist. '
              'These will be synchronized, but the result may be unexpected.')
        print('The entries in question are: %s' % reduce(lambda output, current: '%s%s%s (%s)' %
                                                                                 (output,
                                                                                  ', ' if len(output) > 0 else '',
                                                                                  current['title'],
                                                                                  current['title_type']),
                                                         untested_movies, ''))

    # convert imdb watched_at date to datetime using pytz
    for movie in imdb_movies:
        movie['watched_at'] = user_timezone.localize(convert_imdb_date_string_to_datetime(movie['watched_at']))

    access_token = trakt_v2_oauth.get_access_token(arguments['--oauth-pin'])

    watched_movies_request = requests.get('https://api-v2launch.trakt.tv/sync/watched/movies', headers={
        'Content-Type': 'application/json',
        'Authorization': 'Bearer ' + access_token,
        'trakt-api-version': '2',
        'trakt-api-key': trakt_v2_oauth.client_id
    })

    if watched_movies_request.status_code != 200:
        sys.exit('Getting watched movies from trakt failed with http code %d.\n%s' %
                 (watched_movies_request.status_code, watched_movies_request.text))

    already_watched_imdb_ids = reduce(
        lambda output, current: output + [current['movie']['ids']['imdb']],
        watched_movies_request.json(), [])

    movies_to_sync = list(
        filter(lambda imdb_movie: imdb_movie['imdb_id'] not in already_watched_imdb_ids, imdb_movies))

    skipped_movies = len(imdb_movies) - len(movies_to_sync)
    if skipped_movies > 0:
        print('Not synchronizing %d movie%s, because they are already marked as watched in trakt.' %
              (skipped_movies, 's' if skipped_movies != 1 else ''))

    movies_sync_request = requests.post('https://api-v2launch.trakt.tv/sync/history', headers={
        'Authorization': 'Bearer ' + access_token,
        'trakt-api-version': '2',
        'trakt-api-key': trakt_v2_oauth.client_id
    }, json={
        'movies': list(map(lambda movie: {
            'title': movie['title'],
            'year': movie['year'],
            'watched_at': pytz.utc.normalize(movie['watched_at'].astimezone(pytz.utc)).isoformat(),
            'ids': {
                'imdb': movie['imdb_id']
            }
        }, movies_to_sync))
    })

    if movies_sync_request.status_code == 201:
        movies_sync_request_response = movies_sync_request.json()
        print('Successfully synchronized %s movie%s with trakt.' %
              (movies_sync_request_response['added']['movies'],
               's' if movies_sync_request_response['added']['movies'] != 1 else ''))
        number_of_unrecognized_movies = len(movies_sync_request_response['not_found']['movies'])
        if number_of_unrecognized_movies > 0:
            print('%d unrecognized movie%s: %s' %
                  (number_of_unrecognized_movies, 's' if number_of_unrecognized_movies != 1 else '',
                   reduce(
                       lambda output, current: '%s%s%s (%s)' %
                                               (output, ', ' if len(output) > 0 else '', current['title'],
                                                current['year']),
                       movies_sync_request_response['not_found']['movies'], '')))
    else:
        sys.exit('Synchronizing movies with trakt failed with http code %d.\n%s' %
                 (movies_sync_request.status_code, movies_sync_request.text))