Example #1
0
def moderate_playlists(logger, api_client, username, playlist_config):
    playlist_cleaner = PlaylistCleaner(logger, api_client, username,
                                       playlist_config)
    integrity_manager = IntegrityManager(logger, api_client, playlist_config)
    sp_helper = SpotifyHelper(logger)

    def protect_playlists():
        # runs one iteration of playlist moderation
        if playlist_config['PROTECT_ALL']:
            protected_playlists = sp_helper.get_all_collab_playlists(
                username, api=api_client)
        else:
            protected_playlists = []
            for playlist in playlist_config['PROTECTED_PLAYLISTS']:
                if len(playlist.keys()) == 1:
                    for key, val in playlist.items():
                        protected_playlists.append(val)

        for playlist in protected_playlists:
            print(
                '')  # newlines between playlists improves readibility of logs
            playlist_cleaner.run(playlist)
            integrity_manager.run(playlist)

    if '--loop' in sys.argv or '-l' in sys.argv:
        # For termination of loop mode, the idea is: delays between loop iterations are implemented
        # by a timeboxed attempt to  get user input (from stdin) in order to allow the user to
        # terminate the program loop without needing to send a kill signal
        while True:
            protect_playlists()
            logger.info('Completed iteration')
            if user_wants_to_exit(playlist_config['DELAY_BETWEEN_SCANS']):
                break
    else:
        protect_playlists()
    def __init__(self, logger, api, config):
        self.logger = logger.getChild('IntegrityManager')
        self.api = api
        self.config = config
        self.spotify_helper = SpotifyHelper(self.logger, api=self.api)

        # to avoid uncertainty of whether a forward slash needs to be appended to the backup path
        while self.config['BACKUP_PATH'][-1] == '/':
            self.config['BACKUP_PATH'] = self.config['BACKUP_PATH'][:-1]
Example #3
0
def main():

    if '-h' in sys.argv or '--help' in sys.argv:
        print_help_information()
        exit_with_code(0)
    elif '--rdc' in sys.argv:
        exit_with_code(restore_default_config_file())

    try:
        logger = default_logger(
        )  # used for error logging before custom logger can be configured
        (playlist_config, log_config,
         account_config) = load_configurations(path=get_config_filepath())
        config_validator = ConfigValidator(playlist_config, log_config,
                                           account_config)
        if not config_validator.is_valid():
            raise Exception(
                'Invalid configuration file - check \'data/config.yaml\'')

        logger = setup_logger(
            log_config)  # custom logger based on user's config
        logger.info('Starting new session of SpotifyAutoModerator')

        api_client = SpotifyHelper(logger).configure_api(
            account_config['CLIENT_ID'], account_config['CLIENT_SECRET'],
            account_config['REDIRECT_URI'])
        if not isinstance(api_client, spotipy.client.Spotify):
            raise Exception('Failed to authenticate with Spotify')
        elif not config_validator.all_protected_playlists_exist(api_client):
            raise Exception(
                'Could not find all protected playlists in Spotify')

        moderate_playlists(logger, api_client, account_config['USERNAME'],
                           playlist_config)

    except OSError as err:
        logger.error('Error: \'%s\'', err)
        if 'Address already in use' in str(err):
            logger.error('Redirect URI \'%s\' is already in use',
                         account_config['REDIRECT_URI'])
            logger.error(
                'Try to use a different (free) port number and add this address to the'
                + 'application in the Spotify Developer Dashboard')
        exit_with_code(1)

    except Exception as err:
        logger.error('Error: \'%s\'', err)
        if '401' in str(err):
            logger.error('Confirm your account/client details are correct')
        exit_with_code(1)

    exit_with_code(0)
    def setUp(self):
        self.test_logger = logging.getLogger('TestSpotifyHelper')
        log_handler = logging.StreamHandler()
        log_handler.setLevel('CRITICAL')
        self.test_logger.addHandler(log_handler)

        self.helper = SpotifyHelper(self.test_logger)

        self.generate_spotify_id = (
            lambda: ''.join(random.choice(string.ascii_letters + string.digits) for i in range(0, 22)))
        self.generate_playlist_uri = (
            lambda gen_id=self.generate_spotify_id: 'spotify:playlist:' + gen_id())
        self.generate_track_uri = (
            lambda gen_id=self.generate_spotify_id: 'spotify:track:' + gen_id())

        os.environ = {} # reset environment
Example #5
0
    def all_protected_playlists_exist(self, api_client):
        if ('PROTECTED_PLAYLISTS' not in self.playlist.keys()
                or not isinstance(self.playlist['PROTECTED_PLAYLISTS'], list)):
            self.logger.error(
                '`PLAYLIST_CONFIG.PROTECTED_PLAYLISTS is invalid - it must be a list`'
            )
            return False

        helper = SpotifyHelper(self.logger, api=api_client)
        collab_playlists = helper.get_all_collab_playlists(
            self.account['USERNAME'])
        collab_pl_uris = [pl['uri'] for pl in collab_playlists]

        for playlist in self.playlist['PROTECTED_PLAYLISTS']:
            if len(playlist.keys()) != 1:
                return False

            for key, val in playlist.items():
                if val['uri'] not in collab_pl_uris:
                    return False
        return True
Example #6
0
 def __init__(self, logger, api, playlist_creator_id, config):
     self.logger = logger.getChild('PlaylistCleaner')
     self.api = api
     self.playlist_creator_id = playlist_creator_id
     self.config = config
     self.spotify_helper = SpotifyHelper(self.logger)