def count_players(): """ Returns the number of players currently registered. """ cursor = DB().execute('SELECT COUNT(*) FROM "players"')["cursor"] total = cursor.fetchone()[0] cursor.close() return total
class LastFM(Worker): _title = 'lastfm' _key = None _lfm = None # wait this amount of seconds between lookups _lookup_threshold = 10 _last_lookup = None _history_filename = None _artist_history = {} _track_history = {} _db = None def __init__(self, config, no_cache=False): Worker.__init__(self) self._key = config.get('LastFM', 'key', None) self._lfm = Api(self._key, no_cache=no_cache) self._db = DB(config.get('LastFM', 'path', join(config.configdir(), 'echonest.db'))) self._db.execute( u"CREATE TABLE IF NOT EXISTS artist_lookup "\ "(artist text, timestamp integer, "\ "PRIMARY KEY(artist))") self._db.execute( u"CREATE TABLE IF NOT EXISTS track_lookup "\ "(artist text, title text, timestamp integer, "\ "PRIMARY KEY(artist, title))") self._db.commit() def get_artist_timestamp(self, artist): self._db.execute( u"SELECT timestamp FROM artist_lookup "\ "WHERE artist=?", (artist,)) row = self._db.fetchone() if row: return row[0] return 0 def set_artist_timestamp(self, artist, timestamp): self._db.execute( u"REPLACE INTO artist_lookup (artist, timestamp) "\ "VALUES (?, ?)", (artist, timestamp)) self._db.commit() def get_track_timestamp(self, artist, title): self._db.execute( u"SELECT timestamp FROM track_lookup "\ "WHERE artist=? and title=?", (artist, title)) row = self._db.fetchone() if row: return row[0] return 0 def set_track_timestamp(self, artist, title, timestamp): self._db.execute( u"REPLACE INTO track_lookup (artist, title, timestamp) "\ "VALUES (?, ?, ?)", (artist, title, timestamp)) self._db.commit() def _delay(self): if self._last_lookup: last_lookup = (datetime.utcnow() - self._last_lookup) if last_lookup.seconds < self._lookup_threshold: self._logger.debug(u"sleeping %ss" % ( self._lookup_threshold - last_lookup.seconds)) sleep(self._lookup_threshold - last_lookup.seconds) self._last_lookup = datetime.utcnow() def _track(self, artist, title): self._delay() result = self._lfm.search_track(track=title, artist=artist) # for some tracks (e.g. 'after all' from 'the peacocks' lastfm doesn't # return the correct track as first result (for 'peacocks' it works?!)) # so let's try to find the correct track for t in result: self._logger.info(u'{} {} vs {} {}'.format(artist, title, t.artist.name.lower() ,t.name.lower())) if t.artist.name.lower() == artist and t.name.lower() == title: return t if len(result) == 0: return None return result[0] # return the first def _artist(self, artist): self._delay() result = self._lfm.search_artist(artist=artist) for a in result: if a.name.lower() == artist: return a if len(result) == 0: return None return result[0] def similar_tracks(self, callback, artist, title, threshold): self.queue_callback(self._similar_tracks, callback, artist, title, threshold) def similar_tracks_low(self, callback, artist, title, threshold): self.queue_callback_low(self._similar_tracks, callback, artist, title, threshold) def _similar_tracks(self, callback, artist, title, threshold): """ callback(artist, title, sim_artist, sim_title, match, source) """ timestamp = now() diff = timestamp - self.get_track_timestamp(artist, title) if diff < threshold: self._logger.debug(u"similar_tracks[%s-%s]: looked up %d seconds ago" % (artist, title, diff)) return self.set_track_timestamp(artist, title, timestamp) try: self._logger.debug(u"similar_tracks[%s-%s]: lookup" % (artist, title)) t = self._track(artist, title) if t is None: self._logger.info(u"similar_tracks[%s-%s]: no result" % (artist, title)) return else: p = t.similar self._logger.info(u"similar_tracks[%s-%s]: %d result(s)" % (artist, title, len(p))) for sim in p: callback(artist, title, sim.artist.name.lower(), sim.name.lower(), sim.stats.match, self._title) except URLError, e: self._logger.info(e) self._logger.info(u"similar_tracks[%s-%s]: no result" % (artist, title)) return except Exception, e: self._logger.error(e) self._logger.info(u"similar_tracks[%s-%s]: no result" % (artist, title)) return
class EchoNest(Worker): _title = 'echonest' _key = None # wait this amount of seconds between lookups _lookup_threshold = 10 _last_lookup = None _history_filename = None _artist_history = {} _track_history = {} _db = None def __init__(self, config, no_cache=False): Worker.__init__(self) self._key = config.get('EchoNest', 'key', None) en_config.ECHO_NEST_API_KEY = self._key self._db = DB(config.get('EchoNest', 'path', join(config.configdir(), 'echonest.db'))) self._db.execute( u"CREATE TABLE IF NOT EXISTS artist_lookup "\ "(artist text, timestamp integer, "\ "PRIMARY KEY(artist))") self._db.execute( u"CREATE TABLE IF NOT EXISTS track_lookup "\ "(artist text, title text, timestamp integer, "\ "PRIMARY KEY(artist, title))") self._db.commit() def get_artist_timestamp(self, artist): self._db.execute( u"SELECT timestamp FROM artist_lookup "\ "WHERE artist=?", (artist,)) row = self._db.fetchone() if row: return row[0] return 0 def set_artist_timestamp(self, artist, timestamp): self._db.execute( u"REPLACE INTO artist_lookup (artist, timestamp) "\ "VALUES (?, ?)", (artist, timestamp)) self._db.commit() def get_track_timestamp(self, artist, title): self._db.execute( u"SELECT timestamp FROM track_lookup "\ "WHERE artist=? and title=?", (artist, title)) row = self._db.fetchone() if row: return row[0] return 0 def set_track_timestamp(self, artist, title, timestamp): self._db.execute( u"REPLACE INTO track_lookup (artist, title, timestamp) "\ "VALUES (?, ?, ?)", (artist, title, timestamp)) self._db.commit() def _delay(self): if self._last_lookup: last_lookup = (datetime.utcnow() - self._last_lookup) if last_lookup.seconds < self._lookup_threshold: self._logger.debug(u"sleeping %ss" % ( self._lookup_threshold - last_lookup.seconds)) sleep(self._lookup_threshold - last_lookup.seconds) self._last_lookup = datetime.utcnow() def similar_tracks(self, callback, artist, title, threshold): self.queue_callback(self._similar_tracks, callback, artist, title, threshold) def similar_tracks_low(self, callback, artist, title, threshold): self.queue_callback_low(self._similar_tracks, callback, artist, title, threshold) def _similar_tracks(self, callback, artist, title, threshold): timestamp = now() diff = timestamp - self.get_track_timestamp(artist, title) if diff < threshold: self._logger.debug(u"similar_tracks[%s-%s]: looked up %d seconds ago" % (artist, title, diff)) return self.set_track_timestamp(artist, title, timestamp) try: self._logger.debug(u"similar_tracks[%s-%s]: lookup" % (artist, title)) self._delay() a = en_song.search(title=title, artist=artist) try: p = en_playlist.static(type='song-radio', song_id=a[0].id, results=100) i = 100.0 self._logger.info(u"similar_tracks[%s-%s]: %d result(s)" % (artist, title, len(p))) for song in p: callback(artist, title, song.artist_name.lower(), song.title.lower(), i / 100.0, self._title) i -= 1.0 except IndexError: self._logger.info(u"similar_tracks[%s-%s]: no result" % (artist, title)) return except Exception, e: self._logger.error(e) self._logger.info(u"similar_tracks[%s-%s]: no result" % (artist, title)) return