def login(self): config = ConfigParser.ConfigParser() cwd = os.path.realpath(os.path.dirname(__file__) + u'/..') config.read(os.path.join(cwd, u'scrobbler.cfg')) username = config.get(u'scrobbler', u'username') password = hashlib.md5(config.get(u'scrobbler', u'password')).hexdigest() try: scrobbler.login(user=username, password=password) except scrobbler.ProtocolError: time.sleep(49) except Exception as e: log.exception(u"Couldn't login: %s" % e)
def osc_creds(self): if (not hasattr(self, 'username') or not hasattr(self, 'password')): return try: scrobbler.login(self.username, self.password, hashpw=True) except scrobbler.AuthError: self.l.error('Couldn\'t authenticate with last.fm') self.authenticated = False return self.authenticated = True
def main(): import sys, os import plistlib from time import strftime # get modus operandi and additional arguments mode = None try: mode = sys.argv[1] except: mode = 'scrobble' if mode not in ('update', 'scrobble'): exit(__doc__) # load internal database dbPath = 'itunesScrobbler.sqlite3' print 'loading internal database...' db = openDatabase(dbPath) # load itunes media library print 'loading iTunes Media Library...' mediaLibPath = os.path.join(os.path.expanduser('~'), 'Music', 'iTunes', 'iTunes Music Library.xml') mediaLib = plistlib.readPlist(mediaLibPath) # synchronize libraries tracks = mediaLib['Tracks'] tracksToScrobble = [] print 'synchronizing databases...' for trackId, track in tracks.iteritems(): try: if mode == 'update': updateDatabaseWithTrack(db, track) # gather scrobble data elif mode == 'scrobble': try: count = playCountDiffWithDatabaseForTrack(db, track) except ValueError, e: print 'Warning!', e.message else: if count: tracksToScrobble.append((count, track)) except KeyError: pass # process gathered information if mode == 'update': print 'done! - internal database updated.' elif mode == 'scrobble': if not tracksToScrobble: print 'done! - nothing changed; nothing to scrobble.' else: # sort tracks tracksToScrobble.sort(key=lambda t:(t[1]['Artist']+t[1]['Name']).lower()) # fix tracks' play time fauxPlayTime = datetime.now() # could be any datetime instance, like datetime(2012,1,1) patchAll = False for count, track in tracksToScrobble: if patchAll or 'Play Date UTC' not in track: track['Play Date UTC'] = fauxPlayTime trackLength = track.get('Total Time', 0) // 1000 fauxPlayTime = dateTimeWithOffsetFromDateTime(-count * trackLength, fauxPlayTime) # print what we want to scrobble print print 'This is what we\'ll send to last.fm:' print for count, track in tracksToScrobble: playDate = strftime('%Y-%m-%d %H:%M', track['Play Date UTC'].timetuple()) print count, ('x %(Artist)s - %(Name)s' % track).encode('unicode-escape'), ('(%s)' % playDate) print okay = raw_input('is this okay with you? (y/N) ') if okay != 'y': print 'alright, let\'s forget about it.' else: # try to load username and password and log in with open('.itunesScrobbler') as fd: username = fd.readline().rstrip('\r\n') password = fd.readline().rstrip('\r\n') print 'trying to log in to last.fm...' scrobbler.login(username, password) # scrobble! print 'scrobble ...', for count, track in tracksToScrobble: trackDescription = ('%(Name)s by %(Artist)s' % track).encode('unicode-escape') if len(trackDescription) > 69: trackDescription = trackDescription[:67] + '..' print '\rscrobble', trackDescription, for i in xrange(count): # need to compensate; we only know when the track was *last* played if i is 0: fixedTrack = track else: trackLength = track.get('Total Time', 0) // 1000 fixedTrack = track.copy() fixedTrack['Play Date UTC'] = dateTimeWithOffsetFromDateTime(-i * trackLength, track['Play Date UTC']) # send the fixed track information off to last.fm if not scrobble(fixedTrack): print raise scrobbler.PostError('could not scrobble!') updateDatabaseWithTrack(db, track) if not scrobbler.flush(): # Damn! Something went wrong right at the end. # We could roll back our internal database now, which could lead to duplicate scrobbles, # or we could just ignore this error, which could/will lead to tracks not being scrobbled at all; # both scenarios suck donkey dick! print 'b0rked hard; so sorry :f - you just lost some scrobbles due to bad caching.' else: print print 'all done! :)' db.commit() db.close()
def _real_commit(self, now_playing, cachefile, username, password, scrobbler_url): """this is quite ugly spaghetti code. maybe we could make this a little bit more tidy?""" logger.info('Begin scrobbling to %s', scrobbler_url) if (not do_now_playing): logger.debug('Now playing disabled') now_playing = None success = False tosubmit = set() tosubmitted = set() cache_count = 0 retry_sleep = None retry_count = 0 while not success: if retry_sleep is None: retry_sleep = 60 else: retry_count = retry_count + 1 if retry_count > 7: logger.info('Giving up scrobbling to %s', scrobbler_url) break logger.info('Sleeping %d minute(s)', retry_sleep / 60) time.sleep(retry_sleep) retry_sleep = min(retry_sleep * 2, 120 * 60) #handshake phase logger.debug('Handshake') try: scrobbler.login(username, password, hashpw=False, client=CmuScrobbler.CLIENTID, url=scrobbler_url) except Exception, e: logger.error('Handshake with %s failed: %s', scrobbler_url, e) log_traceback(e) continue #submit phase if os.path.exists(cachefile): logger.info('Scrobbling songs to %s', scrobbler_url) (_, _, _, _, _, _, _, _, mtime, _) = os.stat(cachefile) fo = file(cachefile, 'r') line = fo.readline() while len(line) > 0: (path, artist, track, playtime, source, length, album, trackno) = line.split('\t') trackno = trackno.strip() mbid = get_mbid(unquote(path).decode('utf-8')) tosubmit.add((playtime, artist, track, source, length, album, trackno, mbid)) line = fo.readline() fo.close() logger.info('Read %d songs from cachefile %s', len(tosubmit), cachefile) logger.debug('Sorting songlist') submitlist = list(tosubmit) submitlist.sort(key=lambda x: int(x[0])) retry = False for (playtime, artist, track, source, length, album, trackno, mbid) in submitlist: if (playtime, artist, track, source, length, album, trackno, mbid) in tosubmitted: logger.debug( 'Track already submitted or in cache: %s - %s', unquote(artist), unquote(track)) continue if cache_count >= 3: logger.info('Flushing. cache_count=%d', cache_count) if self._flush(): logger.info('Flush successful.') retry_sleep = None cache_count = 0 else: retry = True break sb_success = False for tries in xrange(1, 4): logger.debug( 'Try to submit: %s, %s, playtime=%d, source=%s, length=%s, album=%s, trackno=%s, mbid=%s', unquote(artist), unquote(track), int(playtime), source, length, unquote(album), trackno, mbid) try: sb_success = scrobbler.submit( unquote(artist).decode('utf-8'), unquote(track).decode('utf-8'), int(playtime), source=source.decode('utf-8'), length=length.decode('utf-8'), album=unquote(album).decode('utf-8'), trackno=trackno.decode('utf-8'), mbid=mbid, ) except Exception, e: logger.error('Submit error: %s', e) log_traceback(e) sb_success = False if sb_success: tosubmitted.add((playtime, artist, track, source, length, album, trackno, mbid)) cache_count += 1 logger.info('Submitted. cache_count=%d: %s - %s', cache_count, unquote(artist), unquote(track)) break logger.error('Submit failed. Try %d', tries) if not sb_success: retry = True break if cache_count >= 3: logger.info('Flushing. cache_count=%d', cache_count) if self._flush(): logger.info('Flush successful.') retry_sleep = None cache_count = 0 else: retry = True break if retry: logger.error('Restaring') continue if cache_count > 0: logger.info('Cache not empty: flushing') if self._flush(): logger.info('Flush successful.') retry_sleep = None cache_count = 0 else: logger.error('Restarting') continue (_, _, _, _, _, _, _, _, newmtime, _) = os.stat(cachefile) if newmtime != mtime: logger.info( 'Cachefile changed since we started. Restarting') continue logger.info('Scrobbled all Songs, removing cachefile') os.remove(cachefile)
def _real_commit(self, now_playing, cachefile, username, password, scrobbler_url): """this is quite ugly spaghetti code. maybe we could make this a little bit more tidy?""" logger.info('Begin scrobbling to %s', scrobbler_url) if (not do_now_playing): logger.debug('Now playing disabled') now_playing = None success = False tosubmit = set() tosubmitted = set() cache_count = 0 retry_sleep = None retry_count = 0 while not success: if retry_sleep is None: retry_sleep = 60 else: retry_count = retry_count + 1 if retry_count > 7: logger.info('Giving up scrobbling to %s', scrobbler_url) break logger.info('Sleeping %d minute(s)', retry_sleep / 60) time.sleep(retry_sleep) retry_sleep = min(retry_sleep * 2, 120 * 60) #handshake phase logger.debug('Handshake') try: scrobbler.login(username, password, hashpw=False, client=CmuScrobbler.CLIENTID, url=scrobbler_url) except Exception, e: logger.error('Handshake with %s failed: %s', scrobbler_url, e) log_traceback(e) continue #submit phase if os.path.exists(cachefile): logger.info('Scrobbling songs to %s', scrobbler_url) (_, _, _, _, _, _, _, _, mtime, _) = os.stat(cachefile) fo = file(cachefile,'r') line = fo.readline() while len(line) > 0: try: (path, artist, track, playtime, source, length, album, trackno) = line.split('\t') trackno = trackno.strip() mbid = get_mbid(unquote(path).decode('utf-8')) tosubmit.add((playtime, artist, track, source, length, album, trackno, mbid)) except Exception, e: logger.debug('cache read error: %s', e) line = fo.readline() fo.close() logger.info('Read %d songs from cachefile %s', len(tosubmit), cachefile) logger.debug('Sorting songlist') submitlist = list(tosubmit) submitlist.sort(key=lambda x: int(x[0])) retry = False for (playtime, artist, track, source, length, album, trackno, mbid) in submitlist: if (playtime, artist, track, source, length, album, trackno, mbid) in tosubmitted: logger.debug('Track already submitted or in cache: %s - %s', unquote(artist), unquote(track)) continue if cache_count >= 3: logger.info('Flushing. cache_count=%d', cache_count) if self._flush(): logger.info('Flush successful.') retry_sleep = None cache_count = 0 else: retry = True break sb_success = False for tries in xrange(1, 4): logger.debug('Try to submit: %s, %s, playtime=%d, source=%s, length=%s, album=%s, trackno=%s, mbid=%s', unquote(artist), unquote(track), int(playtime), source, length, unquote(album), trackno, mbid) try: sb_success = scrobbler.submit(unquote(artist).decode('utf-8'), unquote(track).decode('utf-8'), int(playtime), source=source.decode('utf-8'), length=length.decode('utf-8'), album=unquote(album).decode('utf-8'), trackno=trackno.decode('utf-8'), mbid=mbid, ) except Exception, e: logger.error('Submit error: %s', e) log_traceback(e) sb_success = False if sb_success: tosubmitted.add((playtime, artist, track, source, length, album, trackno, mbid)) cache_count += 1 logger.info('Submitted. cache_count=%d: %s - %s', cache_count, unquote(artist), unquote(track)) break logger.error('Submit failed. Try %d', tries) if not sb_success: retry = True break if cache_count >= 3: logger.info('Flushing. cache_count=%d', cache_count) if self._flush(): logger.info('Flush successful.') retry_sleep = None cache_count = 0 else: retry = True break
def lastfm_login(): try: scrobbler.login(USERNAME, PASSWORD, True) except: pass