class FollowedArtistsCommand(FollowArtistMixin, Command):
    """
    Command /followedartists
    Shows a list of the followed artists the request's user
    """
    COMMAND = 'followedartists'

    def __init__(self, update: Update, context: CallbackContext):
        super().__init__(update, context)
        self.telegram_api_client = TelegramAPIClient()
        self.spotify_api_client = SpotifyAPIClient()

    def get_response(self):
        followed_artists_response = self.spotify_api_client.get_followed_artists(self.update.message.from_user.id)
        return self._build_message(followed_artists_response), None

    def _build_message(self, followed_artists_response):
        if not followed_artists_response:
            return self.not_following_any_artist_message

        msg = '<strong>Following artists:</strong> \n'
        for followed_artist in followed_artists_response:
            artist = followed_artist.get('artist')
            msg += f'- {emojis.EMOJI_ARTIST} ' \
                   f'<a href="{artist.get("url")}">{artist.get("name")}</a> ' \
                   f'Followed at: {datetime.datetime.fromisoformat(followed_artist.get("followed_at")).strftime(OUTPUT_DATE_FORMAT)}\n'
        return msg
class CheckArtistsNewMusicReleasesCommand(FollowArtistMixin, CreateOrUpdateMixin, Command):
    """
    Command /checkartistsnewmusicreleases
    Shows a list of buttons with followed artists for checking their new album releases when clicking
    """
    COMMAND = 'checkartistsnewmusicreleases'

    def __init__(self, update: Update, context: CallbackContext):
        super().__init__(update, context)
        self.spotify_api_client = SpotifyAPIClient()

    def get_response(self):
        new_music_releases_response = self.spotify_api_client.check_new_music_releases(self.update.message.from_user.id)
        if not new_music_releases_response:
            return self.no_new_music_message, None
        message = self._build_message(new_music_releases_response), None
        return message

    @staticmethod
    def _build_message(new_music_releases_response: []) -> str:
        msg = 'Found new music: \n'
        for new_album in new_music_releases_response:
            new_album_first_artist = new_album.get('artists')[0]
            msg += f'    - <a href="{new_album.get("url")}">{new_album_first_artist.get("name")} - {new_album.get("name")} ({new_album.get("album_type")})</a> ' \
                   f'Released at: {datetime.datetime.fromisoformat(new_album.get("release_date")).strftime(OUTPUT_DATE_FORMAT)} \n'
        return msg

    @property
    def no_new_music_message(self):
        return 'There is no new music of your followed artists'
class SavedLinksCommand(Command):
    """
    Command /savedlinks
    Shows a list of the links that the user saved
    """
    COMMAND = 'savedlinks'

    def __init__(self, update: Update, context: CallbackContext):
        super().__init__(update, context)
        self.spotify_api_client = SpotifyAPIClient()

    def get_response(self):
        saved_links_response = self.spotify_api_client.get_saved_links(self.update.message.from_user.id)
        return self._build_message(saved_links_response), None

    @staticmethod
    def _build_message(saved_links_response: {}):
        if not saved_links_response:
            return 'You have not saved links'

        msg = '<strong>Saved links:</strong> \n'
        for saved_link in saved_links_response:
            link = saved_link.get('link')
            genres = Link.get_genres(link)
            msg += f'- {emojis.get_music_emoji(link.get("link_type"))} <a href="{link.get("url")}">{Link.get_name(link)}</a> ' \
                   f'({", ".join(genres) if genres else ""}). ' \
                   f'Saved at: {datetime.datetime.fromisoformat(saved_link.get("saved_at")).strftime(OUTPUT_DATE_FORMAT)}\n'
        return msg
 def handle(cls, update: Update, context: CallbackContext):
     """Handles the pulsation of the button"""
     query = update.callback_query
     followed_artist_id = cls.get_callback_data(query.data)
     if followed_artist_id:
         SpotifyAPIClient().delete_followed_artist(followed_artist_id)
     context.bot.edit_message_reply_markup(
         chat_id=query.message.chat_id, message_id=query.message.message_id)
class UnfollowArtistsCommand(FollowArtistMixin, Command):
    """
    Command /unfollowartist
    Shows a list of buttons with followed artists and deletes them when clicking
    """
    COMMAND = 'unfollowartists'

    def __init__(self, update: Update, context: CallbackContext):
        super().__init__(update, context)
        self.spotify_api_client = SpotifyAPIClient()

    def get_response(self):
        keyboard = self._build_keyboard()
        if not keyboard:
            return self.not_following_any_artist_message, None
        return 'Choose an artist to unfollow:', keyboard

    def _build_keyboard(self):
        followed_artists = self.spotify_api_client.get_followed_artists(self.update.message.from_user.id)
        if not followed_artists:
            return None
        return UnfollowArtistButton.get_keyboard_markup(followed_artists)
class DeleteSavedLinksCommand(Command):
    """
    Command /deletesavedlinks
    Shows a list of buttons with the saved links and deletes them when clicking
    """
    COMMAND = 'deletesavedlinks'

    def __init__(self, update: Update, context: CallbackContext):
        super().__init__(update, context)
        self.spotify_api_client = SpotifyAPIClient()

    def get_response(self):
        keyboard = self._build_keyboard()
        if not keyboard:
            return 'You have not saved links', None
        return 'Choose a saved link to delete:', keyboard

    def _build_keyboard(self):
        saved_links_response = self.spotify_api_client.get_saved_links(self.update.message.from_user.id)
        if not saved_links_response:
            return None
        return DeleteSavedLinkButton.get_keyboard_markup(saved_links_response)
Exemple #7
0
 def save_track(track_id: str):
     spotify_api_client = SpotifyAPIClient()
     create_track_response = spotify_api_client.create_track(track_id)
     return create_track_response
Exemple #8
0
 def save_album(album_id: str):
     spotify_api_client = SpotifyAPIClient()
     create_album_response = spotify_api_client.create_album(album_id)
     return create_album_response
Exemple #9
0
 def save_artist(artist_id: str):
     spotify_api_client = SpotifyAPIClient()
     create_artist_response = spotify_api_client.create_artist(artist_id)
     return create_artist_response
 def __init__(self, update: Update, context: CallbackContext):
     super().__init__(update, context)
     self.spotify_api_client = SpotifyAPIClient()
class FollowArtistCommand(CreateOrUpdateMixin, Command):
    """
    Command /followartist
    Allows user to follow an artist and be notified when they release an album
    """
    COMMAND = 'followartist'

    def __init__(self, update: Update, context: CallbackContext):
        super().__init__(update, context)
        self.spotify_api_client = SpotifyAPIClient()
        self.telegram_api_client = TelegramAPIClient()

    def get_response(self):
        if not self.args:
            return self.help_message, None
        url = self.args[0]
        try:
            spotify_artist_id = self._extract_artist_id_from_url(url)
        except ValueError:
            log.warning('Error trying to process artist url')
            return self.error_invalid_link_message, None
        user = self.save_user(self.update.message.from_user)
        artist = self.spotify_api_client.get_artist(spotify_artist_id)
        try:
            followed_artist_response = self.spotify_api_client.create_followed_artist(artist.get('id'), user.get('id'))
        except APIClientException as e:
            response = e.args[0].response
            if response.status_code == 400 and "unique" in response.text:
                return self.already_following_this_artist_message, None
            raise e
        return self._build_message(followed_artist_response), None

    def _extract_artist_id_from_url(self, url: str) -> Artist:
        url = self._url_cleaning_and_validations(url)
        return SpotifyUtils.get_entity_id_from_url(url)

    @staticmethod
    def _url_cleaning_and_validations(url: str) -> str:
        if not SpotifyUtils.is_valid_url(url):
            raise ValueError
        if SpotifyUtils.get_link_type_from_url(url) != LinkType.ARTIST.value:
            raise ValueError
        cleaned_url = SpotifyUtils.clean_url(url)
        return cleaned_url

    @property
    def already_following_this_artist_message(self):
        return 'You are already following this artist'

    @property
    def error_invalid_link_message(self):
        return 'Invalid artist link'

    @property
    def help_message(self):
        return 'Command usage:  /followartist spotify_artist_url'

    @staticmethod
    def _build_message(followed_artist_response: OrderedDict) -> str:
        artist = followed_artist_response.get('artist')
        msg = f'<strong>Followed artist:</strong> {artist.get("name")}. \n'
        msg += 'You will be aware of it\'s albums releases'
        return msg
 def __init__(self, update, context):
     super().__init__(update, context)
     self.lastfm_api_client = LastfmAPIClient()
     self.spotify_api_client = SpotifyAPIClient()
 def _save_link(link_id: int, user_id: int) -> OrderedDict:
     spotify_api_client = SpotifyAPIClient()
     create_saved_link_response = spotify_api_client.create_saved_link(
         link_id, user_id)
     return create_saved_link_response
Exemple #14
0
 def __init__(self, update: Update, context: CallbackContext):
     self.update = update
     self.context = context
     self.spotify_api_client = SpotifyAPIClient()
     self._perform_search()
Exemple #15
0
class SearchInline(LoggerMixin):
    INLINE = 'search'

    def __init__(self, update: Update, context: CallbackContext):
        self.update = update
        self.context = context
        self.spotify_api_client = SpotifyAPIClient()
        self._perform_search()

    def _perform_search(self):
        self.log_inline(self.INLINE, self.update)
        user_input = self.update.inline_query.query
        entity_type = self._get_entity_type(user_input)
        if not entity_type:
            return

        query = user_input.replace(entity_type, '').strip()
        results = []
        if len(query) >= 3:
            pass
            search_results = self.spotify_api_client.search(query, entity_type)
            results = self._build_results(search_results.get('results'),
                                          entity_type)
        self._show_search_results(results)

    def _show_search_results(self, results):
        self.update.inline_query.answer(results)

    @staticmethod
    def _build_results(search_results: [], entity_type: str) -> []:
        results = []
        for result in search_results:
            thumb_url = ''
            description = ''

            if entity_type == EntityType.TRACK.value:
                album = result['album']
                artists = result['artists']
                thumb_url = album['images'][0]['url']
                description = '{} - {}'.format(
                    ', '.join(artist['name'] for artist in artists),
                    album['name'])
            elif entity_type == EntityType.ALBUM.value:
                thumb_url = result['images'][0]['url'] if result[
                    'images'] else ''
                artists = result['artists']
                description = ', '.join(artist['name'] for artist in artists)
            elif entity_type == EntityType.ARTIST.value:
                thumb_url = result['images'][0]['url'] if result[
                    'images'] else ''
                description = ', '.join(result['genres'])

            results.append(
                InlineQueryResultArticle(
                    id=result['id'],
                    thumb_url=thumb_url,
                    title=result['name'],
                    description=description,
                    input_message_content=InputTextMessageContent(
                        result['external_urls']['spotify'])))
        return results

    @staticmethod
    def _get_entity_type(user_input: str) -> str:
        entity_type = user_input.split(' ', 1)[0]
        valid_entity_type = False

        if entity_type == EntityType.ARTIST.value:
            valid_entity_type = True
        elif entity_type == EntityType.ALBUM.value:
            valid_entity_type = True
        elif entity_type == EntityType.TRACK.value:
            valid_entity_type = True

        if valid_entity_type:
            return entity_type