Exemple #1
0
async def update_spotify_playlist(tracks: Iterable,
                                  playlist_uri: str,
                                  sp: Spotter,
                                  insert_top: bool = False):
    """Add the ids from track iterable to the playlist, insert_top bool does it
    on top of all the items, for fridays"""

    index = 0
    for album_ids in grouper(100, tracks):
        album_ids = clean(album_ids)
        album_ids = [a["id"] for a in album_ids]
        args = (sp.userdata["id"], playlist_uri, album_ids)

        if insert_top:
            args = args + (index, )  # type: ignore

        try:
            await sp.client.user_playlist_add_tracks(*args)
            index += len(album_ids) - 1
            await sleep(0.2)
        except Exception as exc:
            _LOGGER.exception(
                f"{sp.userdata['id']} fail on POST playlist items {album_ids}")
            push_sentry_error(exc, sp.userdata["id"],
                              sp.userdata["display_name"])
Exemple #2
0
async def send_message(fb_id: str, fb_alert: FBAlert, data: str):
    """send fb user text message"""
    fb_token = {"access_token": fb_alert.key}

    # max message size is 2000
    for msg_chunk in grouper(2000, data):
        clean_chunk = [a for a in msg_chunk if a is not None]
        contents = {
            "recipient": {
                "id": fb_id
            },
            "message": {
                "text": "".join(clean_chunk)
            },
            "tag": "ACCOUNT_UPDATE",
        }
        async with aiohttp.ClientSession() as session:
            async with session.post(fb_alert.url,
                                    json=contents,
                                    params=fb_token) as res:
                if res.status != 200:
                    try:
                        res.raise_for_status()
                    except aiohttp.ClientError as exc:
                        _LOGGER.exception(f"{res} {res.content}")
                        push_sentry_error(exc, fb_id)
Exemple #3
0
async def _update_user_artists(
    credentials: SpotifyKeys, user: User, force_update: bool, dry_run: bool
):
    """task to update user followed artists and artist albums"""
    user_config = WeeklyPlaylistUpdateConfig(**user.config[_CONFIG_ID])
    if not user_config.enabled:
        return
    try:
        async with spotify_client(credentials, user) as sp:
            new_follows, lost_follows = await sync_user_followed_artists(
                user, sp, dry_run
            )

            followed_artists = await user.artists.filter()

            _LOGGER.info(
                f"{user} : follows +{len(new_follows)} -{len(lost_follows)}"
                f"; now updating artists ({len(followed_artists)})"
            )
            albums_nr, updated_nr = await get_new_releases(
                sp, followed_artists, force_update
            )
            if updated_nr:
                _LOGGER.info(f"fetched {albums_nr} albums for {updated_nr} artists")
    except Exception as exc:
        _LOGGER.exception(f"{user} failed to update artists")
        push_sentry_error(exc, sp.userdata["id"], sp.userdata["display_name"])
Exemple #4
0
async def _handle_update_user_playlist(credentials: SpotifyKeys, user: User,
                                       dry_run: bool, fb_alert: FBAlert):
    user_config = WeeklyPlaylistUpdateConfig(**user.config[_CONFIG_ID])
    if not user_config.enabled:
        return
    try:
        async with spotify_client(credentials, user) as sp:
            stats = await update_user_playlist(user, sp, dry_run)
            if fb_alert.notify and stats.has_new_tracks():
                await send_message(user.fb_id, fb_alert, stats.describe())
    except SpotifyException as exc:
        _LOGGER.warning(f"{user} failed to update playlist")
        push_sentry_error(exc, user.username, user.display_name)
Exemple #5
0
async def update_artist_albums(
        sp: Spotter,
        artist: Artist,
        dry_run: bool = False) -> Tuple[Artist, List[Album]]:
    """update artist albums by adding them to the db"""
    albums = await fetch_albums(sp, artist)
    processed_albums = []

    for album in albums:
        if album["album_type"] == "compilation":
            # these types of albums are just a collection of already knows songs
            # places in a new compilation album; gonna skipe those for a while
            # until more control of the flow
            continue

        if not is_in_artists_list(artist, album):
            # Some releases are not directly related to the artist himself.
            # It happens that if an artist has some feature songs on an album
            # for a different artist, it will be returned to the artist in cause
            # as well, so that this function checks that, and returns only feature
            # songs if it's the case.
            tracks = await get_featuring_songs(sp, artist, album)
            processed_albums.extend(tracks)
        else:
            processed_albums.append(album)

    args_items = [(album, artist) for album in processed_albums]
    task_results = await run_tasks(Config.ALBUMS_TASKS_AMOUNT, args_items,
                                   handle_album_sync)

    try:
        await artist.update_synced_at()
    except Exception as exc:
        _LOGGER.exception(
            f"{sp.userdata['id']} failed to update {artist} synced_at")
        push_sentry_error(exc, sp.userdata["id"], sp.userdata["display_name"])

    new_inserts = [a for created, a in task_results if created]
    return artist, new_inserts
Exemple #6
0
async def fetch_albums(sp: Spotter,
                       artist: Artist,
                       retry: bool = True) -> List[dict]:
    """fetches artist albums from spotify"""
    try:
        data = await sp.client.artist_albums(
            artist.spotify_id, limit=50, album_type="album,single,appears_on")
        albums = await fetch_all_albums(sp, data)
    except SpotifyException as exc:
        _LOGGER.warning(f"failed fetch artist albums for `{artist}`: {exc}")
        return []
    except Exception as exc:
        if not retry:
            _LOGGER.exception(
                f"{sp.userdata['id']} failed to fetch all {artist} albums")
            push_sentry_error(exc, sp.userdata["id"],
                              sp.userdata["display_name"])
            raise
        _LOGGER.warning(
            f"{sp.userdata['id']} attempt another fetch all {artist} albums")
        albums = await fetch_albums(sp, artist, retry=False)

    return albums