def __init__(self, irc): self.__parent = super(LastFM, self) self.__parent.__init__(irc) self.db = LastFMDB(dbfilename) world.flushers.append(self.db.flush) self.APIKEY = self.registryValue("apiKey") self.APIURL = "http://ws.audioscrobbler.com/2.0/?api_key=%s&" % self.APIKEY
def __init__(self, irc): self.__parent = super(LastFM, self) self.__parent.__init__(irc) self.db = LastFMDB(dbfilename) world.flushers.append(self.db.flush)
class LastFM(callbacks.Plugin): # 1.0 API (deprecated) APIURL_1_0 = "http://ws.audioscrobbler.com/1.0/user" # 2.0 API (see http://www.lastfm.de/api/intro) APIKEY = "b7638a70725eea60737f9ad9f56f3099" APIURL_2_0 = "http://ws.audioscrobbler.com/2.0/?api_key=%s&" % APIKEY def __init__(self, irc): self.__parent = super(LastFM, self) self.__parent.__init__(irc) self.db = LastFMDB(dbfilename) world.flushers.append(self.db.flush) def die(self): if self.db.flush in world.flushers: world.flushers.remove(self.db.flush) self.db.close() self.__parent.die() def lastfm(self, irc, msg, args, method, optionalId): """<method> [<id>] Lists LastFM info where <method> is in [friends, neighbours, profile, recenttracks, tags, topalbums, topartists, toptracks]. Set your LastFM ID with the set method (default is your current nick) or specify <id> to switch for one call. """ id = (optionalId or self.db.getId(msg.nick) or msg.nick) channel = msg.args[0] maxResults = self.registryValue("maxResults", channel) method = method.lower() url = "%s/%s/%s.txt" % (self.APIURL_1_0, id, method) try: f = urllib2.urlopen(url) except urllib2.HTTPError: irc.error("Unknown ID (%s) or unknown method (%s)" % (msg.nick, method)) return lines = f.read().split("\n") content = map(lambda s: s.split(",")[-1], lines) irc.reply("%s's %s: %s (with a total number of %i entries)" % (id, method, ", ".join(content[0:maxResults]), len(content))) lastfm = wrap(lastfm, ["something", optional("something")]) def nowPlaying(self, irc, msg, args, optionalId): """[<id>] Announces the now playing track of the specified LastFM ID. Set your LastFM ID with the set method (default is your current nick) or specify <id> to switch for one call. """ id = (optionalId or self.db.getId(msg.nick) or msg.nick) # see http://www.lastfm.de/api/show/user.getrecenttracks url = "%s&method=user.getrecenttracks&user=%s" % (self.APIURL_2_0, id) try: f = urllib2.urlopen(url) except urllib2.HTTPError: irc.error("Unknown ID (%s)" % id) return xml = minidom.parse(f).getElementsByTagName("recenttracks")[0] user = xml.getAttribute("user") t = xml.getElementsByTagName("track")[0] # most recent track isNowplaying = (t.getAttribute("nowplaying") == "true") artist = t.getElementsByTagName("artist")[0].firstChild.data track = t.getElementsByTagName("name")[0].firstChild.data try: album = "["+t.getElementsByTagName("album")[0].firstChild.data+"]" except IndexError: album = "" if isNowplaying: irc.reply(('%s is listening to "%s" by %s %s' % (user, track, artist, album)).encode("utf8")) else: time = int(t.getElementsByTagName("date")[0].getAttribute("uts")) irc.reply(('%s listened to "%s" by %s %s more than %s' % (user, track, artist, album, self._formatTimeago(time))).encode("utf-8")) np = wrap(nowPlaying, [optional("something")]) def setUserId(self, irc, msg, args, newId): """<id> Sets the LastFM ID for the caller and saves it in a database. """ self.db.set(msg.nick, newId) irc.reply("LastFM ID changed.") self.profile(irc, msg, args) set = wrap(setUserId, ["something"]) def profile(self, irc, msg, args, optionalId): """[<id>] Prints the profile info for the specified LastFM ID. Set your LastFM ID with the set method (default is your current nick) or specify <id> to switch for one call. """ id = (optionalId or self.db.getId(msg.nick) or msg.nick) url = "%s/%s/profile.xml" % (self.APIURL_1_0, id) try: f = urllib2.urlopen(url) except urllib2.HTTPError: irc.error("Unknown user (%s)" % id) return xml = minidom.parse(f).getElementsByTagName("profile")[0] keys = "realname registered age gender country playcount".split() profile = tuple([self._parse(xml, node) for node in keys]) irc.reply(("%s (realname: %s) registered on %s; age: %s / %s; \ Country: %s; Tracks played: %s" % ((id,) + profile)).encode("utf8")) profile = wrap(profile, [optional("something")]) def compareUsers(self, irc, msg, args, user1, optionalUser2): """user1 [<user2>] Compares the taste from two users If <user2> is ommitted, the taste is compared against the ID of the calling user. """ user2 = (optionalUser2 or self.db.getId(msg.nick) or msg.nick) channel = msg.args[0] maxResults = self.registryValue("maxResults", channel) # see http://www.lastfm.de/api/show/tasteometer.compare url = "%s&method=tasteometer.compare&type1=user&type2=user&value1=%s&value2=%s&limit=%s" % ( self.APIURL_2_0, user1, user2, maxResults ) try: f = urllib2.urlopen(url) except urllib2.HTTPError, e: irc.error("Failure: %s" % (e)) return xml = minidom.parse(f) resultNode = xml.getElementsByTagName("result")[0] score = float(self._parse(resultNode, "score")) scoreStr = "%s (%s)" % (round(score, 2), self._formatRating(score)) # Note: XPath would be really cool here... artists = [el for el in resultNode.getElementsByTagName("artist")] artistNames = [el.getElementsByTagName("name")[0].firstChild.data for el in artists] irc.reply(("Result of comparison between %s and %s: score: %s, common artists: %s" \ % (user1, user2, scoreStr, ", ".join(artistNames)) ).encode("utf-8") )
class LastFM(callbacks.Plugin): # {{{ vars BASEURL = "http://ws.audioscrobbler.com/1.0/user" APIKEY = "" # FIXME: Get own key APIURL = "" # }}} # {{{ system functions def __init__(self, irc): self.__parent = super(LastFM, self) self.__parent.__init__(irc) self.db = LastFMDB(dbfilename) world.flushers.append(self.db.flush) self.APIKEY = self.registryValue("apiKey") self.APIURL = "http://ws.audioscrobbler.com/2.0/?api_key=%s&" % self.APIKEY def die(self): if self.db.flush in world.flushers: world.flushers.remove(self.db.flush) self.db.close() self.__parent.die() # }}} # {{{ lastfm def lastfm(self, irc, msg, args, method, optionalId): """<method> [<id>] Lists LastFM info where <method> is in [friends, neighbours, profile, recenttracks, tags, topalbums, topartists, toptracks]. Set your LastFM ID with the set method (default is your current nick) or specify <id> to switch for one call. """ id = (optionalId or self.db.getId(msg.nick) or msg.nick) channel = msg.args[0] maxResults = self.registryValue("maxResults", channel) method = method.lower() try: f = urlopen("%s/%s/%s.txt" % (self.BASEURL, id, method)) except HTTPError: irc.error("Unknown ID (%s) or unknown method (%s)" % (msg.nick, method)) return lines = f.read().split("\n") content = map(lambda s: s.split(",")[-1], lines) irc.reply("%s's %s: %s (with a total number of %i entries)" % (id, method, ", ".join(content[0:maxResults]), len(content))) lastfm = wrap(lastfm, ["something", optional("something")]) # }}} # {{{ np def np(self, irc, msg, args, optionalId): """[<id>] Announces the now playing track of the specified LastFM ID. Set your LastFM ID with the set method (default is your current nick) or specify <id> to switch for one call. """ id = (self.db.getId(optionalId) or optionalId or self.db.getId(msg.nick) or msg.nick) channel = msg.args[0] showColours = self.registryValue("showColours", channel) trackInfo = self.registryValue("showTrackInfo", channel) showTags = self.registryValue("showTags", channel) getYear = True try: f = urlopen("%s&method=user.getrecenttracks&user=%s" % (self.APIURL, id)) except (HTTPError) as e: irc.error("Unknown ID (%s)! Also, \"%s\"" % (id,e)) return try: xml = minidom.parse(f).getElementsByTagName("recenttracks")[0] except IndexError: irc.error("Something broke, or you ain't listened to any tracks lol.") return user = xml.getAttribute("user") try: t = xml.getElementsByTagName("track")[0] # most recent track except IndexError,e: irc.error("No tracks or something for %s lol or maybe it's \"%s\"" % (id,e)) return isNowplaying = (t.getAttribute("nowplaying") == "true") artist = t.getElementsByTagName("artist")[0].firstChild.data track = t.getElementsByTagName("name")[0].firstChild.data try: theAlbum = t.getElementsByTagName("album")[0].firstChild.data album = u" [{0}]".format(theAlbum) except AttributeError: album = "" getYear = False artist2 = quote_plus(artist.encode("utf8")) track2 = quote_plus(track.encode("utf8")) # Play count and shit try: herp = urlopen("%s&method=track.getInfo&username=%s&artist=%s&track=%s" % (self.APIURL, id, artist2, track2)) playinfo = minidom.parse(herp).getElementsByTagName("track")[0] playcount = playinfo.getElementsByTagName("playcount")[0].firstChild.data listenercount = playinfo.getElementsByTagName("listeners")[0].firstChild.data userloved = playinfo.getElementsByTagName("userloved")[0].firstChild.data except (IndexError, HTTPError,AttributeError): trackInfo = False try: userplaycount = playinfo.getElementsByTagName("userplaycount")[0].firstChild.data except IndexError: userplaycount = 0 if getYear: try: albuminfox = urlopen(u"{0}&method=album.getinfo&artist={1}&album={2}".format(self.APIURL, artist2, theAlbum)) albuminfo = minidom.parse(albuminfox).getElementsByTagName("album")[0] releasedate = albuminfo.getElementsByTagName("releasedate")[0].firstChild.data releasedate = releasedate.split(' ')[6].split(',')[0] album = " [{0} ~{1}~]".format(theAlbum,releasedate) except (IndexError, HTTPError,BadStatusLine,UnicodeEncodeError): releasedate = "" # tags tags = [] #if album != "": #thetags = urlopen("%s&method=album.getTopTags&artist=%s&album=%s&autocorrect=1" #% ( self.APIURL,artist2,quote_plus(t.getElementsByTagName("album")[0].firstChild.data))) #else: if True: try: thetags = urlopen("{0}&method=artist.getTopTags&artist={1}".format(self.APIURL,artist2)) toptags = minidom.parse(thetags).getElementsByTagName("toptags")[0] except IndexError: toptags = [] for item in range(3): try: tags.append(toptags.getElementsByTagName("tag")[item].getElementsByTagName("name")[0].firstChild.data) except IndexError: break if len(tags) == 0: isTagged = False else: isTagged = True if showColours: if isNowplaying: output = ('\x038%s\x03 is listening to "\x0310%s\x03" by \x0312%s\x0313%s\x03' % (user, track, artist, album)).encode("utf8") else: time = int(t.getElementsByTagName("date")[0].getAttribute("uts")) output = ('\x038%s\x03 listened to "\x0310%s\x03" by \x0312%s\x0313%s\x03 about \x0315%s\x03' % (user, track, artist, album, self._formatTimeago(time))).encode("utf8") if trackInfo == True: if userloved == "1": output += (' \x035%s\x03. %s plays by \x038%s\x03, %s plays by %s listeners.' % (u'♥', userplaycount, user, playcount, listenercount)).encode("utf8") else: output += ('. %s plays by \x038%s\x03, %s plays by %s listeners.' % (userplaycount, user, playcount, listenercount)).encode("utf8") if showTags == True: if isTagged == True: output += " (" for i,item in enumerate(tags): output += ("\x0307%s\x03" % item).encode("utf8") if i != (len(tags)-1): output += ", " output += ")" else: output += (' (\x037%s\x03)' % ("no tags")).encode("utf8") else: if isNowplaying: output = ('%s is listening to "%s" by %s%s' % (user, track, artist, album)).encode("utf8") else: time = int(t.getElementsByTagName("date")[0].getAttribute("uts")) output = ('%s listened to "%s" by %s%s about %s' % (user, track, artist, album, self._formatTimeago(time))).encode("utf8") if trackInfo == True: if userloved == "1": output += (' %s. %s plays by %s, %s plays by %s listeners.' % (u'♥', userplaycount, user, playcount, listenercount)).encode("utf8") else: output += ('. %s plays by %s, %s plays by %s listeners.' % (userplaycount, user, playcount, listenercount)).encode("utf8") if showTags == True: if isTagged == True: output += " (" for i,item in enumerate(tags): output += ("%s" % item).encode("utf8") if i != (len(tags)-1): output += ", " output += ")" else: output += (' (%s)' % ("no tags")).encode("utf8") irc.reply(output)
class LastFM(callbacks.Plugin): # 1.0 API (deprecated) APIURL_1_0 = "http://ws.audioscrobbler.com/1.0/user" # 2.0 API (see http://www.lastfm.de/api/intro) APIKEY = "b7638a70725eea60737f9ad9f56f3099" APIURL_2_0 = "http://ws.audioscrobbler.com/2.0/?api_key=%s&" % APIKEY def __init__(self, irc): self.__parent = super(LastFM, self) self.__parent.__init__(irc) self.db = LastFMDB(dbfilename) world.flushers.append(self.db.flush) def die(self): if self.db.flush in world.flushers: world.flushers.remove(self.db.flush) self.db.close() self.__parent.die() def lastfm(self, irc, msg, args, method, optionalId): """<method> [<id>] Lists LastFM info where <method> is in [friends, neighbours, profile, recenttracks, tags, topalbums, topartists, toptracks]. Set your LastFM ID with the set method (default is your current nick) or specify <id> to switch for one call. """ id = (optionalId or self.db.getId(msg.nick) or msg.nick) channel = msg.args[0] maxResults = self.registryValue("maxResults", channel) method = method.lower() url = "%s/%s/%s.txt" % (self.APIURL_1_0, id, method) try: f = urllib2.urlopen(url) except urllib2.HTTPError: irc.error("Unknown ID (%s) or unknown method (%s)" % (msg.nick, method)) return lines = f.read().split("\n") content = map(lambda s: s.split(",")[-1], lines) irc.reply("%s's %s: %s (with a total number of %i entries)" % (id, method, ", ".join(content[0:maxResults]), len(content))) lastfm = wrap(lastfm, ["something", optional("something")]) def nowPlaying(self, irc, msg, args, optionalId): """[<id>] Announces the now playing track of the specified LastFM ID. Set your LastFM ID with the set method (default is your current nick) or specify <id> to switch for one call. """ id = (optionalId or self.db.getId(msg.nick) or msg.nick) # see http://www.lastfm.de/api/show/user.getrecenttracks url = "%s&method=user.getrecenttracks&user=%s" % (self.APIURL_2_0, id) try: f = urllib2.urlopen(url) except urllib2.HTTPError: irc.error("Unknown ID (%s)" % id) return parser = LastFMParser() (user, isNowPlaying, artist, track, album, time) = parser.parseRecentTracks(f) albumStr = "[" + album + "]" if album else "" if isNowPlaying: irc.reply(('%s is listening to "%s" by %s %s' % (user, track, artist, albumStr)).encode("utf8")) else: irc.reply(('%s listened to "%s" by %s %s more than %s' % (user, track, artist, albumStr, self._formatTimeago(time))).encode("utf-8")) np = wrap(nowPlaying, [optional("something")]) def setUserId(self, irc, msg, args, newId): """<id> Sets the LastFM ID for the caller and saves it in a database. """ self.db.set(msg.nick, newId) irc.reply("LastFM ID changed.") self.profile(irc, msg, args) set = wrap(setUserId, ["something"]) def profile(self, irc, msg, args, optionalId): """[<id>] Prints the profile info for the specified LastFM ID. Set your LastFM ID with the set method (default is your current nick) or specify <id> to switch for one call. """ id = (optionalId or self.db.getId(msg.nick) or msg.nick) url = "%s/%s/profile.xml" % (self.APIURL_1_0, id) try: f = urllib2.urlopen(url) except urllib2.HTTPError: irc.error("Unknown user (%s)" % id) return xml = minidom.parse(f).getElementsByTagName("profile")[0] keys = "realname registered age gender country playcount".split() profile = tuple([self._parse(xml, node) for node in keys]) irc.reply(("%s (realname: %s) registered on %s; age: %s / %s; \ Country: %s; Tracks played: %s" % ((id, ) + profile)).encode("utf8")) profile = wrap(profile, [optional("something")]) def compareUsers(self, irc, msg, args, user1, optionalUser2): """user1 [<user2>] Compares the taste from two users If <user2> is ommitted, the taste is compared against the ID of the calling user. """ user2 = (optionalUser2 or self.db.getId(msg.nick) or msg.nick) channel = msg.args[0] maxResults = self.registryValue("maxResults", channel) # see http://www.lastfm.de/api/show/tasteometer.compare url = "%s&method=tasteometer.compare&type1=user&type2=user&value1=%s&value2=%s&limit=%s" % ( self.APIURL_2_0, user1, user2, maxResults) try: f = urllib2.urlopen(url) except urllib2.HTTPError, e: irc.error("Failure: %s" % (e)) return xml = minidom.parse(f) resultNode = xml.getElementsByTagName("result")[0] score = float(self._parse(resultNode, "score")) scoreStr = "%s (%s)" % (round(score, 2), self._formatRating(score)) # Note: XPath would be really cool here... artists = [el for el in resultNode.getElementsByTagName("artist")] artistNames = [ el.getElementsByTagName("name")[0].firstChild.data for el in artists ] irc.reply(("Result of comparison between %s and %s: score: %s, common artists: %s" \ % (user1, user2, scoreStr, ", ".join(artistNames)) ).encode("utf-8") )
class LastFM(callbacks.Plugin): # 1.0 API (deprecated) APIURL_1_0 = "http://ws.audioscrobbler.com/1.0/user" # 2.0 API (see http://www.lastfm.de/api/intro) APIKEY = "fe777aa8d75991a017c59a6ec7ad5bdf" APIURL_2_0 = "http://ws.audioscrobbler.com/2.0/?api_key=%s&" % APIKEY def __init__(self, irc): self.__parent = super(LastFM, self) self.__parent.__init__(irc) self.db = LastFMDB(dbfilename) world.flushers.append(self.db.flush) def die(self): if self.db.flush in world.flushers: world.flushers.remove(self.db.flush) self.db.close() self.__parent.die() def lastfm(self, irc, msg, args, method, optionalId): """<method> [<id>] Lists LastFM info where <method> is in [friends, neighbours, profile, recenttracks, tags, topalbums, topartists, toptracks]. Set your LastFM ID with the set method (default is your current nick) or specify <id> to switch for one call. """ id = (self.db.getId(msg.nick) or msg.nick) if optionalId: id = (self.db.getId(optionalId) or optionalId) channel = msg.args[0] maxResults = self.registryValue("maxResults", channel) method = method.lower() url = "%s/%s/%s.txt" % (self.APIURL_1_0, id, method) try: f = urllib2.urlopen(url) except urllib2.HTTPError: irc.error("Unknown ID (%s) or unknown method (%s)" % (msg.nick, method)) return lines = f.read().split("\n") content = map(lambda s: s.split(",")[-1], lines) irc.reply("%s's %s: %s (with a total number of %i entries)" % (id, method, ", ".join(content[0:maxResults]), len(content))) lastfm = wrap(lastfm, ["something", optional("something")]) def nowPlaying(self, irc, msg, args, optionalId): """[<id>] Announces the now playing track of the specified LastFM ID. Set your LastFM ID with the set method (default is your current nick) or specify <id> to switch for one call. """ nick = msg.nick id = (self.db.getId(nick) or nick) user = nick channel = None if optionalId: if optionalId[0] == "#": channel = optionalId else: id = (self.db.getId(optionalId) or optionalId) user = optionalId # see http://www.lastfm.de/api/show/user.getrecenttracks url = "%s&method=user.getrecenttracks&user=%s" % (self.APIURL_2_0, id) try: f = urllib2.urlopen(url) except urllib2.HTTPError: irc.error("Unknown ID (%s)" % id) return parser = LastFMParser() (username, isNowPlaying, artist, track, album, time) = parser.parseRecentTracks(f) # extra API call to get: listeners, playcount, user playcount, user loved (0/1 toggle), track tags # doc: http://www.last.fm/api/show/track.getInfo try: params = urllib.urlencode({'username': id.encode("utf8"), 'track': track.encode("utf8"), 'artist': artist.encode("utf8")}) urlTwo = "%smethod=track.getInfo&%s" % (self.APIURL_2_0, params) fTwo = urllib2.urlopen(urlTwo) except urllib2.HTTPError: irc.error("Error getting now playing track infomation for %s" % id) (listeners, playcount, usercount, userloved, tags) = parser.parseTrackInformation(fTwo) replyStr = self._formatNowPlaying(user, id, track.encode("utf8"), artist.encode("utf8"), album, usercount, playcount, listeners, userloved, isNowPlaying) tagStr = self._formatTags(tags).encode("utf8") if channel == None: irc.reply(replyStr + tagStr) else: irc.queueMsg(ircmsgs.privmsg(channel, replyStr + tagStr)) irc.noReply() np = wrap(nowPlaying, [optional("something")]) def setUserId(self, irc, msg, args, newId): """<id> Sets the LastFM ID for the caller and saves it in a database. """ self.db.set(msg.nick, newId) irc.reply("LastFM ID changed.") self.profile(irc, msg, args) set = wrap(setUserId, ["something"]) def profile(self, irc, msg, args, optionalId): """[<id>] Prints the profile info for the specified LastFM ID. Set your LastFM ID with the set method (default is your current nick) or specify <id> to switch for one call. """ id = (self.db.getId(msg.nick) or msg.nick) user = msg.nick if optionalId: id = (self.db.getId(optionalId) or optionalId) user = optionalId url = "%s/%s/profile.xml" % (self.APIURL_1_0, id) try: f = urllib2.urlopen(url) except urllib2.HTTPError: irc.error("Unknown user (%s)" % id) return xml = minidom.parse(f).getElementsByTagName("profile")[0] keys = "realname registered playcount".split() profile = tuple([self._parse(xml, node) for node in keys]) irc.reply(("%s (realname: %s) joined Last.FM on %s. Total tracks played: %s. [http://last.fm/user/%s]" % ((user,) + profile + (id,))).encode("utf8")) profile = wrap(profile, [optional("something")]) def compareUsers(self, irc, msg, args, user1, optionalUser2): """user1 [<user2>] Compares the taste from two users If <user2> is ommitted, the taste is compared against the ID of the calling user. """ name1 = user1 name2 = msg.nick user2 = (self.db.getId(msg.nick) or msg.nick) if optionalUser2: name2 = optionalUser2 user2 = (self.db.getId(optionalUser2) or optionalUser2) if self.db.getId(user1): user1 = self.db.getId(user1) channel = msg.args[0] maxResults = self.registryValue("maxResults", channel) # see http://www.lastfm.de/api/show/tasteometer.compare url = "%s&method=tasteometer.compare&type1=user&type2=user&value1=%s&value2=%s&limit=%s" % ( self.APIURL_2_0, user1, user2, maxResults ) try: f = urllib2.urlopen(url) except urllib2.HTTPError, e: irc.error("Failure: %s" % (e)) return xml = minidom.parse(f) resultNode = xml.getElementsByTagName("result")[0] score = float(self._parse(resultNode, "score")) scoreStr = "%s (%s)" % (int(round(score, 2) * 100), self._formatRating(score)) # Note: XPath would be really cool here... artists = [el for el in resultNode.getElementsByTagName("artist")] artistNames = [el.getElementsByTagName("name")[0].firstChild.data for el in artists] irc.reply(("Result of comparison between %s (%s) and %s (%s): score: %s, common artists: %s" \ % (name1, user1, name2, user2, scoreStr, ", ".join(artistNames)) ).encode("utf-8") )