Beispiel #1
0
    def search_lyrics(call):
        """Handle searching for a song's lyrics."""
        data = call.data
        artist = data[ATTR_ARTIST_NAME]
        title = data[ATTR_SONG_TITLE]
        entity_id = data.get(CONF_ENTITY_ID)
        state = data.get("state")
        old_state = hass.states.get(entity_id)
        if old_state:
            attrs = old_state.attributes
        else:
            attrs = {}

        # get lyrics
        from lyricsgenius import Genius
        genius = Genius(genius_access_token)
        #_LOGGER.debug("Searching for lyrics with artist '{}' and title '{}'".format(artist, title))
        song = genius.search_song(title, artist, get_full_info=False)

        if song is None:
            #_LOGGER.debug("Song not found.")
            attrs = {
                'artist':
                artist.title(),  # title case until we have a preformatted name
                'title': title,
                'lyrics': None
            }
        else:
            #_LOGGER.debug("Song data: \n{}".format(song.to_dict()))
            attrs = song.to_dict()
            attrs['artist'] = artist.title(
            )  # title case until we have a preformatted name

        if entity_id is not None:
            hass.states.set(entity_id, state, attrs)
Beispiel #2
0
class Lyrics:
    def __init__(self):
        self.genius = Genius(data["geniusAPI"]["token"])

    def searchLyrics(self, name):
        try:
            song, artist = (name.strip()).split(',')
        except:
            song, artist = name.strip(), ""

        self.song = self.genius.search_song(song, artist)
        song_info = {
            "title": self.song.title,
            "artist": self.song.artist,
            "lyrics": self.song.lyrics,
            "thumbnail": self.song.song_art_image_thumbnail_url,
            "linecount": (self.song.lyrics).count('\n')
        }
        return song_info

    def serachSongByLyrics(self, lyr):
        request = self.genius.search_lyrics(lyr)
        ans = []
        for hit in request['sections'][0]['hits']:
            ans.append((hit['result']['full_title']).split(' by'))
        return ans

    def saveLyrics(self, songName, songLyrics):
        with open(f'{songName }.txt', 'w') as f:
            f.write(songLyrics)
Beispiel #3
0
class GeniusProvider(LyricsProviderABC):
    NAME = 'genius.com'

    API_BASE_URL = 'https://api.genius.com/'
    LYRICS_BASE_URL = 'https://genius.com/'

    def __init__(self):
        super().__init__()

        self.api = GeniusAPI(constants.Genius.TOKEN, verbose=False)

    def _requests_lyrics(self, track: 'Track') -> Optional[str]:
        try:
            track_genius = self.api.search_song(
                f'{track.title.replace(" - Bonus Track", "")} by {track.artists[0]}'
            )
            if track_genius is None:
                self.logger.info(
                    f'GeniusProvider: Track not found: {track_genius}')
                return

            self.logger.debug(
                f'GeniusProvider: Found track: {track_genius.title}')
            return track_genius.lyrics
        except requests.exceptions.HTTPError as e:
            raise HTTPError(self.__class__, e)
        except requests.exceptions.RequestException as e:
            raise NetworkError(self.__class__, e)
Beispiel #4
0
def get_song_genius(track_name, artist_name):
    genius = Genius(GENIUS_TOKEN, verbose=False)
    song = genius.search_song(track_name, artist_name)

    if not song:
        return None

    song = json.loads(song.to_json())

    if not valid_song(track_name, song['title'], artist_name,
                      song['primary_artist']['name']):
        return None

    try:
        meaning = song['description']['plain'].split('\n')
        assert (meaning != ["?"] and meaning != [""])
    except:
        meaning = None

    response = {
        'lyrics': add_line_breaks(song['lyrics'].split('\n')),
        'meaning': meaning,
        'source': 'Genius',
        'source_url': song['url'],
    }

    for item in song['media']:
        if item['provider'] == 'youtube':
            response['youtube_embed_url'] = 'https://www.youtube.com/embed/' + \
                item['url'].split('=')[1]
            break

    return response
class OpenSongLyrics:
    def __init__(self):
        self.sclient_id = spotify_client_id
        self.sclient_secret = spotify_client_secret
        self.redirect_uri = 'http://localhost:8080'
        self.scope = 'user-read-playback-state'
        self.username = '******'
        self.client_credentials_manager = SpotifyOAuth(
            username=self.username,
            redirect_uri=self.redirect_uri,
            scope=self.scope,
            client_id=self.sclient_id,
            client_secret=self.sclient_secret,
            open_browser=False)
        self.genius_token = genius_token
        self.lyrics = None
        self.genius = Genius(client_access_token=self.genius_token,
                             response_format='dom',
                             verbose=True,
                             skip_non_songs=True)

    def get_song_info(self):
        sp = spotipy.Spotify(
            client_credentials_manager=self.client_credentials_manager)
        playback_read = sp.current_playback()
        if playback_read is not None:
            get_title = playback_read['item']['name']
            get_artists = playback_read['item']['artists']
            artists = []
            for artist in get_artists:
                name = artist['name']
                artists.append(name)
            album = playback_read['item']['album']['name']
            song_info = {
                'title': get_title,
                'artists': artists,
                'album': album
            }
            print(song_info)
        else:
            song_info = {}
        return song_info

    def get_current_lyrics(self):
        song_info = self.get_song_info()
        print(song_info)
        song_title = clean_title(artists=song_info['artists'],
                                 song_title=song_info['title'])
        self.lyrics = self.genius.search_song(
            title=song_title, artist=song_info['artists'][0]).lyrics
        # artists = " ".join(song_info['artists'])
        # term = song_title + " " + artists
        # a = genius.search_all(term, per_page=5, page=1)
        # aa = genius._get_item_from_search_response(a, term, type_='song', result_type='song_title')
        # album = genius.search_lyrics()
        return self.lyrics
def lyrics(message):
    args = extract_args(message)
    if r"-" in args:
        pass
    else:
        edit(message, f'`{get_translation("lyricsError")}`')
        return

    if not GENIUS_TOKEN:
        edit(message, f'`{get_translation("geniusToken")}`')
    else:
        genius = Genius(GENIUS_TOKEN)
        try:
            args = args.split('-')
            artist = args[0].strip()
            song = args[1].strip()
        except BaseException:
            edit(message, f'`{get_translation("lyricsError2")}`')
            return

    if len(args) < 1:
        edit(message, f'`{get_translation("lyricsError2")}`')
        return

    edit(message, get_translation('lyricsSearch', ['`', artist, song]))

    try:
        songs = genius.search_song(song, artist)
    except TypeError:
        songs = None

    if not songs:
        edit(message, get_translation('lyricsNotFound', ['**', artist, song]))
        return
    if len(songs.lyrics) > 4096:
        edit(message, f'`{get_translation("lyricsOutput")}`')
        with open('lyrics.txt', 'w+') as f:
            f.write(
                get_translation('lyricsQuery',
                                ['', '', artist, song, songs.lyrics]))
        reply_doc(message, 'lyrics.txt', delete_after_send=True)
    else:
        edit(
            message,
            get_translation('lyricsQuery',
                            ['**', '`', artist, song, songs.lyrics]),
        )
    return
Beispiel #7
0
class Genius(Provider):
    name = 'genius'
    synchronized = False

    def __init__(self, config_entry):
        remove_section_headers = config_entry.getboolean(
            'remove_section_headers', False)
        self.genius = LyrGenius(
            config_entry['token'],
            verbose=False,
            remove_section_headers=remove_section_headers,
        )

    def get_lyrics(self, artist: str, title: str, _: int) -> Lyrics:
        lyrics = Lyrics()
        song = self.genius.search_song(title, artist, get_full_info=False)
        if song:
            lyrics.unsynchronized = song.lyrics
        return lyrics
def get_lyrics(artist, song_title):
    """ Retrieves lyrics from Genius.com using a python """
    artist = artist.lower()
    song_title = song_title.lower()

    genius = Genius(LYRICS_SECRET_KEY)

    # genius = lyricsgenius.Genius(LYRICS_SECRET_KEY)

    try:
        # import pdb; pdb.set_trace()
        song = genius.search_song(song_title, artist)
        # song = genius.song(song_title, artist)
        if (song):

            lyrics = song.lyrics.replace('\n', '<br>')
            return {'status': 'success', 'msg': 'ok', 'lyrics': lyrics}

        else:  # No matching lyrics were found
            status = 'error'
            msg = NO_MATCHING_LYRICS
            lyrics = None
            return {'status': status, 'msg': msg, 'lyrics': lyrics}

    except Exception as e:
        print(f"Exception occurred in retrieving lyrics: {str(e)}")
        status = 'error'
        lyrics = None
        if e.status == 404:
            msg = f"{NO_MATCHING_LYRICS} (error-code ={e.status})"
        elif e.status == 403:
            msg = f"{LYRICS_SERVICE_NOT_RESPONDiNG} (error code={e.status}) "
        elif e.status == 500:

            msg = f"Server error occurred (error-code={e.status})"
        else:  # Catch all for all other errors
            msg = f"{MISC_SERVER_ERROR} (error-code={e.status})"

        # import pdb; pdb.set_trace()
        return {'status': status, 'msg': msg, 'lyrics': lyrics}
Beispiel #9
0
def get_song_lyrics(genius: lyricsgenius.Genius, song: str,
                    artist: str) -> Union[dict, None]:
    """Searches Genius for song details based on song name and artist.

    Args:
        genius (lyricsgenius.Genius): LyricsGenius object to use for query.
        song (str): Title of song
        artist (str): Name of artist

    Returns:
        Union[dict,None]: Song details (from JSON) or `None` if no results.
    """
    songdetails = genius.search_song(
        title=song,
        artist=artist,
        get_full_info=True,
    )

    if songdetails:
        return songdetails.to_dict()
    else:
        return None
Beispiel #10
0
class GetGenius:
    def __init__(self):
        # init Genius
        GENIUS_ACCESS_TOKEN = os.getenv('GENIUS_ACCESS_TOKEN')
        self.genius = Genius(GENIUS_ACCESS_TOKEN)

    def get_lyrics(self, query):
        lyrics = []

        results = self.genius.search_lyrics(query)
        for hit in results['sections'][0]['hits']:
            if hit['result']['title'][-4:] != 'list':
                docid = hit['result']['id']
                title = str(hit['result']['title']).replace('/', ' ').replace(
                    '?', ' ')
                artist = hit['result']['primary_artist']['name']
                url_img = hit['result']['song_art_image_url']
                lyric = self.genius.search_song(title, artist).lyrics

                lyrics.append([docid, title, artist, url_img, lyric])

        return (lyrics)
def retrieve_song_lyrics(update, context):
    '''get song lyrics'''
    text = update.message.text
    genius = Genius(LYRICS_TOKEN)
    genius.skip_non_songs = True
    song = genius.search_song(text, artist='', get_full_info=False)
    if not song:
        update.message.reply_text("Unable to find lyrics for the given song.")
    else:
        lyrics = song.lyrics
        song_length = len(lyrics)
        count = 0
        try:
            while song_length > 4096:
                update.message.reply_text(lyrics[:4096])
                song_length -= 4096
                count += 1
            update.message.reply_text(lyrics[4096 * count:])
        except:
            update.message.reply_text(
                "Unable to find lyrics for the given song.")
    update.message.reply_text("Use /help to list available actions.")
    return ConversationHandler.END
Beispiel #12
0
 def cmd_lyrics(arg):
     token = "47eX0yhBx2cDhrs1n7530NrDmSVJbuCmgCORJRDv9wvIbtbKRAK4BPP2_uoKVaN3"
     genius = Genius(token)
     search_phrase = str(arg)
     try:
         full_input = search_phrase.lower()
         full_input = full_input.split(",")
         artist_input = full_input[0]
         song_input = full_input[1]
         result = genius.search_song(song_input, artist_input)
         text_data = result.lyrics
     except Exception as E:
         text_data = (
             "Lyric search failed, please check the spelling of the artist and song title. Please note, "
             "there are millions of songs and artist in the database, your query has to be exactly right to "
             "retrieve the lyrics.")
         text_data += "Your body of the message should look like one of the following examples: \r"
         text_data += "Ariana Grande, Imagine \r"
         text_data += "Lady Gaga, Shallow \r"
         text_data += "Mariah Carey, All I want for Christmas is Your \r"
         text_data += "Chainsmokers, Hope \r"
         text_data += "Error: " + str(E)
     return text_data
Beispiel #13
0
def main():
    genius = Genius(apikeys.genius)
    genius.excluded_terms = ['(How to pronounce)']
    genius.remove_section_headers = True
    genius.skip_non_songs = True
    pinyin = Pinyin()

    song_info = [
        input("Enter the song name\n"),
        input(
            "Enter the artist name (recommended, leave blank if you don't know)\n"
        )
    ]
    song = genius.search_song(song_info[0], song_info[1])
    lyrics = song.lyrics

    pinyin_lyrics = pinyin.get_pinyin(lyrics, splitter=' ', tone_marks='marks')
    pinyin_lyrics = cleanup(pinyin_lyrics)
    print(pinyin_lyrics)

    outfile_path = "C:\\Users\\Declan\\Desktop\\" + song.title + ', ' + song.artist + '-Pinyin.txt'
    outfile = open(outfile_path, 'w', encoding='utf-8')
    outfile.write(pinyin_lyrics)
    outfile.close()
Beispiel #14
0
class GeniusLyrics:
    def __init__(self, access_token, genius=None):
        self.__artist = None
        self.__title = None
        self.__lyrics = None
        self.__genius = None

        from lyricsgenius import Genius
        # use or create Genius class
        if isinstance(genius, Genius):
            self.__genius = genius
        else:
            self.__genius = Genius(access_token, skip_non_songs=True)

    @property
    def artist(self):
        return self.__artist

    @artist.setter
    def artist(self, new_artist):
        self.__artist = new_artist
        _LOGGER.debug(f"Artist set to: {self.__artist}")

    @property
    def title(self):
        return self.__title

    @title.setter
    def title(self, new_title):
        # filter out terms from title
        # TODO: move to CONFIG_SCHEMA
        exclude_terms = [
            '(explicit',
            '(feat',
        ]
        _new_title = str(new_title).lower()
        for term in exclude_terms:
            if term in _new_title:
                pos = _new_title.find(term)
                self.__title = new_title[0:pos].strip()
                break
        else:
            self.__title = new_title
        _LOGGER.debug(f"Title set to: {self.__title}")

    @property
    def lyrics(self):
        return self.__lyrics

    def fetch_lyrics(self, artist=None, title=None):
        if artist:
            self.__artist = artist
        if title:
            self.__title = title

        if self.__artist is None or self.__title is None:
            _LOGGER.error("Missing artist and/or title")
            return

        _LOGGER.info(
            f"Search lyrics for artist='{self.__artist}' and title='{self.__title}'"
        )

        song = self.__genius.search_song(self.__title,
                                         self.__artist,
                                         get_full_info=False)
        if song:
            _LOGGER.debug(
                f"Found song: artist = {song.artist}, title = {song.title}")

            # FIXME: need to avoid incorrectly found song lyrics
            # for now..comparing artist names suffices. Titles may differ (e.g. 'feat. John Doe')
            # if self.__title == song.title:
            #     _LOGGER.debug(f"Found lyrics: {song.lyrics}")

            # if str(self.__artist).lower() == str(song.artist).lower() \
            #         or str(song.title).lower() in str(self.__title).lower():

            self.__title = song.title
            self.__lyrics = song.lyrics
            return True
        else:
            self.__lyrics = "Lyrics not found"
            return False

    def reset(self):
        self.__artist = None
        self.__title = None
        self.__lyrics = None
    def execute(self, context):
        if self.skip_task == True:
            return

        genius = Genius(self.genius_access_token)

        redshift = PostgresHook(postgres_conn_id=self.redshift_conn_id)

        self.year = context.get('execution_date').year

        if (self.delete_before_insert == True):
            self.log.info("Clearing data from destination Redshift table")
            redshift.run("DELETE FROM {}".format(self.to_table))

        self.log.info("Getting songs to query their lyrics")
        if self.select_limit is not None:
            select_limit = "LIMIT {}".format(self.select_limit)
        else:
            select_limit = ""
        select_query = """
           SELECT
                  artist_name AS artist,
                  song_name AS song
             FROM staging_charts
            WHERE chart_year = '{}'
              AND chart_title = '{}'
            {}
        """.format(self.year, self.chart_name.replace("'", "\\'"),
                   select_limit)
        song_list = redshift.get_records(select_query)
        self.log.info("Querying lyrics for {} tracks".format(len(song_list)))

        sid = SentimentIntensityAnalyzer()
        song_lyrics = []
        for song in song_list:
            try:
                genius_song = genius.search_song(song[1], song[0])
            except Exception as e:
                self.log.error(e)
            if genius_song is not None:
                self.log.info('Found : {} - {}'.format(genius_song.title,
                                                       genius_song.artist))

                # get the lyrics
                sentence = genius_song.lyrics
                # remove words between [] and ()
                sentence = re.sub(r'\[.*\]', '', sentence)
                sentence = re.sub(r'\(.*\)', '', sentence)
                # tokenize
                tokens = nltk.word_tokenize(sentence)
                # tokenize without punctuation and converting to lowercase
                lower_alpha_tokens = [
                    w for w in word_tokenize(sentence.lower()) if w.isalpha()
                ]
                # remove stopwords
                no_stops = [
                    t for t in lower_alpha_tokens
                    if t not in stopwords.words('english')
                ]
                # get stopwords removed
                only_stops = [
                    x for x in lower_alpha_tokens if x not in no_stops
                ]
                # count
                count_words = len(lower_alpha_tokens)
                count_stopwords = len(only_stops)
                count_no_stopwords = len(no_stops)
                count_distinct_words = len(
                    collections.Counter(lower_alpha_tokens))
                count_distinct_no_stopwords = len(
                    collections.Counter(no_stops))
                count_distinct_words_used_once = len([
                    x[1] for x in collections.Counter(no_stops).most_common()
                    if x[1] == 1
                ])
                # get most frequent words
                distinct_most_common = [
                    '{}:{}'.format(x[0], x[1]) for x in collections.Counter(
                        no_stops).most_common(self.most_common_count)
                ]
                count_most_common_usage = sum([
                    x[1] for x in collections.Counter(no_stops).most_common(
                        self.most_common_count)
                ])
                # analyse sentiment
                lyrics_sentiment = sid.polarity_scores(sentence)
                common_words_sentiment = sid.polarity_scores(' '.join([
                    x[0] for x in collections.Counter(no_stops).most_common(
                        self.most_common_count)
                ]))
                common_words_sentiment_with_weights = sid.polarity_scores(
                    ' '.join([
                        ' '.join([x[0]] * x[1]) for x in collections.Counter(
                            no_stops).most_common(self.most_common_count)
                    ]))

                song_lyrics.append({
                    'artist':
                    genius_song.artist,
                    'song':
                    genius_song.title,
                    'lyrics':
                    genius_song.lyrics.replace("'", "\\'"),
                    'count_words':
                    count_words,
                    'count_no_stopwords':
                    count_no_stopwords,
                    'count_distinct_words':
                    count_distinct_words,
                    'count_distinct_no_stopwords':
                    count_distinct_no_stopwords,
                    'count_distinct_words_used_once':
                    count_distinct_words_used_once,
                    'distinct_most_common':
                    ','.join(distinct_most_common),
                    'count_most_common_usage':
                    count_most_common_usage,
                    'lyrics_sentiment':
                    lyrics_sentiment['compound'],
                    'common_words_sentiment':
                    common_words_sentiment['compound'],
                    'common_words_sentiment_with_weights':
                    common_words_sentiment_with_weights['compound'],
                })

        self.log.info("Copying data to table")
        data_to_insert = [("(" + ",".join(
            (len(song)) * ["'{}'"]) + ")").format(
                song['artist'],
                song['song'],
                song['lyrics'][0:65535],
                song['count_words'],
                song['count_no_stopwords'],
                song['count_distinct_words'],
                song['count_distinct_no_stopwords'],
                song['count_distinct_words_used_once'],
                song['distinct_most_common'],
                song['count_most_common_usage'],
                song['lyrics_sentiment'],
                song['common_words_sentiment'],
                song['common_words_sentiment_with_weights'],
            ) for song in song_lyrics]
        formatted_sql = self.sql_query.format(self.to_table,
                                              ','.join(data_to_insert))
        redshift.run(formatted_sql)
from lyricsgenius import Genius
# token goes here
# still need to get the token

genius = Genius(token)
res = genius.search_song("Red Hot Chili Peppers", "Under the Bridge")

print(res.lyrics)
Beispiel #17
0
# load env file
load_dotenv(find_dotenv())
# init twilio things
twilio_account_sid = os.getenv('TWILIO_ACCOUNT_SID')
twilio_auth_token = os.getenv('TWILIO_AUTH_TOKEN')
# init lyrics genius things
lyrics_genius_client_id = os.getenv('GENIUS_CLIENT_ID')
genius = Genius(lyrics_genius_client_id)
# get artist info
#song = genius.search_song("Look At Me", "xxxtentacion")
#song = genius.search_song("WAP", "cardi b")
#song = genius.search_song("f**k love", "xxxtentacion")
#song = genius.search_song("lateralus", "tool")
#song = genius.search_song("and i told them i invented times new roman", "dance gavin dance")
song = genius.search_song("throat babies", "city girls")
lyrics = song.lyrics.splitlines()

pyautogui.PAUSE = 1
sleep(2)
for line in lyrics:
    pyautogui.write(line + "\n", )
    #pyautogui.press("enter",interval=0.025, _pause=0.25)

#phone_num_to = "+17867201701"
#phone_num_from = "+17866996629"
#lyrics_file = "/Users/jasonballadares/repos/imessagespambot/data/lookatme.txt"
#lyrics = get_lyrics(lyrics_file)

# send_messages(phone_num_to, phone_num_from, lyrics,
#              Client(account_sid, auth_token))
Beispiel #18
0
    df = pd.DataFrame({
        "track": track,
        "artist": artist,
    })

    return df


spotify_data = get_playlist_tracks(playlist_uri)
print(spotify_data)

lyrics = [""] * len(spotify_data)
for i, (track, artist) in tqdm(
        enumerate(zip(spotify_data["track"], spotify_data["artist"]))):
    try:
        song = genius.search_song(track, artist, get_full_info=False)
        lyrics[i] = song.lyrics
    except:
        print(f'Skipping "{track}" by {artist}')

for i, x in tqdm(enumerate(lyrics)):
    if x == "":
        track = spotify_data["track"][i]
        artist = spotify_data["artist"][i]
        try:
            song = genius.search_song(track, artist, get_full_info=False)
            lyrics[i] = song.lyrics
        except:
            print(f'Giving up on "{track}" by {artist}')

spotify_data.insert(2, "lyrics", lyrics)
Beispiel #19
0
 def _fetch_lyrics(self, query: str) -> typing.Optional[Song]:
     genius = Genius(self.GENIUS_TOKEN, verbose=False)
     return genius.search_song(query, get_full_info=False)
Beispiel #20
0
from lyricsgenius import Genius
from colorama import init, Fore, Style
from mutagen.easyid3 import EasyID3
from genius_tokens import CLIENT_ACCESS_TOKEN
import sys

args = sys.argv

if len(args) == 1:
    print("Specify path to audio")
    exit(1)

audio_path = args[1]
audio = EasyID3(audio_path)

genius = Genius(CLIENT_ACCESS_TOKEN)
genius.verbose = False
genius.remove_section_headers = True
song = genius.search_song(audio["title"][0], audio["artist"][0])

print(song.lyrics)
Beispiel #21
0
class Scraper:
    """
    Scraper for genius data. 

    Args: 
        genius_auth_path (str): filepath to the authorization text file with
            genius API client access token. Default is 'data/genius.auth'
        minsleep (float): minimum time to sleep between requests to the 
            genius API. Default is 0.5
    """
    def __init__(self, genius_auth_path="data/genius.auth", minsleep=0.5):

        # gets client access token
        with open("data/genius.auth", "r") as file:
            client_access_token = file.read().strip()

        self.minsleep = minsleep
        self.api = Genius(client_access_token, remove_section_headers=True)
        self.lyrics = MongoClient().billboard["lyrics"]
        self.errlog = MongoClient().billboard["lyrics_errlog"]
        print("Initialized")

    def populate_billboard_scrapables(self):
        """
        Identifies billboard tracks to scrape from the spotify collection.
        Returns: None. sets self.df
        """
        results = MongoClient().billboard.spotify.find()
        self.df = pd.DataFrame(
            data=map(
                lambda r: (
                    r["metadata"]["id"],
                    r["metadata"]["artists"][0]["name"],
                    r["metadata"]["name"],
                ),
                results,
            ),
            columns=["track_id", "artist_name", "title"],
        )
        print(f"Tracks identified to scrape lyrics: {self.df.shape[0]}")

    def populate_nillboard_scrapables(self):
        """
        Populates tracks to scraped that are not on the billboard
        Returns: None. Sets internal state as self.df
        """

        # initialize db connection
        db = MongoClient().billboard

        # get the track_ids that have already been scraped.
        scraped_ids = [r["_id"] for r in db.lyrics.find()
                       ] + [r["metadata"]["id"] for r in db.spotify.find()]
        print("scraped ids", len(scraped_ids))

        # get the entries that have not yet been scraped
        tracks_cursor = db.spotify_nillboard.find(
            {"_id": {
                "$nin": scraped_ids
            }})

        # unpack the db response cursor
        data = map(
            lambda r: [
                r["_id"],
                r["metadata"]["artists"][0]["name"],
                r["metadata"]["name"],
            ],
            tracks_cursor,
        )

        # set internal dataframe to be scraped
        self.df = pd.DataFrame(data,
                               columns=["track_id", "artist_name", "title"])
        print(f"Tracks identified to scrape lyrics: {self.df.shape[0]}")

    def scrape_df_segment_to_db(self, scraperange, verbose=1):
        """
        Scrapes an index range from self.df to the database.

        Args:
            scraperange (iterable): iterable of indices to scrape from self.df
                to the db
            verbose (int): verbosity level. Higher verbosity, more prints.

        Returns: None. Puts genius data in billboard.lyrics and errors in 
            billboard.lyrics_errlog when needed.
        """

        for i in scraperange:
            row = self.df.iloc[i]
            try:
                self.scrape_song_to_db(row["artist_name"], row["title"],
                                       row["track_id"])

            # record error and continue
            except TypeError as e:
                self.record_error(row["track_id"], "TypeError")

            # track has already been scraped to the db - print and continue
            except DuplicateKeyError:
                if verbose:
                    print(f"Duplicate skipped on index {i}")

            if verbose > 1:
                print(i)

    def scrape_song_to_db(self, artist, title, track_id):
        """
        Scrapes a single track to the database. 

        Args: 
            artist (str): the artist name
            title (str): the title of the track
            track_id (str): the id of the track to be used as the mongodb _id 

        Returns: None. Adds a track to the lyrics collection, or lyrics_errlog 
        if needed. 
        """

        # remove featured artist names
        artist = stripFeat(artist)

        try:
            # record stout from lyricsgenius call because it catches errors and prints
            with Capturing() as output:
                songdata = self.api.search_song(title, artist)

        # for the few errors that have been raised
        except ReadTimeout:
            self.api.sleep_time += 3
            print(f"sleep time increased to {self.api.sleep_time}")
            self.record_error(track_id, "ReadTimeout")
            self.scrape_song_to_db(artist, title, track_id)
            return

        # take sleep time slowly back to minimum
        if self.api.sleep_time > self.minsleep:
            self.api.sleep_time -= 0.25
            print(f"sleep time decreased to {self.api.sleep_time}")

        # search successful
        if songdata != None:
            self.record_lyrics_result(track_id, songdata)

        # handle (record & retry) Timeout error
        elif output[1].startswith("Timeout"):
            self.api.sleep_time += 3
            self.record_error(track_id, "Timeout")
            self.scrape_song_to_db(artist, title, track_id)
            return

        # record error: not in genius db
        elif output[1].startswith("No results"):
            self.record_error(track_id, "no_results")

        # record error: song without lyrics
        elif output[1] == "Specified song does not contain lyrics. Rejecting.":
            self.record_error(track_id, "lacks_lyrics")

        # record error: URL issue
        elif (output[1] ==
              "Specified song does not have a valid URL with lyrics. Rejecting."
              ):
            self.record_error(track_id, "invalid_url")

    def record_lyrics_result(self, track_id, songdata):
        """
        Inserts a track's lyrics to the lyrics collection.

        Args: 
            track_id (str): spotify track id to be the mongodb _id
            songdata (dict): contains track data in keys 'artist', 'title', and 'lyrics'

        Returns: None. A song is inserted into the lyrics collection.
        """
        self.lyrics.insert_one({
            "_id": track_id,
            "response_artist": songdata.artist,
            "response_title": songdata.title,
            "lyrics": songdata.lyrics,
        })

    def record_error(self, track_id, errtype):
        """
        Inserts the record of an error into the errlog collection.

        Args:
            track_id (str): id of the track this error occurred on
            errtype (str): type of error that occurred.

        Returns: None. Inserts 1 record into the errlog collection
        """
        self.errlog.insert_one({"track": track_id, "type": errtype})

    def record_error_verbose(self, track_id, errmsg):
        """
        Inserts a verbose error into the errlog collection.

        Args:   
            track_id (str): id of the track this error occurred on
            errmsg (str): error message to record

        Returns: None. An error of type 'verbose' is inserted into the errlog collection.
        """
        self.errlog.insert_one({
            "track": track_id,
            "type": "verbose",
            "message": errmsg
        })
Beispiel #22
0
class music(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.YTDL_OPTIONS = {
            'format': 'bestaudio',
            'noplaylist': True,
            'default-search': 'auto',
            'quiet': True,
            'extractaudio': True,
            'audioformat': 'mp3',
            'rm-cache-dir': True,
            'skip_download': True
        }
        self.YTDL_OPTIONS_PLAYLIST_FIRSTSONG = {
            'format': 'bestaudio',
            'extractaudio': True,
            'skip_download': True,
            'playlistend': 1,
            'noplaylist': False,
            'quiet': True,
            '-yes_playlist': True
        }
        self.YTDL_OPTIONS_PLAYLIST_RESTOFSONGS = {
            'format': 'bestaudio',
            'extractaudio': True,
            'skip_download': True,
            'playliststart': 2,
            'playlistend': 20,
            'quiet': True,
            'noplaylist': False,
            '-yes_playlist': True
        }
        self.FFMPEG_OPTIONS = {
            'before_options':
            '-reconnect 1 -reconnect_streamed 1 -reconnect_delay_max 5',
            'options': '-vn'
        }
        conn = sqlite.connect("data/internal.db")
        conn.execute(
            "CREATE TABLE IF NOT EXISTS music(id INTEGER PRIMARY KEY, guild_id INTEGER NOT NULL, current_song TEXT, queued_songs TEXT, loop INTEGER NOT NULL)"
        )
        conn.commit()
        conn.close()
        self.lyrics_finder = Genius(GENIUS_TOKEN)

    def songs_to_string(self, songs):
        output = ""
        for song in songs:
            output += f"|{song['track']}|{song['title']}|{song['artist']}|{song['duration']}|{song['likes']}|{song['dislikes']}|{song['link']}|{song['author']}|"

        return output

    def song_to_string(self, song):
        return f"|{song['track']}|{song['title']}|{song['artist']}|{song['duration']}|{song['likes']}|{song['dislikes']}|{song['link']}|{song['author']}|"

    def songs_from_string(self, songs):
        if songs == "" or songs == None or not songs:
            return []
        songs = songs.split("||")
        output = []
        for song in songs:
            if song == "":
                pass
            else:
                song = list(filter(None, song.split("|")))

                output.append({
                    'track': song[0],
                    'title': song[1],
                    'artist': song[2],
                    'duration': song[3],
                    'likes': song[4],
                    'dislikes': song[5],
                    'link': song[6],
                    'author': song[7]
                })

        return output

    def song_from_string(self, song):
        if not song:
            return {}
        song = song.split("|")
        return {
            'track': song[1],
            'title': song[2],
            'artist': song[3],
            'duration': song[4],
            'likes': song[5],
            'dislikes': song[6],
            'link': song[7],
            'author': song[8]
        }

    def write_to_db(self, ctx, song):
        conn = sqlite.connect("data/internal.db")
        song_to_store = f"|{song['track']}|{song['title']}|{song['artist']}|{song['duration']}|{song['likes']}|{song['dislikes']}|{song['link']}|{song['author']}|"
        if len(
                conn.execute(
                    f"SELECT * FROM music WHERE guild_id = {ctx.guild.id}").
                fetchall()) == 0:
            conn.execute("INSERT INTO music VALUES(NULL, ?, ?, ?, ?)",
                         [ctx.guild.id, "", song_to_store, 0])
        else:
            guild_music = conn.execute(
                f"SELECT * FROM music WHERE guild_id = {ctx.guild.id}"
            ).fetchall()[0]
            guild_loop = guild_music[4]
            guild_music = self.songs_from_string(guild_music[3])
            if guild_loop == 1:
                guild_music.insert(-1, song)
            else:
                guild_music.append(song)
            conn.execute(
                f"UPDATE music SET queued_songs = ? WHERE guild_id = ?",
                (self.songs_to_string(guild_music), ctx.guild.id))

        conn.commit()
        conn.close()

    def write_to_db_multiple(self, ctx, songs):
        conn = sqlite.connect("data/internal.db")
        songs_to_store = self.songs_to_string(songs)
        if len(
                conn.execute(
                    f"SELECT * FROM music WHERE guild_id = {ctx.guild.id}").
                fetchall()) == 0:
            conn.execute("INSERT INTO music VALUES(NULL, ?, ?, ?, ?)",
                         [ctx.guild.id, "", songs_to_store, 0])
        else:
            guild_music = conn.execute(
                f"SELECT * FROM music WHERE guild_id = {ctx.guild.id}"
            ).fetchall()[0]
            guild_loop = guild_music[4]
            guild_music = self.songs_from_string(guild_music[3])
            if guild_loop == 1:
                for song in songs:
                    guild_music.insert(-1, song)
            else:
                guild_music.extend(songs)
            conn.execute(
                f"UPDATE music SET queued_songs = ? WHERE guild_id = ?",
                (self.songs_to_string(guild_music), ctx.guild.id))

        conn.commit()
        conn.close()

    async def get_audio_info(self, song, author, ytlist=False, first=True):
        if not ytlist:
            if song.__contains__(
                    "https://www.youtube.com") or song.__contains__(
                        "https://www.youtu.be"):
                with YoutubeDL(self.YTDL_OPTIONS) as ydl:
                    info = ydl.extract_info(song, download=False)
            else:
                with YoutubeDL(self.YTDL_OPTIONS) as ydl:
                    info = ydl.extract_info(f"ytsearch:{song}",
                                            download=False)['entries'][0]

            try:
                creator = info['creator']

            except KeyError:
                creator = info['uploader_id']

            try:
                dislikes = info['dislike_count']

            except KeyError:
                dislikes = "Hidden"

            return {
                "track": info['url'],
                "title": info['title'],
                "artist": creator,
                "duration": info['duration'],
                "likes": info['like_count'],
                "dislikes": dislikes,
                "link": "https://www.youtube.com/watch?v=" + info['id'],
                "author": author
            }
        else:
            if first:
                with YoutubeDL(self.YTDL_OPTIONS_PLAYLIST_FIRSTSONG) as ydl:
                    info = ydl.extract_info(song, download=False)['entries'][0]

                try:
                    creator = info['creator']

                except KeyError:
                    creator = info['uploader_id']

                try:
                    dislikes = info['dislike_count']

                except KeyError:
                    dislikes = "Hidden"

                return {
                    "track": info['url'],
                    "title": info['title'],
                    "artist": creator,
                    "duration": info['duration'],
                    "likes": info['like_count'],
                    "dislikes": dislikes,
                    "link": "https://www.youtube.com/watch?v=" + info['id'],
                    "author": author
                }

            else:
                with YoutubeDL(self.YTDL_OPTIONS_PLAYLIST_RESTOFSONGS) as ydl:
                    info = ydl.extract_info(song, download=False)['entries']

                output = []

                for entry in info:

                    try:
                        creator = entry['creator']

                    except KeyError:
                        creator = entry['uploader_id']

                    try:
                        dislikes = entry['dislike_count']

                    except KeyError:
                        dislikes = "Hidden"

                    output.append({
                        "track":
                        entry['url'],
                        "title":
                        entry['title'],
                        "artist":
                        creator,
                        "duration":
                        entry['duration'],
                        "likes":
                        entry['like_count'],
                        "dislikes":
                        dislikes,
                        "link":
                        "https://www.youtube.com/watch?v=" + entry['id'],
                        "author":
                        author
                    })
                return output

    def play_audio(self, ctx, inform=True):
        conn = sqlite.connect("data/internal.db")
        guild_info = conn.execute(
            f"SELECT * FROM music WHERE guild_id = {ctx.guild.id}").fetchall(
            )[0]
        songs = self.songs_from_string(guild_info[3])
        current_song = "" if conn.execute(
            f"SELECT * FROM music WHERE guild_id = {ctx.guild.id}").fetchall(
            )[0][2] == "" else self.song_from_string(guild_info[2])
        loop = guild_info[4]

        if len(songs) > 0:

            if loop == 1 and current_song == songs[0] and len(songs) > 1:
                songs.append(songs.pop(0))

            current_song = songs.pop(0)

            if inform:
                self.bot.loop.create_task(self.inform_user(ctx))

            if loop == 1:
                songs.append(current_song)

            conn.execute(
                f"UPDATE music SET current_song = ?, queued_songs = ? WHERE guild_id = ?",
                (self.song_to_string(current_song),
                 self.songs_to_string(songs), ctx.guild.id))
            conn.commit()
            conn.close()
            ctx.voice_client.play(
                FFmpegPCMAudio(current_song['track'], **self.FFMPEG_OPTIONS),
                after=lambda error: print(error)
                if error is not None else self.play_audio(ctx))

    async def inform_user(self, ctx):
        conn = sqlite.connect("data/internal.db")
        current_song = self.songs_from_string(
            conn.execute(f"SELECT * FROM music WHERE guild_id = {ctx.guild.id}"
                         ).fetchall()[0][2])[0]
        conn.close()
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        music_field.title = f"{current_song['title']}"
        music_field.add_field(name=f"`{current_song['artist']}`",
                              value=f"Artist")
        music_field.add_field(
            name=
            f"`{datetime.timedelta(seconds = int(current_song['duration']))}`",
            value=f"Duration")
        music_field.add_field(
            name=f"`{current_song['likes']}/{current_song['dislikes']}`",
            value=f"Popularity")
        author = await ctx.guild.fetch_member(current_song['author'])
        music_field.add_field(name=f"Playing now!",
                              value=f"Requested by { author.mention}")
        await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="join")
    @commands.command()
    async def join(self, ctx, hello=""):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        if ctx.author.voice:
            if not ctx.voice_client:
                await ctx.author.voice.channel.connect()
                music_field.add_field(
                    name=f"Connected to your channel!",
                    value=
                    f"You can use `{get_prefix(self.bot, ctx.message)}play` to start some music"
                )
                if hello != "":
                    info = self.get_audio_info(
                        "https://www.youtube.com/watch?v=hCiv9wphnME")
                    ctx.voice_client.play(
                        FFmpegPCMAudio(info['track'], **self.FFMPEG_OPTIONS))
            else:
                music_field.add_field(
                    name=f"I'm already connected!",
                    value=
                    f"Use `{get_prefix(self.bot, ctx.message)}play` to play music"
                )

        else:
            music_field.add_field(
                name=f"You have to be connected to a voice channel.",
                value=
                f"What a dumb rule, right? But I have to know where to connect first."
            )

        await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="leave")
    @commands.command()
    async def leave(self, ctx):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        if ctx.voice_client:
            await ctx.voice_client.disconnect()
            music_field.add_field(
                name=f"Disconnected from voice channel!",
                value=f"And until next time, have a great time!")

        else:
            music_field.add_field(
                name=f"I am not connected anywhere!",
                value=
                f"You can use `{get_prefix(self.bot, ctx.message)}join` to get me on your channel or `{get_prefix(self.bot, ctx.message)}play` to start some music"
            )

        await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="play")
    @commands.command()
    async def play(self, ctx, *, song):

        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")

        if ctx.author.voice:
            if ctx.voice_client == None:
                await ctx.author.voice.channel.connect()

            if song.lower().__contains__("list="):

                if song.lower().__contains__("&list="):
                    x = song.index("list=")
                    song = f"https://www.youtube.com/playlist?{song[x:]}"

                info = await self.get_audio_info(song,
                                                 ctx.author.id,
                                                 ytlist=True,
                                                 first=True)
                self.write_to_db(ctx, info)
                if not ctx.voice_client.is_playing(
                ) and not ctx.voice_client.is_paused():
                    self.play_audio(ctx, inform=False)
                await self.inform_user(ctx)
                infos = await self.get_audio_info(song,
                                                  ctx.author.id,
                                                  ytlist=True,
                                                  first=False)
                self.write_to_db_multiple(ctx, infos)
                music_field.title = f"Loaded your list!"
                music_field.add_field(
                    name=
                    f"I have placed all the songs from the playlist into your queue",
                    value=
                    f"I'm sorry if it took long, sometimes, loading 200 song playlist is not an easy task."
                )
                await ctx.send(embed=music_field)
            else:
                info = await self.get_audio_info(
                    song,
                    ctx.author.id,
                )

                if not ctx.voice_client.is_playing(
                ) and not ctx.voice_client.is_paused():
                    self.write_to_db(ctx, info)
                    self.play_audio(ctx)

                else:
                    music_field.title = f"{info['title']}"
                    music_field.add_field(name=f"`{info['artist']}`",
                                          value=f"Artist")
                    music_field.add_field(
                        name=
                        f"`{datetime.timedelta(seconds = info['duration'])}`",
                        value=f"Duration")
                    music_field.add_field(
                        name=f"`{info['likes']}/{info['dislikes']}`",
                        value=f"Popularity")
                    music_field.add_field(
                        name=f"Added to queue",
                        value=f"***Sorry, somebody was faster than you.***")

                    self.write_to_db(ctx, info)

                    await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="pause")
    @commands.command()
    async def pause(self, ctx):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        conn = sqlite.connect("data/internal.db")

        if ctx.voice_client == None:
            music_field.add_field(
                name="Nothing to be paused!",
                value=
                f"This commands purpose is to pause currently playing song. To play song use `{get_prefix(self.bot, ctx.message)}play`"
            )
        else:
            if ctx.voice_client.is_playing():
                current_song = self.song_from_string(
                    conn.execute(
                        "SELECT current_song FROM music WHERE guild_id = ?",
                        (ctx.guild.id, )).fetchall()[0][0])
                music_field.add_field(
                    name=f"{current_song['title']} paused!",
                    value=
                    f"Song is now paused if you want to resume it, you can use `{get_prefix(self.bot, ctx.message)}resume`"
                )
                ctx.voice_client.pause()

            elif ctx.voice_client.is_paused():
                current_song = self.song_from_string(
                    conn.execute(
                        "SELECT current_song FROM music WHERE guild_id = ?",
                        (ctx.guild.id, )).fetchall()[0][0])
                music_field.add_field(
                    name=f"{current_song['title']} is already paused!",
                    value=
                    f"To resume it use `{get_prefix(self.bot, ctx.message)}resume`"
                )

            else:
                music_field.add_field(
                    name="Nothing to be paused!",
                    value=
                    f"This commands purpose is to pause currently playing song. To play song use `{get_prefix(self.bot, ctx.message)}play`"
                )

        await ctx.send(embed=music_field)
        conn.close()

    #@cog_ext.cog_slash(name="resume")
    @commands.command()
    async def resume(self, ctx):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        conn = sqlite.connect("data/internal.db")

        if ctx.voice_client == None:
            music_field.add_field(
                name="Nothing to be resumed!",
                value=
                f"If you want to start some music use `{get_prefix(self.bot, ctx.message)}play`"
            )
        else:
            if ctx.voice_client.is_paused():
                current_song = self.song_from_string(
                    conn.execute(
                        "SELECT current_song FROM music WHERE guild_id = ?",
                        (ctx.guild.id, )).fetchall()[0][0])
                music_field.add_field(name=f"{current_song['title']} resumed!",
                                      value=f"Let the show start again!")
                ctx.voice_client.resume()

            elif ctx.voice_client.is_playing():
                current_song = self.song_from_string(
                    conn.execute(
                        "SELECT current_song FROM music WHERE guild_id = ?",
                        (ctx.guild.id, )).fetchall()[0][0])
                music_field.add_field(
                    name=f"{current_song['title']} is playing already!",
                    value=
                    f"You can pause it using `{get_prefix(self.bot, ctx.message)}pause`"
                )

            else:
                music_field.add_field(
                    name="Nothing to be resumed!",
                    value=
                    f"If you want to start some music use `{get_prefix(self.bot, ctx.message)}play`"
                )

        await ctx.send(embed=music_field)
        conn.close()

    #@cog_ext.cog_slash(name="skip")
    @commands.command()
    async def skip(self, ctx):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        conn = sqlite.connect("data/internal.db")

        if ctx.voice_client == None:
            music_field.add_field(
                name="Nothing to be skipped!",
                value=
                f"It seems you have no songs playing nor in queue. Don't worry, use `{get_prefix(self.bot, ctx.message)}play` to play something!"
            )

        else:
            if ctx.voice_client.is_playing() or ctx.voice_client.is_paused():
                current_song = self.song_from_string(
                    conn.execute(
                        "SELECT current_song FROM music WHERE guild_id = ?",
                        (ctx.guild.id, )).fetchall()[0][0])
                conn.close()
                music_field.add_field(name=f"{current_song['title']} skipped!",
                                      value=f"You didn't like it, I see")
                ctx.voice_client.stop()

            else:
                music_field.add_field(
                    name="Nothing to be skipped!",
                    value=
                    f"It seems you have no songs playing nor in queue. Don't worry, use `{get_prefix(self.bot, ctx.message)}play` to play something!"
                )

        await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="loop")
    @commands.command()
    async def loop(self, ctx):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        conn = sqlite.connect("data/internal.db")
        if len(
                conn.execute("SELECT * FROM music WHERE guild_id = ?",
                             (ctx.guild.id, )).fetchall()) == 0:
            conn.execute("INSERT INTO music VALUES(NULL, ?, ?, ?, ?)",
                         ("", "", 1, ctx.guild.id))
            music_field.add_field(
                name="Loop turn on!",
                value=
                f"To enjoy the sweet music before you start hatin' it, {ctx.author.mention}?"
            )
            conn.commit()
            conn.close()

        else:

            loop = True if int(
                conn.execute(
                    "SELECT loop FROM music WHERE guild_id = ?",
                    (ctx.guild.id, )).fetchall()[0][0]) == 1 else False

            if loop:
                conn.execute("UPDATE music SET loop = ? WHERE guild_id = ?",
                             (0, ctx.guild.id))
                conn.commit()
                conn.close()
                music_field.add_field(name="Song looping off!",
                                      value=f"You got tired of it, huh?")

            else:
                conn.execute("UPDATE music SET loop = ? WHERE guild_id = ?",
                             (1, ctx.guild.id))
                conn.commit()
                music_field.add_field(
                    name="Loop turn on!",
                    value=
                    f"You really like ***this*** song, {ctx.author.mention}?")
                songs = self.songs_from_string(
                    conn.execute(
                        f"SELECT queued_songs FROM music WHERE guild_id = {ctx.guild.id}"
                    ).fetchall()[0][0])

                if ctx.voice_client.is_playing(
                ) or ctx.voice_client.is_paused and songs.empty():
                    conn.execute(
                        "UPDATE music SET queued_songs = ? WHERE guild_id = ?",
                        (conn.execute(
                            "SELECT current_song FROM music WHERE guild_id = ?",
                            (ctx.guild.id, )).fetchall()[0][0], ctx.guild.id))
                    conn.commit()
                    conn.close()

        await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="stop")
    @commands.command()
    async def stop(self, ctx):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        conn = sqlite.connect("data/internal.db")

        if ctx.voice_client == None:
            music_field.add_field(
                name="No songs to be stopped!",
                value=
                f"You don't have ny songs in your queue or playing. Use `{get_prefix(self.bot, ctx.message)}play` to play something!"
            )

        else:
            if ctx.voice_client.is_playing() or ctx.voice_client.is_paused():
                conn.execute(
                    "UPDATE music SET queued_songs = ?, current_song = ? WHERE guild_id = ?",
                    ("", "", ctx.guild.id))
                conn.commit()
                ctx.voice_client.stop()
                music_field.add_field(
                    name="All songs from queue were purged!",
                    value=
                    f"To disconnect me use `{get_prefix(self.bot, ctx.message)}leave` or issue `{get_prefix(self.bot, ctx.message)}play` to play new songs!"
                )

        await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="queue")
    @commands.command()
    async def queue(self, ctx):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        conn = sqlite.connect("data/internal.db")
        total_duration = 0
        if ctx.voice_client:
            if ctx.voice_client.is_playing() or ctx.voice_client.is_paused():
                current_song = self.song_from_string(
                    conn.execute(
                        "SELECT current_song FROM music WHERE guild_id = ?",
                        (ctx.guild.id, )).fetchall()[0][0])
                songs = self.songs_from_string(
                    conn.execute(
                        f"SELECT queued_songs FROM music WHERE guild_id = {ctx.guild.id}"
                    ).fetchall()[0][0])
                loop = "Yes" if conn.execute(
                    f"SELECT loop FROM music WHERE guild_id = ?",
                    (ctx.guild.id, )).fetchall()[0][0] == 1 else "No"
                if current_song:
                    music_field.title = f"`Now playing` - {current_song['title']}"
                    if songs:
                        for song in songs:
                            author = await ctx.guild.fetch_member(
                                song['author'])
                            music_field.add_field(
                                name=
                                f"`{songs.index(song) + 1}` - {song['title']} by `{song['artist']}`",
                                value=
                                f"Duration: `{datetime.timedelta(seconds = int(song['duration']))}` | Popularity: `{song['likes']}/{song['dislikes']}` | Requested by {author.mention}",
                                inline=False)
                            total_duration += int(song['duration'])

                        music_field.add_field(
                            name=f"Total Duration",
                            value=
                            f"`{datetime.timedelta(seconds = total_duration)}`"
                        )
                        music_field.add_field(name=f"Number of songs",
                                              value=f"`{len(songs)}`")
                        music_field.add_field(name=f"Loop", value=f"`{loop}`")

                    else:
                        author = await ctx.guild.fetch_member(
                            current_song['author'])
                        music_field.add_field(
                            name=f"Author: `{current_song['artist']}`",
                            value=
                            f"Duration: `{datetime.timedelta(seconds = int(current_song['duration']))}` | Popularity: `{current_song['likes']}/{current_song['dislikes']}` | Requested by {author.mention}"
                        )

                else:
                    music_field.title = f"I'm not playing anything"
                    music_field.add_field(
                        name=f"You can sit here in silence",
                        value=
                        f"Or you can play a song using `{get_prefix(self.bot, ctx.message)}play link or name of song here`"
                    )

            else:
                music_field.add_field(
                    name=f"They are no songs playing!",
                    value=
                    f"If you want to play a new song simply type `{get_prefix(self.bot, ctx.message)}play`"
                )

        else:
            music_field.title = f"You want to display a whole queue of nothingness?"
            music_field.add_field(
                name=
                f"Not even connecting me and wanting to display queue.. Rude.",
                value=
                f"You can join me into your voice channel using `{get_prefix(self.bot, ctx.message)}join`"
            )

        await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="remove")
    @commands.command()
    async def remove(self, ctx, index):
        index = int(index)
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        conn = sqlite.connect("data/internal.db")
        current_song = self.song_from_string(
            conn.execute("SELECT current_song FROM music WHERE guild_id = ?",
                         (ctx.guild.id, )).fetchall()[0][0])
        songs = self.songs_from_string(
            conn.execute(
                f"SELECT queued_songs FROM music WHERE guild_id = {ctx.guild.id}"
            ).fetchall()[0][0])

        if not songs and not ctx.voice_client.is_playing(
        ) and not ctx.voice_client.is_paused():
            music_field.add_field(
                name="There is no existing queue",
                value=
                f"But you can use `{get_prefix(self.bot, ctx.message)}play` to play something!"
            )

        elif index - 1 > len(songs):
            music_field.add_field(
                name="This song doesn't exist in your queue",
                value=
                f"To remove all songs from the queue use `{get_prefix(self.bot, ctx.message)}stop`"
            )

        elif index - 1 <= len(songs) and index - 1 >= 0:
            removed_song = songs.pop(index - 1)
            music_field.add_field(
                name=
                f"{removed_song['title']} has been removed from your queue!",
                value=f"I bet nobody will miss it anyway")
            conn.execute(
                "UPDATE music SET queued_songs = ? WHERE guild_id = ?",
                (self.songs_to_string(songs), ctx.guild.id))
            conn.commit()
        conn.close()
        await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="move")
    @commands.command()
    async def move(self, ctx, index_of_song, desired_position):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        index_of_song = int(index_of_song) - 1
        desired_position = int(desired_position) - 1
        conn = sqlite.connect("data/internal.db")
        current_song = self.song_from_string(
            conn.execute("SELECT current_song FROM music WHERE guild_id = ?",
                         (ctx.guild.id, )).fetchall()[0][0])
        songs = self.songs_from_string(
            conn.execute(
                f"SELECT queued_songs FROM music WHERE guild_id = {ctx.guild.id}"
            ).fetchall()[0][0])
        if index_of_song >= 0 and desired_position >= 0:
            if index_of_song > len(songs):
                music_field.add_field(
                    name=f"There is no song on position `{index_of_song + 1}`",
                    value=
                    f"Did you want to skip? Use `{get_prefix(bot, ctx.message)}skip` Don't worry, if you have loop enabled the song will stay in queue"
                )

            else:
                if desired_position > len(songs) - 1:
                    songs.append(songs.pop(index_of_song))
                    conn.execute(
                        "UPDATE music SET queued_songs = ? WHERE guild_id = ?",
                        (self.songs_to_string(songs), ctx.guild.id))
                    conn.commit()
                    music_field.add_field(
                        name=
                        f"Song `{songs[-1]['title']}` was moved to the end of queue from position `{index_of_song + 1}`",
                        value=
                        f"This happened because you entered number greater than the index of last song"
                    )

                else:
                    songs.insert(desired_position, songs.pop(index_of_song))
                    conn.execute(
                        "UPDATE music SET queued_songs = ? WHERE guild_id = ?",
                        (self.songs_to_string(songs), ctx.guild.id))
                    conn.commit()
                    music_field.add_field(
                        name=
                        f"I have moved `{songs[desired_position]['title']}`from position `{index_of_song + 1}` to `{desired_position + 1}`",
                        value=f"I hope I got it right!")

        conn.close()
        await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="now")
    @commands.command()
    async def now(self, ctx):

        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")

        if ctx.voice_client:
            if ctx.voice_client.is_playing() or ctx.voice_client.is_paused():
                conn = sqlite.connect("data/internal.db")
                current_song = self.song_from_string(
                    conn.execute(
                        "SELECT current_song FROM music WHERE guild_id = ?",
                        (ctx.guild.id, )).fetchall()[0][0])
                conn.close()
                if current_song:
                    author = await ctx.guild.fetch_member(
                        current_song['author'])
                    music_field.title = f"`Now playing` - {current_song['title']}"
                    music_field.add_field(
                        name=f"Author: `{current_song['artist']}`",
                        value=
                        f"Duration: `{datetime.timedelta(seconds = int(current_song['duration']))}` | Popularity: `{current_song['likes']}/{current_song['dislikes']}` | Requested by {author.mention}"
                    )

                else:
                    music_field.title = f"I'm not playing anything"
                    music_field.add_field(
                        name=
                        f"But you can play a song using `{get_prefix(self.bot, ctx.message)}play link or name of song here`",
                        value=
                        "Or you can continue sitting here in complete silence, your choice."
                    )

            else:
                music_field.title = f"I'm not playing anything"
                music_field.add_field(
                    name=
                    f"But you can play a song using `{get_prefix(self.bot, ctx.message)}play link or name of song here`",
                    value=
                    "Or you can continue sitting here in complete silence, your choice."
                )

        else:
            music_field.title = f"You have to at least connect me first!"
            music_field.add_field(
                name=
                f"I can't display nothing. Well, I can, I'm doing now, right?",
                value=
                f"You can play a song using `{get_prefix(self.bot, ctx.message)}play link or name of song here`"
            )

        await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="grab")
    @commands.command()
    async def grab(self, ctx):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        dm_field = discord.Embed(colour=discord.Colour(0xFDED32))
        dm_field.set_author(name="𝓖𝓛𝓞𝓑")
        conn = sqlite.connect("data/internal.db")
        current_song = self.song_from_string(
            conn.execute("SELECT current_song FROM music WHERE guild_id = ?",
                         (ctx.guild.id, )).fetchall()[0][0])
        conn.close()

        if ctx.voice_client.is_playing() or ctx.voice_client.is_paused():
            music_field.title = f"{current_song['title']}"
            music_field.add_field(name=f"`{current_song['artist']}`",
                                  value=f"Artist")
            music_field.add_field(
                name=
                f"`{datetime.timedelta(seconds = int(current_song['duration']))}`",
                value=f"Total Duration")
            music_field.add_field(
                name=f"`{current_song['likes']}/{current_song['dislikes']}`",
                value=f"Popularity")
            music_field.add_field(name=f"You really liked it, didn't ya?",
                                  value=f"*I sent this song to your DMs*")
            dm_field.title = f"{current_song['title']}"
            dm_field.add_field(name=f"`{current_song['artist']}`",
                               value=f"Artist")
            dm_field.add_field(
                name=
                f"`{datetime.timedelta(seconds = int(current_song['duration']))}`",
                value=f"Total Duration")
            dm_field.add_field(
                name=f"`{current_song['likes']}/{current_song['dislikes']}`",
                value=f"Popularity")
            dm_field.add_field(name=f"Here you go!",
                               value=f"{current_song['link']}")
            channel = await ctx.author.create_dm()
            await channel.send(embed=dm_field)

        else:
            music_field.title = f"I'm not playing anything!"
            music_field.add_field(
                name=
                f"If I'm not playing anything what am I supposed to send you?",
                value=f"*Who's the ape now, huh.*")

        await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="addToPlaylist")
    @commands.command()
    async def addToPlaylist(self, ctx, name, *, song_name=None):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        conn = sqlite.connect("data/internal.db")
        current_song = self.song_from_string(
            conn.execute("SELECT current_song FROM music WHERE guild_id = ?",
                         (ctx.guild.id, )).fetchall()[0][0])
        songs = self.songs_from_string(
            conn.execute(
                f"SELECT queued_songs FROM music WHERE guild_id = {ctx.guild.id}"
            ).fetchall()[0][0])
        song_to_save = ""
        if current_song == {} and song_name is None:
            music_field.add_field(name=f"You have to specify what song!",
                                  value=f"I can't add nothing to playlist..")

        else:
            if song_name == None:
                song_to_save = f"{current_song['link']}|"
            elif song_name.lower() == "queue":
                for song in self.songs:
                    song_to_save += f"{song['link']}|"
                song_to_save += f"{current_song['link']}|"
            else:
                info = await self.get_audio_info(song_name, ctx.message.author)
                song_to_save += f"{info['link']}|"
            if len(
                    conn.execute(
                        f"SELECT * FROM playlists WHERE name = '{name}' AND user_id = '{ctx.author.id}'"
                    ).fetchall()) == 0:
                conn.execute("INSERT INTO playlists VALUES(NULL, ?, ?, ?)",
                             (ctx.author.id, name, song_to_save))
                conn.commit()
                if song_name == None:
                    music_field.add_field(
                        name=
                        f"`{name}` playlist created! I added `{current_song['title']}` into it for you.",
                        value=
                        f"You can add songs to your playlist using `{get_prefix(self.bot, ctx.message)}addToPlaylist {name} song`"
                    )
                elif song_name.lower() == "queue":
                    music_field.add_field(
                        name=
                        f"New playlist named `{name}` created! And your queue added into it",
                        value=
                        f"You can play your playlist using `{get_prefix(self.bot, ctx.message)}playPlaylist {name}` or you can add songs to your queue, use `{get_prefix(self.bot, ctx.message)}addToPlaylist {name} queue` to update it"
                    )
                else:
                    music_field.add_field(
                        name=
                        f"Created new playlist named `{name}` and added `{info['title']}` into it",
                        value=
                        f"You can play your playlist using `{get_prefix(self.bot, ctx.message)}playPlaylist {name}` or you can add songs to your queue, use `{get_prefix(self.bot, ctx.message)}addToPlaylist {name} queue` to update it"
                    )

            else:
                songs_in_playlist = conn.execute(
                    f"SELECT songs FROM playlists WHERE user_id = '{ctx.author.id}' AND name = '{name}'"
                ).fetchall()[0][0]
                conn.execute(
                    f"UPDATE playlists SET songs = '{songs_in_playlist + song_to_save}' WHERE user_id = '{ctx.author.id}' AND name = '{name}'"
                )
                conn.commit()

                if song_name == None:
                    music_field.add_field(
                        name=
                        f"Added your currently playing song named `{current_song['title']}` into your playlist `{name}`",
                        value=
                        f"You can play it using `{get_prefix(self.bot, ctx.message)}playPlaylist`"
                    )
                else:
                    music_field.add_field(
                        name=
                        f"Added `{info['title']}` into your playlist named `{name}`",
                        value=
                        f"That's nice song you got there, {ctx.author.mention}!"
                    )

        conn.close()
        await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="updatePlaylist")
    @commands.command()
    async def updatePlaylist(self, ctx, name):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        conn = sqlite.connect("data/internal.db")
        current_song = self.song_from_string(
            conn.execute("SELECT current_song FROM music WHERE guild_id = ?",
                         (ctx.guild.id, )).fetchall()[0][0])
        songs = self.songs_from_string(
            conn.execute(
                f"SELECT queued_songs FROM music WHERE guild_id = {ctx.guild.id}"
            ).fetchall()[0][0])
        playlists = conn.execute(
            f"SELECT * FROM playlists WHERE name = '{name}' AND user_id = '{ctx.author.id}'"
        ).fetchall()
        if len(playlists) == 0:
            music_field.add_field(
                name=f"Couldn't find any playlists under the name `{name}`",
                value=
                f"But you can create it! Using `{get_prefix(self.bot, ctx.message)}addToPlaylist {name} song`"
            )

        else:
            songs_to_save = f"{current_song['link']}|"
            for song in songs:
                songs_to_save += f"{song['link']}|"

            conn.execute(
                f"UPDATE playlists SET songs = '{songs_to_save}' WHERE name = '{name}' AND user_id = '{ctx.author.id}'"
            )
            conn.commit()
            music_field.add_field(
                name=f"Updated playlist `{name}` according to your queue",
                value=
                f"You can now play the updated version using `{get_prefix(self.bot, ctx.message)}playPlaylist {name}`"
            )

        conn.close()
        await ctx.send(embed=music_field)

    #@cog_ext.cog_slash(name="playPlaylist")
    @commands.command()
    async def playPlaylist(self, ctx, name):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        conn = sqlite.connect("data/internal.db")
        if len(ctx.message.mentions) == 0:
            data = conn.execute(
                f"SELECT * FROM playlists WHERE name = '{name}'").fetchall()

        else:
            data = conn.execute(
                f"SELECT * FROM playlists WHERE name = '{name}' user_id = '{ctx.message.mentions[0].id}'"
            ).fetchall()

        if len(data) != 0:
            songs = list(filter(None, data[0][3].split("|")))
            if not ctx.voice_client:
                await ctx.author.voice.channel.connect()

            if not ctx.voice_client.is_playing(
            ) and not ctx.voice_client.is_paused():
                self.write_to_db(
                    ctx, await self.get_audio_info(songs.pop(0),
                                                   ctx.message.author.id))
                self.play_audio(ctx, inform=False)
                await self.inform_user(ctx)

            songs_to_write = []

            if songs:
                for song in songs:
                    songs_to_write.append(await self.get_audio_info(
                        song, ctx.message.author.id))

            self.write_to_db_multiple(ctx, songs_to_write)

            music_field.add_field(
                name=f"Replaced your queue with songs from playlist `{name}`",
                value=
                f"If you add any songs to your queue, you can update your playlist using `{get_prefix(self.bot, ctx.message)}addToPlaylist {name} update`"
            )

        else:
            music_field.add_field(
                name=f"I couldn't find any playlist under name `{name}`",
                value=
                f"Don't worry, you can always create a new one with this name using `{get_prefix(self.bot, ctx.message)}addToPlaylist {name} song`"
            )

        conn.close()
        await ctx.send(embed=music_field)

    @commands.command()
    async def lyrics(self, ctx):
        music_field = discord.Embed(colour=discord.Colour(0xFDED32))
        music_field.set_author(name="𝓜𝓾𝓼𝓲𝓬")
        conn = sqlite.connect("data/internal.db")
        current_song = self.song_from_string(
            conn.execute("SELECT current_song FROM music WHERE guild_id = ?",
                         (ctx.guild.id, )).fetchall()[0][0])
        conn.close()
        # 'track': song[1], 'title': song[2], 'artist': song[3], 'duration': song[4], 'likes': song[5], 'dislikes': song[6], 'link': song[7], 'author': song[8]
        title = current_song['title']
        strings_to_erase = re.findall(r"([([].+?[])])", title)
        for string in strings_to_erase:
            print(string)
            title = title.replace(string, '')

        music_field.title = f"Lyrics for {title}"
        lyrics = self.lyrics_finder.search_song(title).lyrics
        words = list(filter(None, re.split(r"[[].+?[]]", lyrics)))
        titles = list(filter(None, re.findall(r"[[].+?[]]", lyrics)))

        for i in range(len(titles)):
            music_field.add_field(name=f"{titles[i]}",
                                  value=f"{words[i]}",
                                  inline=False)
            #music_field.remove_field(index=0)

        await ctx.send(embed=music_field)