예제 #1
0
 def _connect(self, username, password, populate_loved=False):
     """
         Connect lastfm
         @param username as str
         @param password as str
         @thread safe
     """
     self._username = username
     if self._goa is not None or (password != '' and username != ''):
         self._is_auth = True
     else:
         self._is_auth = False
     try:
         self._check_for_proxy()
         if self._goa is None:
             LastFMNetwork.__init__(
                 self,
                 api_key=self._API_KEY,
                 api_secret=self._API_SECRET,
                 username=self._username,
                 password_hash=md5(password))
         else:
             LastFMNetwork.__init__(
                 self,
                 api_key=self._API_KEY,
                 api_secret=self._API_SECRET,
                 session_key=self._goa.call_get_access_token_sync(None)[0])
         if populate_loved:
             self._populate_loved_tracks()
     except Exception as e:
         print("Lastfm::_connect(): %s" % e)
예제 #2
0
 def _scrobble(self, artist, album, title, timestamp, duration, first=True):
     """
         Scrobble track
         @param artist as str
         @param title as str
         @param album_title as str
         @param timestamp as int
         @param duration as int
         @param first is internal
         @thread safe
     """
     debug("LastFM::_scrobble(): %s, %s, %s, %s, %s" % (artist,
                                                        album,
                                                        title,
                                                        timestamp,
                                                        duration))
     try:
         LastFMNetwork.scrobble(self,
                                artist=artist,
                                album=album,
                                title=title,
                                timestamp=timestamp)
     except BadAuthenticationError as e:
         pass
     except Exception as e:
         print("Lastfm::scrobble():", e)
         # Scrobble sometimes fails
         if first:
             self._connect(self._username, self._password)
예제 #3
0
파일: lastfm.py 프로젝트: kenden/lollypop
 def _connect(self, username, password, populate_loved=False):
     """
         Connect lastfm
         @param username as str
         @param password as str
         @thread safe
     """
     self._username = username
     if password != "" and username != "":
         self._is_auth = True
     else:
         self._is_auth = False
     try:
         self._check_for_proxy()
         LastFMNetwork.__init__(
             self,
             api_key=self._API_KEY,
             api_secret=self._API_SECRET,
             username=Lp.settings.get_value("lastfm-login").get_string(),
             password_hash=md5(password),
         )
         if populate_loved:
             self._populate_loved_tracks()
     except Exception as e:
         print("Lastfm::_connect(): %s" % e)
예제 #4
0
파일: lastfm.py 프로젝트: lesthack/lollypop
 def _scrobble(self, artist, album, title, timestamp, duration):
     """
         Scrobble track
         @param artist as str
         @param title as str
         @param album_title as str
         @param timestamp as int
         @param duration as int
         @thread safe
     """
     debug("LastFM::_scrobble(): %s, %s, %s, %s, %s" % (artist,
                                                        album,
                                                        title,
                                                        timestamp,
                                                        duration))
     try:
         LastFMNetwork.scrobble(self,
                                artist=artist,
                                album=album,
                                title=title,
                                timestamp=timestamp)
     except BadAuthenticationError:
         pass
     except:
         self._connect(self._username, self._password)
예제 #5
0
파일: lastfm.py 프로젝트: lesthack/lollypop
 def _now_playing(self, artist, album, title, duration, first=True):
     """
         Now playing track
         @param artist as str
         @param title as str
         @param album as str
         @param duration as int
         @param first is internal
         @thread safe
     """
     debug("LastFM::_now_playing(): %s, %s, %s, %s" % (artist,
                                                       album,
                                                       title,
                                                       duration))
     try:
         LastFMNetwork.update_now_playing(self,
                                          artist=artist,
                                          album=album,
                                          title=title,
                                          duration=duration)
     except BadAuthenticationError:
         if Lp.notify is not None:
             GLib.idle_add(Lp.notify.send, _("Wrong Last.fm credentials"))
     except:
         # now playing sometimes fails
         if first:
             self._connect(self._username, self._password)
             self._now_playing(artist, album, title, duration, False)
예제 #6
0
파일: lastfm.py 프로젝트: kenden/lollypop
 def __init__(self):
     """
         Init lastfm support
     """
     try:
         self._settings = Gio.Settings.new("org.gnome.system.proxy.http")
     except:
         self._settings = None
     LastFMNetwork.__init__(self, api_key=self._API_KEY, api_secret=self._API_SECRET)
     self._username = ""
     self._is_auth = False
     self._password = None
     self._check_for_proxy()
     self.connect(None)
예제 #7
0
class Scrobbler(object):
    """
    classdocs
    """

    def __init__(self):
        """
        Constructor
        """
        self.API = "b7b91229e4232d9e6dfa232b3937923e"
        self.secret = "ad646ed84aad9da4f1189454a4872cd9"

        # Allow users to create a scrobbler without logging in first
        self.authenticated = False

    def login(self, username, password):
        """
        Log in using the username and password provided. Use this function before scrobbling.
        Returns error details in case of failure
        :param password:
        :param username:
        """
        password_hash = md5(password)
        try:
            self.lastfm = LastFMNetwork(self.API, self.secret, None, username, password_hash)
        except WSError:
            raise
        else:
            self.authenticated = self.lastfm.get_authenticated_user().get_name() == username

    def scrobble(self, data):
        """
        Scrobble a list of dicts that each contain a single parsed track to Last.fm
        :param data: the tracks to scrobble
        """
        if self.authenticated:
            self.lastfm.scrobble_many(data)
        else:
            raise WSError("You are not authenticated yet, please use the login function before scrobbling.")
        return data
예제 #8
0
 def __init__(self):
     """
         Init lastfm support
     """
     self.__username = ''
     self.__is_auth = False
     self.__password = None
     self.__check_for_proxy()
     self.__goa = self.__get_goa_oauth()
     if self.__goa is None and Lp().settings.get_value('use-librefm'):
         LibreFMNetwork.__init__(self)
     else:
         if self.__goa is not None:
             self.__API_KEY = self.__goa.props.client_id
             self.__API_SECRET = self.__goa.props.client_secret
         else:
             self.__API_KEY = '7a9619a850ccf7377c46cf233c51e3c6'
             self.__API_SECRET = '9254319364d73bec6c59ace485a95c98'
         LastFMNetwork.__init__(self,
                                api_key=self.__API_KEY,
                                api_secret=self.__API_SECRET)
     self.connect(None)
예제 #9
0
 def login(self, username, password):
     """
     Log in using the username and password provided. Use this function before scrobbling.
     Returns error details in case of failure
     :param password:
     :param username:
     """
     password_hash = md5(password)
     try:
         self.lastfm = LastFMNetwork(self.API, self.secret, None, username, password_hash)
     except WSError:
         raise
     else:
         self.authenticated = self.lastfm.get_authenticated_user().get_name() == username
예제 #10
0
 def __init__(self):
     """
         Init lastfm support
     """
     try:
         self._settings = Gio.Settings.new('org.gnome.system.proxy.http')
     except:
         self._settings = None
     self._username = ''
     self._is_auth = False
     self._password = None
     self._check_for_proxy()
     self._goa = self._get_goa_oauth()
     if self._goa is not None:
         self._API_KEY = self._goa.props.client_id
         self._API_SECRET = self._goa.props.client_secret
     else:
         self._API_KEY = '7a9619a850ccf7377c46cf233c51e3c6'
         self._API_SECRET = '9254319364d73bec6c59ace485a95c98'
     LastFMNetwork.__init__(self,
                            api_key=self._API_KEY,
                            api_secret=self._API_SECRET)
     self.connect(None)
예제 #11
0
    def __init__(self, token=''):
        """Always create network"""
        with shelve.open('lastfm') as db:
            session_key = db.get('session_key')

            self.network = LastFMNetwork(
                api_key=self.API_KEY,
                api_secret=self.API_SECRET,
                session_key=session_key,
                token=token
            )

            if token:
                app.logger.info('saving session key: {}'.format(self.network.session_key))
                db['session_key'] = self.network.session_key
예제 #12
0
 def __init__(self):
     data_dir = player_get_data_dir()
     self.db_path = os.path.join(data_dir, "similarity.db")
     self.gaia_db_path = os.path.join(data_dir, "gaia.db")
     self.db_queue = PriorityQueue()
     self._db_wrapper = DatabaseWrapper()
     self._db_wrapper.daemon = True
     self._db_wrapper.set_path(self.db_path)
     self._db_wrapper.set_queue(self.db_queue)
     self._db_wrapper.start()
     self.create_db()
     self.network = LastFMNetwork(api_key=API_KEY)
     self.cache_time = 90
     if GAIA:
         self.gaia_queue = LifoQueue()
         self.gaia_analyser = GaiaAnalysis(
             self.gaia_db_path, self.gaia_queue)
         self.gaia_analyser.daemon = True
         self.gaia_analyser.start()
예제 #13
0
    def get_art(self, song):
        """Get artwork from LastFM.

        Before connecting to network, if there exists a file whose name begins
        with ``_sanitize(song['artist'] + ' ' + song['album'])``, return that
        file path.
        Do not overwrite existing files.

        :param dict song:
            A dictionary with keys ``'album'`` and ``'artist'`` to correspond
            with string representations of the album and artist (resp.) of
            interest. Use ``MPDClient.currentsong()`` to return uch a dictionary
            .
        :return:
            A string representation of the local file path to the image file for
            ``song`` or ``None`` if no results found
        """
        album_tofind = _sanitize(song['artist'], song['album'])

        l = [
            n for n in os.listdir(self.save_dir) if n.startswith(album_tofind)
        ]
        if l != []:
            file_path = os.path.join(self.save_dir, l[0])
            sys.stderr.write("Found {}\n".format(file_path))
            return file_path

        # Define the search network compatible with LastFM API
        network = LastFMNetwork(api_key=_last_fm_api_key)

        album_search = AlbumSearch(song['album'], network)

        #if int(album_search.get_total_result_count()) == 0:
        if album_search.get_total_result_count() == None:
            # LastFm does not have this album, links to unknown.png
            sys.stderr.write("Last.FM: no results\n")
            unknown = os.path.join(self.save_dir, 'unknown.png')
            album_tofind += ".png"
            os.symlink(unknown, os.path.join(self.save_dir, album_tofind))
            return album_tofind

        # Get the first hit, since there is at least one result -
        # the "I'm feeling lucky" approach.
        album = album_search.get_next_page()[0]

        # Get url of album art from ``pylast.AlbumSearch`` object
        img_url = album.get_cover_image()

        file_path = os.path.join(self.save_dir,
                                 self._get_save_name(song, img_url))

        # Check if this file exists in filesystem already
        if os.path.isfile(file_path):
            sys.stderr.write(
                "Last.FM: we already had the album {}!\n".format(file_path))
            return file_path
        else:
            try:
                # Download the image
                urlretrieve(img_url, file_path)
            except e:
                sys.stderr.write(e + "\n")
                return None

        sys.stderr.write("Last.FM: found {}\n".format(file_path))
        return file_path
예제 #14
0
파일: nowplaying.py 프로젝트: wioxjk/npbot
class NowplayingBot(PineappleBot):
    def init(self):
        self.last_posted_track = None

    def start(self):
        for k in [
                'lastfm_api_key', 'lastfm_api_secret', 'lastfm_username',
                'lastfm_password_hash', 'youtube_key', 'use_last_played'
        ]:
            if k not in self.config:
                raise ConfigurationError(f"NowplayingBot requires a '{k}'")

        self.lastfm = LastFMNetwork(
            api_key=self.config.lastfm_api_key,
            api_secret=self.config.lastfm_api_secret,
            username=self.config.lastfm_username,
            password_hash=self.config.lastfm_password_hash)

        self.post_np()

    @interval(30)
    def post_np(self):
        # grab the track from the last.fm api
        if self.config.use_last_played == 'yes':
            currently_playing = self.lastfm.get_user(
                self.config.lastfm_username).get_recent_tracks(1)[0][0]
        else:
            currently_playing = self.lastfm.get_user(
                self.config.lastfm_username).get_now_playing()

        # don't try to post if nothing is being played
        if currently_playing is None:
            return

        # don't repost if we've already posted about this track
        if currently_playing.__hash__() == self.last_posted_track:
            return
        else:
            self.last_posted_track = currently_playing.__hash__()

        # make a best-effort guess at the youtube link for this track
        yt_search = search_youtube(str(currently_playing),
                                   key=self.config.youtube_key)
        if len(yt_search) > 0:
            yt_link = f"https://www.youtube.com/watch?v={yt_search[0]['id']}"
        else:
            yt_link = '🎇 no youtube link, sorry 🎇'

        # template the post
        post_template = '''\
#np #nowplaying #fediplay {artist} - {track}

{yt_link}'''

        post = post_template.format(
            artist=currently_playing.get_artist().get_name(
                properly_capitalized=True),
            track=currently_playing.get_title(),
            yt_link=yt_link)

        # do the thing
        self.mastodon.status_post(post, visibility='unlisted')
예제 #15
0
class LastFm:
    # You have to have your own unique two values for API_KEY and API_SECRET
    # Obtain yours from http://www.last.fm/api/account for Last.fm
    # API_KEY = '2b532992c84242d372f5c0044d6883e5'
    # API_SECRET = '3c6688ac84deda063a697f5662a93eb0'
    API_KEY = '8fc05a68240dadf4c2430392768053fe'
    API_SECRET = 'bc2d48b14f3e864c6a07bbb6f9a0b690'
    URL_AUTH = 'http://www.last.fm/api/auth/?api_key={}'.format(API_KEY)
    URL_CALLBACK = 'http%3A%2F%2F127.0.0.1%3A5656%2Flastfm%2Fcallback'

    network = None
    LOVE_CUTOFF = 0.97

    def __init__(self, token=''):
        """Always create network"""
        with shelve.open('lastfm') as db:
            session_key = db.get('session_key')

            self.network = LastFMNetwork(
                api_key=self.API_KEY,
                api_secret=self.API_SECRET,
                session_key=session_key,
                token=token
            )

            if token:
                app.logger.info('saving session key: {}'.format(self.network.session_key))
                db['session_key'] = self.network.session_key

    def scrobble(self, history):
        """Scrobble song to lastfm"""
        params = {
            'artist': history.song.artist.name,
            'album': history.song.album.name,
            'title': history.song.name,
            'track_number': history.song.track_number,
            'timestamp': int(history.played_at.timestamp()),
        }
        app.logger.info('scrobbling: {}'.format(params))
        self.network.scrobble(**params)

    def show_some_love(self, songs):
        """Sets track to love or not"""
        app.logger.info('showing some love for {} songs'.format(len(songs)))
        for song in songs:
            db.session.refresh(song)
            network_track = self.network.get_track(song.artist.name, song.name)
            is_loved = song.rating >= self.LOVE_CUTOFF
            app.logger.debug('[{:.0f}%] {} loving {}'.format(
                song.rating * 100, is_loved, network_track))
            if is_loved:
                network_track.love()
            else:
                network_track.unlove()
            # is_loved = network_track.get_userloved()
            # app.logger.debug('found network track {} loved {}'.format(network_track, is_loved))
            # if is_loved:
            #     if song.rating < self.LOVE_CUTOFF:
            #         app.logger.info('lost love {} [{:.0f}%]'.format(network_track, song.rating *
            #                                                        100))
            #         res = network_track.unlove()
            #         app.logger.debug(res)
            #     else:
            #         app.logger.info('still loving {} [{:.0f}%]'.format(network_track, song.rating *
            #                                                          100))
            # else:
            #     res = network_track.unlove()
            #     app.logger.debug(res)
            #     if song.rating >= self.LOVE_CUTOFF:
            #         app.logger.info('new love {} [{:.0f}%]'.format(network_track, song.rating *
            #                                                        100))
            #         res = network_track.love()
            #         app.logger.debug(res)
            #     else:
            #         app.logger.info('still no love for {} [{:.0f}%]'.format(network_track,
            #                                                              song.rating * 100))

    def get_user_top_albums(self, user_name, period=None):
        """Get top albums for user"""
        period = period or PERIOD_12MONTHS
        user = self.network.get_user(user_name)
        return user.get_top_albums(period)

    def get_user_playcount(self, user):
        """Get playcount of user"""

    def get_similar_tracks(self, artist, title):
        """Get similar tracks to this song"""
        track = self.network.get_track(artist, title)
        similar = track.get_similar()
        app.logger.info('Found {} similar tracks for {} {}'.format(len(similar), artist, title))
        return similar
예제 #16
0
파일: __init__.py 프로젝트: rubenwardy/mews
from flask import Flask

app = Flask(__name__)
app.config.from_pyfile("../config.cfg")

from pylast import LastFMNetwork
lastfm = LastFMNetwork(api_key=app.config["LASTFM_API_KEY"],
                       api_secret=app.config["LASTFM_API_SECRET"])

from . import views, models
예제 #17
0
def lastfm(keyword):
    network = LastFMNetwork(api_key=API_KEY, api_secret=API_SECRET)
    suggestion = network.search_for_track("", keyword).get_next_page()[0]
    artist, title = suggestion.artist.get_name(), suggestion.title
    print(artist, "-", title)
    return artist, title
예제 #18
0
class LastFm:
    # You have to have your own unique two values for API_KEY and API_SECRET
    # Obtain yours from http://www.last.fm/api/account for Last.fm
    # API_KEY = '2b532992c84242d372f5c0044d6883e5'
    # API_SECRET = '3c6688ac84deda063a697f5662a93eb0'
    API_KEY = '8fc05a68240dadf4c2430392768053fe'
    API_SECRET = 'bc2d48b14f3e864c6a07bbb6f9a0b690'
    URL_AUTH = 'http://www.last.fm/api/auth/?api_key={}'.format(API_KEY)
    URL_CALLBACK = 'http%3A%2F%2F127.0.0.1%3A5656%2Flastfm%2Fcallback'

    network = None
    LOVE_CUTOFF = 0.97

    def __init__(self, token=''):
        """Always create network"""
        with shelve.open('lastfm') as db:
            session_key = db.get('session_key')

            self.network = LastFMNetwork(api_key=self.API_KEY,
                                         api_secret=self.API_SECRET,
                                         session_key=session_key,
                                         token=token)

            if token:
                app.logger.info('saving session key: {}'.format(
                    self.network.session_key))
                db['session_key'] = self.network.session_key

    def scrobble(self, history):
        """Scrobble song to lastfm"""
        params = {
            'artist': history.song.artist.name,
            'album': history.song.album.name,
            'title': history.song.name,
            'track_number': history.song.track_number,
            'timestamp': int(history.played_at.timestamp()),
        }
        app.logger.info('scrobbling: {}'.format(params))
        self.network.scrobble(**params)

    def show_some_love(self, songs):
        """Sets track to love or not"""
        app.logger.info('showing some love for {} songs'.format(len(songs)))
        for song in songs:
            db.session.refresh(song)
            network_track = self.network.get_track(song.artist.name, song.name)
            is_loved = song.rating >= self.LOVE_CUTOFF
            app.logger.debug('[{:.0f}%] {} loving {}'.format(
                song.rating * 100, is_loved, network_track))
            if is_loved:
                network_track.love()
            else:
                network_track.unlove()
            # is_loved = network_track.get_userloved()
            # app.logger.debug('found network track {} loved {}'.format(network_track, is_loved))
            # if is_loved:
            #     if song.rating < self.LOVE_CUTOFF:
            #         app.logger.info('lost love {} [{:.0f}%]'.format(network_track, song.rating *
            #                                                        100))
            #         res = network_track.unlove()
            #         app.logger.debug(res)
            #     else:
            #         app.logger.info('still loving {} [{:.0f}%]'.format(network_track, song.rating *
            #                                                          100))
            # else:
            #     res = network_track.unlove()
            #     app.logger.debug(res)
            #     if song.rating >= self.LOVE_CUTOFF:
            #         app.logger.info('new love {} [{:.0f}%]'.format(network_track, song.rating *
            #                                                        100))
            #         res = network_track.love()
            #         app.logger.debug(res)
            #     else:
            #         app.logger.info('still no love for {} [{:.0f}%]'.format(network_track,
            #                                                              song.rating * 100))

    def get_user_top_albums(self, user_name, period=None):
        """Get top albums for user"""
        period = period or PERIOD_12MONTHS
        user = self.network.get_user(user_name)
        return user.get_top_albums(period)

    def get_user_playcount(self, user):
        """Get playcount of user"""

    def get_similar_tracks(self, artist, title):
        """Get similar tracks to this song"""
        track = self.network.get_track(artist, title)
        similar = track.get_similar()
        app.logger.info('Found {} similar tracks for {} {}'.format(
            len(similar), artist, title))
        return similar
예제 #19
0
def get_last():
    with open('instance/config.yaml', 'r') as fp:
        config = yaml.load(fp)
    return LastFMNetwork(api_key=config['lastfm_api_key'],
                         api_secret=config['lastfm_api_secret'])
# Clean Welcome
CLEAN_WELCOME = sb(os.environ.get("CLEAN_WELCOME", "True"))

# Last.fm Module
BIO_PREFIX = os.environ.get("BIO_PREFIX", None)
DEFAULT_BIO = os.environ.get("DEFAULT_BIO", None)

LASTFM_API = os.environ.get("LASTFM_API", None)
LASTFM_SECRET = os.environ.get("LASTFM_SECRET", None)
LASTFM_USERNAME = os.environ.get("LASTFM_USERNAME", None)
LASTFM_PASSWORD_PLAIN = os.environ.get("LASTFM_PASSWORD", None)
LASTFM_PASS = md5(LASTFM_PASSWORD_PLAIN)
if LASTFM_API and LASTFM_SECRET and LASTFM_USERNAME and LASTFM_PASS:
    lastfm = LastFMNetwork(api_key=LASTFM_API,
                           api_secret=LASTFM_SECRET,
                           username=LASTFM_USERNAME,
                           password_hash=LASTFM_PASS)
else:
    lastfm = None

# Google Drive Module
G_DRIVE_CLIENT_ID = os.environ.get("G_DRIVE_CLIENT_ID", None)
G_DRIVE_CLIENT_SECRET = os.environ.get("G_DRIVE_CLIENT_SECRET", None)
G_DRIVE_AUTH_TOKEN_DATA = os.environ.get("G_DRIVE_AUTH_TOKEN_DATA", None)
GDRIVE_FOLDER_ID = os.environ.get("GDRIVE_FOLDER_ID", None)
TEMP_DOWNLOAD_DIRECTORY = os.environ.get("TMP_DOWNLOAD_DIRECTORY",
                                         "./downloads")

# Setting Up CloudMail.ru and MEGA.nz extractor binaries,
# and giving them correct perms to work properly.
if not os.path.exists('bin'):
예제 #21
0
    def get_art(self, song):
        """Get artwork from LastFM.

        Before connecting to network, if there exists a file whose name begins
        with ``_sanitize(song['artist'] + ' ' + song['album'])``, return that
        file path.
        Do not overwrite existing files.
        Set ``os.path.join(save_dir, 'current')`` as symlink to image file.

        :param dict song: 
            A dictionary with keys ``'album'`` and ``'artist'`` to correspond
            with string representations of the album and artist (resp.) of 
            interest. Use ``MPDClient.currentsong()`` to return uch a dictionary
            .
        :return:
            A string representation of the local file path to the image file for
            ``song`` or ``None`` if no results found
        """
        l = [
            n for n in os.listdir(self.save_dir)
            if n.startswith(song['artist'] + "_" + song['album'])
        ]
        if l != []:
            sys.stderr.write("Already have this album\n")
            file_path = os.path.join(self.save_dir, l[0])

            # We have album art - check if it's linked
            if os.path.realpath(self.link_path) != file_path:
                sys.stderr.write("Linking...\n")
                self.remove_current_link()
                self.set_current_link(file_path)
            sys.stderr.write("Exiting.\n")
            return file_path

        # Define the search network compatible with LastFM API
        network = LastFMNetwork(api_key=_last_fm_api_key)

        album_search = AlbumSearch(song['artist'] + ' ' + song['album'],
                                   network)

        if album_search.get_total_result_count() == 0:
            # Remove current album link, and return, since no art was found for
            # given query.
            sys.stderr.write("No results from Last.FM\n")
            self.remove_current_link()
            return None

        # Get the first hit, since there is at least one result -
        # the "I'm feeling lucky" approach.
        album = album_search.get_next_page()[0]

        # Get url of album art from ``pylast.AlbumSearch`` object
        img_url = album.get_cover_image()

        file_path = os.path.join(self.save_dir,
                                 self._get_save_name(song, img_url))

        # Check if this file exists in filesystem already and is linked
        if os.path.isfile(file_path):
            if os.path.realpath(self.link_path) == file_path:
                return file_path
        else:
            try:
                # Download the image
                urlretrieve(img_url, file_path)
                self.remove_current_link()
            except HTTPError as e:
                sys.stderr.write(e + "\n")
                self.remove_current_link()
                return None

        self.set_current_link(file_path)
        return file_path
예제 #22
0
파일: lastfm.py 프로젝트: COMU/gramafon
def Client():
    global _network
    if not _network:
        _network = LastFMNetwork(api_key=api_k, api_secret=api_s)
        _network.enable_rate_limit()
    return _network
예제 #23
0
class Similarity(object):

    """Here the actual similarity computation and lookup happens."""

    def __init__(self):
        data_dir = player_get_data_dir()
        self.db_path = os.path.join(data_dir, "similarity.db")
        self.gaia_db_path = os.path.join(data_dir, "gaia.db")
        self.db_queue = PriorityQueue()
        self._db_wrapper = DatabaseWrapper()
        self._db_wrapper.daemon = True
        self._db_wrapper.set_path(self.db_path)
        self._db_wrapper.set_queue(self.db_queue)
        self._db_wrapper.start()
        self.create_db()
        self.network = LastFMNetwork(api_key=API_KEY)
        self.cache_time = 90
        if GAIA:
            self.gaia_queue = LifoQueue()
            self.gaia_analyser = GaiaAnalysis(
                self.gaia_db_path, self.gaia_queue)
            self.gaia_analyser.daemon = True
            self.gaia_analyser.start()

    def execute_sql(self, sql=None, priority=1, command=None):
        """Put sql command on the queue to be executed."""
        if command is None:
            command = SQLCommand(sql)
        self.db_queue.put((priority, command))

    def get_sql_command(self, sql, priority=1):
        """Build a SQLCommand, put it on the queue and return it."""
        command = SQLCommand(sql)
        self.execute_sql(command=command, priority=priority)
        return command

    def remove_track_by_filename(self, filename):
        if not filename:
            return
        if GAIA:
            self.gaia_queue.put((REMOVE, filename))

    def get_ordered_gaia_tracks_by_request(self, filename, number, request):
        start_time = time()
        tracks = self.gaia_analyser.get_tracks(
            filename, number, request=request)
        print("finding gaia matches took %f s" % (time() - start_time,))
        return tracks

    def get_ordered_gaia_tracks(self, filename, number):
        """Get neighbours for track."""
        start_time = time()
        tracks = self.gaia_analyser.get_tracks(filename, number)
        print("finding gaia matches took %f s" % (time() - start_time,))
        return tracks

    def get_artist(self, artist_name):
        """Get artist information from the database."""
        sql = ("SELECT * FROM artists WHERE name = ?;", (artist_name,))
        command = self.get_sql_command(sql, priority=1)
        for row in command.result_queue.get():
            return row
        sql2 = ("INSERT INTO artists (name) VALUES (?);", (artist_name,))
        command = self.get_sql_command(sql2, priority=0)
        command.result_queue.get()
        command = self.get_sql_command(sql, priority=1)
        for row in command.result_queue.get():
            return row

    def get_track_from_artist_and_title(self, artist_name, title):
        """Get track information from the database."""
        artist_id = self.get_artist(artist_name)[0]
        sql = (
            "SELECT * FROM tracks WHERE artist = ? AND title = ?;",
            (artist_id, title))
        command = self.get_sql_command(sql, priority=3)
        for row in command.result_queue.get():
            return row
        sql2 = (
            "INSERT INTO tracks (artist, title) VALUES (?, ?);",
            (artist_id, title))
        command = self.get_sql_command(sql2, priority=2)
        command.result_queue.get()
        command = self.get_sql_command(sql, priority=3)
        for row in command.result_queue.get():
            return row

    def get_similar_tracks(self, track_id):
        """Get similar tracks from the database.

        Sorted by descending match score.

        """
        sql = (
            "SELECT track_2_track.match, artists.name, tracks.title"
            " FROM track_2_track INNER JOIN tracks ON"
            " track_2_track.track2 = tracks.id INNER JOIN artists ON"
            " artists.id = tracks.artist WHERE track_2_track.track1 = ? UNION "
            "SELECT track_2_track.match, artists.name, tracks.title"
            " FROM track_2_track INNER JOIN tracks ON"
            " track_2_track.track1 = tracks.id INNER JOIN artists ON"
            " artists.id = tracks.artist WHERE track_2_track.track2"
            " = ? ORDER BY track_2_track.match DESC;",
            (track_id, track_id))
        command = self.get_sql_command(sql, priority=0)
        return command.result_queue.get()

    def get_similar_artists(self, artist_id):
        """Get similar artists from the database.

        Sorted by descending match score.

        """
        sql = (
            "SELECT match, name FROM artist_2_artist INNER JOIN"
            " artists ON artist_2_artist.artist2 = artists.id WHERE"
            " artist_2_artist.artist1 = ? UNION "
            "SELECT match, name FROM artist_2_artist INNER JOIN"
            " artists ON artist_2_artist.artist1 = artists.id WHERE"
            " artist_2_artist.artist2 = ? ORDER BY match DESC;",
            (artist_id, artist_id))
        command = self.get_sql_command(sql, priority=0)
        return command.result_queue.get()

    def get_artist_match(self, artist1, artist2):
        """Get artist match score from database."""
        sql = (
            "SELECT match FROM artist_2_artist WHERE artist1 = ?"
            " AND artist2 = ?;",
            (artist1, artist2))
        command = self.get_sql_command(sql, priority=2)
        for row in command.result_queue.get():
            return row[0]
        return 0

    def get_track_match(self, track1, track2):
        """Get track match score from database."""
        sql = (
            "SELECT match FROM track_2_track WHERE track1 = ? AND track2 = ?;",
            (track1, track2))
        command = self.get_sql_command(sql, priority=2)
        for row in command.result_queue.get():
            return row[0]
        return 0

    def update_artist_match(self, artist1, artist2, match):
        """Write match score to the database."""
        self.execute_sql((
            "UPDATE artist_2_artist SET match = ? WHERE artist1 = ? AND"
            " artist2 = ?;",
            (match, artist1, artist2)), priority=10)

    def update_track_match(self, track1, track2, match):
        """Write match score to the database."""
        self.execute_sql((
            "UPDATE track_2_track SET match = ? WHERE track1 = ? AND"
            " track2 = ?;",
            (match, track1, track2)), priority=10)

    def insert_artist_match(self, artist1, artist2, match):
        """Write match score to the database."""
        self.execute_sql((
            "INSERT INTO artist_2_artist (artist1, artist2, match) VALUES"
            " (?, ?, ?);",
            (artist1, artist2, match)), priority=10)

    def insert_track_match(self, track1, track2, match):
        """Write match score to the database."""
        self.execute_sql((
            "INSERT INTO track_2_track (track1, track2, match) VALUES"
            " (?, ?, ?);",
            (track1, track2, match)), priority=10)

    def update_artist(self, artist_id):
        """Write artist information to the database."""
        self.execute_sql((
            "UPDATE artists SET updated = DATETIME('now') WHERE id = ?;",
            (artist_id,)), priority=10)

    def update_track(self, track_id):
        """Write track information to the database."""
        self.execute_sql((
            "UPDATE tracks SET updated = DATETIME('now') WHERE id = ?",
            (track_id,)), priority=10)

    def update_similar_artists(self, artists_to_update):
        """Write similar artist information to the database."""
        for artist_id, similar in list(artists_to_update.items()):
            for artist in similar:
                row = self.get_artist(artist['artist'])
                if row:
                    id2 = row[0]
                    if self.get_artist_match(artist_id, id2):
                        self.update_artist_match(
                            artist_id, id2, artist['score'])
                        continue
                    self.insert_artist_match(artist_id, id2, artist['score'])
            self.update_artist(artist_id)

    def update_similar_tracks(self, tracks_to_update):
        """Write similar track information to the database."""
        for track_id, similar in list(tracks_to_update.items()):
            for track in similar:
                row = self.get_track_from_artist_and_title(
                    track['artist'], track['title'])
                if row:
                    id2 = row[0]
                    if self.get_track_match(track_id, id2):
                        self.update_track_match(track_id, id2, track['score'])
                        continue
                    self.insert_track_match(track_id, id2, track['score'])
            self.update_track(track_id)

    def create_db(self):
        """Set up a database for the artist and track similarity scores."""
        self.execute_sql((
            'CREATE TABLE IF NOT EXISTS artists (id INTEGER PRIMARY KEY, name'
            ' VARCHAR(100), updated DATE, UNIQUE(name));',), priority=0)
        self.execute_sql(
            ('CREATE TABLE IF NOT EXISTS artist_2_artist (artist1 INTEGER,'
             ' artist2 INTEGER, match INTEGER, UNIQUE(artist1, artist2));',),
            priority=0)
        self.execute_sql((
            'CREATE TABLE IF NOT EXISTS tracks (id INTEGER PRIMARY KEY, artist'
            ' INTEGER, title VARCHAR(100), updated DATE, '
            'UNIQUE(artist, title));',), priority=0)
        self.execute_sql((
            'CREATE TABLE IF NOT EXISTS track_2_track (track1 INTEGER, track2'
            ' INTEGER, match INTEGER, UNIQUE(track1, track2));',), priority=0)
        self.execute_sql((
            "CREATE INDEX IF NOT EXISTS a2aa1x ON artist_2_artist "
            "(artist1);",), priority=0)
        self.execute_sql((
            "CREATE INDEX IF NOT EXISTS a2aa2x ON artist_2_artist "
            "(artist2);",), priority=0)
        self.execute_sql(
            ("CREATE INDEX IF NOT EXISTS t2tt1x ON track_2_track (track1);",),
            priority=0)
        self.execute_sql(
            ("CREATE INDEX IF NOT EXISTS t2tt2x ON track_2_track (track2);",),
            priority=0)

    def delete_orphan_artist(self, artist):
        """Delete artists that have no tracks."""
        sql = (
            'SELECT artists.id FROM artists WHERE artists.name = ? AND '
            'artists.id NOT IN (SELECT tracks.artist from tracks);',
            (artist,))
        command = self.get_sql_command(sql, priority=10)
        for row in command.result_queue.get():
            artist_id = row[0]
            self.execute_sql((
                'DELETE FROM artist_2_artist WHERE artist1 = ? OR artist2 = '
                '?;', (artist_id, artist_id)), priority=10)
            self.execute_sql(
                ('DELETE FROM artists WHERE id = ?', (artist_id,)),
                priority=10)

    def analyze_track(self, filename):
        """Perform gaia analysis of a track."""
        if not filename:
            return
        if GAIA:
            self.gaia_queue.put((ADD, filename))

    def analyze_tracks(self, filenames):
        """Analyze audio files."""
        if not filenames:
            return
        if GAIA:
            for filename in filenames:
                self.gaia_queue.put((ADD, filename))

    def get_similar_tracks_from_lastfm(self, artist_name, title, track_id,
                                       cutoff=0):
        """Get similar tracks."""
        try:
            lastfm_track = self.network.get_track(artist_name, title)
        except (WSError, NetworkError, MalformedResponseError) as e:
            print(e)
            return []
        tracks_to_update = {}
        results = []
        try:
            for similar in lastfm_track.get_similar():
                match = int(100 * similar.match)
                if match <= cutoff:
                    continue
                item = similar.item
                similar_artist = item.artist.get_name()
                similar_title = item.title
                tracks_to_update.setdefault(track_id, []).append({
                    'score': match,
                    'artist': similar_artist,
                    'title': similar_title})
                results.append((match, similar_artist, similar_title))
        except (WSError, NetworkError, MalformedResponseError) as e:
            print(e)
            return []
        self.update_similar_tracks(tracks_to_update)
        return results

    def get_similar_artists_from_lastfm(self, artist_name, artist_id,
                                        cutoff=0):
        """Get similar artists from lastfm."""
        try:
            lastfm_artist = self.network.get_artist(artist_name)
        except (WSError, NetworkError, MalformedResponseError) as e:
            print(e)
            return []
        artists_to_update = {}
        results = []
        try:
            for similar in lastfm_artist.get_similar():
                match = int(100 * similar.match)
                if match <= cutoff:
                    continue
                name = similar.item.get_name()
                artists_to_update.setdefault(artist_id, []).append({
                    'score': match,
                    'artist': name})
                results.append((match, name))
        except (WSError, NetworkError, MalformedResponseError) as e:
            print(e)
            return []
        self.update_similar_artists(artists_to_update)
        return results

    def get_ordered_similar_tracks(self, artist_name, title):
        """Get similar tracks from last.fm/the database.

        Sorted by descending match score.

        """
        now = datetime.now()
        track = self.get_track_from_artist_and_title(
            artist_name, title)
        track_id, updated = track[0], track[3]
        if updated:
            updated = datetime(*strptime(updated, "%Y-%m-%d %H:%M:%S")[0:6])
            if updated + timedelta(self.cache_time) > now:
                print(
                    "Getting similar tracks from db for: %s - %s" % (
                        artist_name, title))
                return self.get_similar_tracks(track_id)
        return self.get_similar_tracks_from_lastfm(
            artist_name, title, track_id)

    def get_ordered_similar_artists(self, artists):
        """Get similar artists from the database.

        Sorted by descending match score.

        """
        results = []
        now = datetime.now()
        for name in artists:
            artist_name = name
            result = None
            artist = self.get_artist(artist_name)
            artist_id, updated = artist[0], artist[2]
            if updated:
                updated = datetime(
                    *strptime(updated, "%Y-%m-%d %H:%M:%S")[0:6])
                if updated + timedelta(self.cache_time) > now:
                    print(
                        "Getting similar artists from db for: %s " %
                        artist_name)
                    result = self.get_similar_artists(artist_id)
            if not result:
                result = self.get_similar_artists_from_lastfm(
                    artist_name, artist_id)
            results.extend(result)
        results.sort(reverse=True)
        return results

    def miximize(self, filenames):
        """Return ideally ordered list of filenames."""
        if not GAIA:
            return []

        return self.gaia_analyser.get_miximized_tracks(filenames)
예제 #24
0
 def __init__(self, username=''):
     self._username = username
     self._api = LastFMNetwork(api_key=get_last_fm_api_key())
     self._user = self._api.get_user(self._username)
예제 #25
0
TZ_NUMBER = int(os.environ.get("TZ_NUMBER", 1))

# Clean Welcome
CLEAN_WELCOME = sb(os.environ.get("CLEAN_WELCOME", "True"))

# Last.fm Module
BIO_PREFIX = os.environ.get("BIO_PREFIX", None)
DEFAULT_BIO = os.environ.get("DEFAULT_BIO", None)

LASTFM_API = os.environ.get("LASTFM_API", None)
LASTFM_SECRET = os.environ.get("LASTFM_SECRET", None)
LASTFM_USERNAME = os.environ.get("LASTFM_USERNAME", None)
LASTFM_PASSWORD_PLAIN = os.environ.get("LASTFM_PASSWORD", None)
LASTFM_PASS = md5(LASTFM_PASSWORD_PLAIN)
if LASTFM_API and LASTFM_SECRET and LASTFM_USERNAME and LASTFM_PASS:
    lastfm = LastFMNetwork(api_key=LASTFM_API,
                           api_secret=LASTFM_SECRET,
                           username=LASTFM_USERNAME,
                           password_hash=LASTFM_PASS)
else:
    lastfm = None

# Google Drive Module
G_DRIVE_CLIENT_ID = os.environ.get("G_DRIVE_CLIENT_ID", None)
G_DRIVE_CLIENT_SECRET = os.environ.get("G_DRIVE_CLIENT_SECRET", None)
G_DRIVE_AUTH_TOKEN_DATA = os.environ.get("G_DRIVE_AUTH_TOKEN_DATA", None)
GDRIVE_FOLDER_ID = os.environ.get("GDRIVE_FOLDER_ID", None)
TEMP_DOWNLOAD_DIRECTORY = os.environ.get("TMP_DOWNLOAD_DIRECTORY",
                                         "./downloads")

# Setting Up CloudMail.ru and MEGA.nz extractor binaries,