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()
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))