Skip to content

Commit 009e34d

Browse files
committed
Cleaned up np and compare. Added additional commands
1 parent 122b13f commit 009e34d

1 file changed

Lines changed: 259 additions & 17 deletions

File tree

plugins/lastfm.py

Lines changed: 259 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,46 @@
33
import requests
44
import random
55

6+
from sqlalchemy import Table, Column, PrimaryKeyConstraint, String
7+
68
from cloudbot import hook
7-
from cloudbot.util import timeformat
9+
from cloudbot.util import timeformat, web, botvars
810

911
api_url = "http://ws.audioscrobbler.com/2.0/?format=json"
1012

13+
table = Table(
14+
"lastfm",
15+
botvars.metadata,
16+
Column('nick', String),
17+
Column('acc', String),
18+
PrimaryKeyConstraint('nick')
19+
)
20+
21+
22+
@hook.on_start()
23+
def load_cache(db):
24+
"""
25+
:type db: sqlalchemy.orm.Session
26+
"""
27+
global last_cache
28+
last_cache = []
29+
for row in db.execute(table.select()):
30+
nick = row["nick"]
31+
account = row["acc"]
32+
last_cache.append((nick, account))
33+
34+
35+
def get_account(nick):
36+
"""looks in last_cache for the lastfm account name"""
37+
last_account = [row[1] for row in last_cache if nick.lower() == row[0]]
38+
if not last_account:
39+
return
40+
else:
41+
last_account = last_account[0]
42+
return last_account
43+
1144

12-
@hook.command("lastfm", "last", "lfm", "l", autohelp=False)
45+
@hook.command("lastfm", "np", "l", autohelp=False)
1346
def lastfm(text, nick, db, bot, notice):
1447
"""[user] [dontsave] - displays the now playing (or last played) track of LastFM user [user]"""
1548
api_key = bot.config.get("api_keys", {}).get("lastfm")
@@ -23,17 +56,14 @@ def lastfm(text, nick, db, bot, notice):
2356
else:
2457
user = text
2558

26-
db.execute("create table if not exists lastfm(nick primary key, acc)")
27-
2859
if not user:
29-
user = db.execute("select acc from lastfm where nick=lower(:nick)",
30-
{'nick': nick}).fetchone()
60+
user = get_account(nick)
3161
if not user:
3262
notice(lastfm.__doc__)
3363
return
34-
user = user[0]
3564

36-
params = {'method': 'user.getrecenttracks', 'api_key': api_key, 'user': user, 'limit': 1}
65+
params = {'method': 'user.getrecenttracks',
66+
'api_key': api_key, 'user': user, 'limit': 1}
3767
request = requests.get(api_url, params=params)
3868

3969
if request.status_code != requests.codes.ok:
@@ -71,12 +101,15 @@ def lastfm(text, nick, db, bot, notice):
71101
title = track["name"]
72102
album = track["album"]["#text"]
73103
artist = track["artist"]["#text"]
104+
url = web.try_shorten(track["url"])
74105

75106
out = '{} {} "{}"'.format(user, status, title)
76107
if artist:
77108
out += " by \x02{}\x0f".format(artist)
78109
if album:
79110
out += " from the album \x02{}\x0f".format(album)
111+
if url:
112+
out += " {}".format(url)
80113

81114
# append ending based on what type it was
82115
out += ending
@@ -85,18 +118,31 @@ def lastfm(text, nick, db, bot, notice):
85118
db.execute("insert or replace into lastfm(nick, acc) values (:nick, :account)",
86119
{'nick': nick.lower(), 'account': user})
87120
db.commit()
88-
121+
load_cache(db)
89122
return out
90123

91124

92-
@hook.command("lastfmcompare", "compare")
93-
def lastfmcompare(text, bot):
94-
"""<user1> <user2> - compare the music compatibility of two LastFM users"""
125+
@hook.command("lastfmcompare", "compare", "lc")
126+
def lastfmcompare(text, nick, bot, db):
127+
"""[user] ([user] optional) - displays the now playing (or last played) track of LastFM user [user]"""
95128
api_key = bot.config.get("api_keys", {}).get("lastfm")
96129
if not api_key:
97130
return "No last.fm API key set."
131+
if not text:
132+
return("please specify a lastfm username to compare")
133+
try:
134+
user1, user2 = text.split()
135+
except:
136+
user2 = text
137+
user1 = nick
138+
139+
user2_check = get_account(user2)
140+
if user2_check:
141+
user2 = user2_check
98142

99-
user1, user2 = text.split()
143+
user1_check = get_account(user1)
144+
if user1_check:
145+
user1 = user1_check
100146

101147
params = {
102148
'method': 'tasteometer.compare',
@@ -112,8 +158,13 @@ def lastfmcompare(text, bot):
112158
return "Failed to fetch info ({})".format(request.status_code)
113159

114160
data = request.json()
161+
if 'error' in data:
162+
return "Error: {}.".format(data["message"])
115163

116-
score = int(float(data["comparison"]["result"]["score"]) * 100)
164+
score = float(data["comparison"]["result"]["score"])
165+
score = float("{:.3f}".format(score * 100))
166+
if score == 0:
167+
return "{} and {} have no common listening history.".format(user2, user1)
117168
level = "Super" if score > 95 else "Very High" if score > 80 else "High" if score > 60 else \
118169
"Medium" if score > 40 else "Low" if score > 10 else "Very Low"
119170

@@ -122,7 +173,198 @@ def lastfmcompare(text, bot):
122173
type(data["comparison"]["result"]["artists"]["artist"]) == list else \
123174
[data["comparison"]["result"]["artists"]["artist"]["name"]] if "artist" \
124175
in data["comparison"]["result"]["artists"] else ""
125-
artist_string = "\x02In Common:\x02 " + ", ".join(artists) if artists else ""
176+
artist_string = "\x02In Common:\x02 " + \
177+
", ".join(artists) if artists else ""
178+
179+
return "Musical compatibility between \x02{}\x02 and \x02{}\x02: {} (\x02{}%\x02) {}".format(user1, user2, level,
180+
score, artist_string)
181+
182+
183+
@hook.command("ltop", "ltt", autohelp=False)
184+
def toptrack(text, nick, db, bot, notice):
185+
"""Grabs a list of the top tracks for a last.fm username"""
186+
api_key = bot.config.get("api_keys", {}).get("lastfm")
187+
if not api_key:
188+
return "error: no api key set"
189+
190+
if text:
191+
username = get_account(text)
192+
if not username:
193+
username = text
194+
else:
195+
username = get_account(nick)
196+
if not username:
197+
return("No last.fm username specified and no last.fm username is set in the database.")
198+
199+
params = {
200+
'api_key': api_key,
201+
'method': 'user.gettoptracks',
202+
'user': username,
203+
'limit': 5
204+
}
205+
request = requests.get(api_url, params=params)
206+
207+
if request.status_code != requests.codes.ok:
208+
return "Failed to fetch info ({})".format(request.status_code)
209+
210+
data = request.json()
211+
if 'error' in data:
212+
return "Error: {}.".format(data["message"])
213+
out = "{}'s favorite songs: ".format(username)
214+
for r in range(5):
215+
track_name = data["toptracks"]["track"][r]["name"]
216+
artist_name = data["toptracks"]["track"][r]["artist"]["name"]
217+
play_count = data["toptracks"]["track"][r]["playcount"]
218+
out = out + "{} by {} listened to {} times. ".format(track_name, artist_name, play_count)
219+
return out
220+
221+
222+
@hook.command("lta", "topartist", autohelp=False)
223+
def topartists(text, nick, db, bot, notice):
224+
"""Grabs a list of the top artists for a last.fm username. You can set your lastfm username with .l username"""
225+
api_key = bot.config.get("api_keys", {}).get("lastfm")
226+
if not api_key:
227+
return "error: no api key set"
228+
229+
if text:
230+
username = get_account(text)
231+
if not username:
232+
username = text
233+
else:
234+
username = get_account(nick)
235+
if not username:
236+
return("No last.fm username specified and no last.fm username is set in the database.")
237+
params = {
238+
'api_key': api_key,
239+
'method': 'user.gettopartists',
240+
'user': username,
241+
'limit': 5
242+
}
243+
request = requests.get(api_url, params=params)
126244

127-
return "Musical compatibility between \x02{}\x02 and \x02{}\x02: {} (\x02{}%\x02)".format(user1, user2, level,
128-
score), artist_string
245+
if request.status_code != requests.codes.ok:
246+
return "Failed to fetch info ({})".format(request.status_code)
247+
248+
data = request.json()
249+
if 'error' in data:
250+
return "Error: {}.".format(data["message"])
251+
252+
out = "{}'s favorite artists: ".format(username)
253+
for r in range(5):
254+
artist_name = data["topartists"]["artist"][r]["name"]
255+
play_count = data["topartists"]["artist"][r]["playcount"]
256+
out = out + "{} listened to {} times. ".format(artist_name, play_count)
257+
return out
258+
259+
260+
@hook.command("lt", "ltrack", autohelp=False)
261+
def lastfm_track(text, nick, db, bot, notice):
262+
"""Grabs a list of the top tracks for a last.fm username"""
263+
api_key = bot.config.get("api_keys", {}).get("lastfm")
264+
if not api_key:
265+
return "error: no api key set"
266+
artist = ""
267+
track = ""
268+
if text:
269+
params = text.split(',')
270+
if len(params) < 2:
271+
notice(
272+
"Please specify an artist and track title in the form artist name, track name.", nick)
273+
return
274+
else:
275+
artist = params[0]
276+
track = params[1]
277+
else:
278+
notice(
279+
"Please specify an artist and track title in the form artist name, track name.", nick)
280+
return
281+
username = get_account(nick)
282+
if username:
283+
params = {
284+
'api_key': api_key,
285+
'method': 'track.getInfo',
286+
'artist': artist,
287+
'track': track,
288+
'username': username,
289+
'autocorrect': 1
290+
}
291+
else:
292+
params = {
293+
'api_key': api_key,
294+
'method': 'track.getInfo',
295+
'artist': artist,
296+
'track': track,
297+
'autocorrect': 1
298+
}
299+
request = requests.get(api_url, params=params)
300+
301+
if request.status_code != requests.codes.ok:
302+
return "Failed to fetch info ({})".format(request.status_code)
303+
304+
response = request.json()
305+
if 'error' in response:
306+
return "Error: {}.".format(response["message"])
307+
308+
track_name = response["track"]["name"]
309+
artist_name = response["track"]["artist"]["name"]
310+
album_name = response["track"]["album"]["title"]
311+
url = web.try_shorten(response["track"]["url"])
312+
listeners = response["track"]["listeners"]
313+
playcount = response["track"]["playcount"]
314+
out = out = "'{}' from the album {} by {} has been played {} times by {} listeners. {}".format(
315+
track_name, album_name, artist_name, playcount, listeners, url)
316+
if 'userplaycount' in response["track"]:
317+
userplaycount = response["track"]["userplaycount"]
318+
out = "'{}' from the album {} by {} has been played {} times by {} listeners. {} has listened {} times. {}".format(
319+
track_name, album_name, artist_name, playcount, listeners, username, userplaycount, url)
320+
return out
321+
322+
323+
@hook.command("la", "lartist", autohelp=False)
324+
def lastfm_artist(text, nick, db, bot, notice):
325+
"""<artist> prints information about the specified artist"""
326+
api_key = bot.config.get("api_keys", {}).get("lastfm")
327+
if not api_key:
328+
return "error: no api key set"
329+
artist = text
330+
params = ""
331+
if text:
332+
pass
333+
else:
334+
notice("Please specify an artist.", nick)
335+
username = get_account(nick)
336+
if username:
337+
params = {
338+
'api_key': api_key,
339+
'method': 'artist.getInfo',
340+
'artist': artist,
341+
'username': username,
342+
'autocorrect': 1
343+
}
344+
else:
345+
params = {
346+
'api_key': api_key,
347+
'method': 'artist.getInfo',
348+
'artist': artist,
349+
'autocorrect': 1
350+
}
351+
352+
request = requests.get(api_url, params=params)
353+
354+
if request.status_code != requests.codes.ok:
355+
return "Failed to fetch info ({})".format(request.status_code)
356+
357+
response = request.json()
358+
if 'error' in response:
359+
return "Error: {}.".format(response["message"])
360+
artist_name = response["artist"]["name"]
361+
url = web.try_shorten(response["artist"]["url"])
362+
listeners = response["artist"]["stats"]["listeners"]
363+
playcount = response["artist"]["stats"]["playcount"]
364+
out = out = "{} has been played {} times by {} listeners. {}".format(
365+
artist_name, playcount, listeners, url)
366+
if 'userplaycount' in response["artist"]["stats"]:
367+
userplaycount = response["artist"]["stats"]["userplaycount"]
368+
out = "'{}' has been played {} times by {} listeners. {} has listened {} times. {}".format(
369+
artist_name, playcount, listeners, username, userplaycount, url)
370+
return out

0 commit comments

Comments
 (0)