cinch-lastfm-ng 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +59 -0
- data/VERSION +1 -0
- data/cinch-lastfm-ng.gemspec +48 -0
- data/lib/cinch/plugins/lastfm/version.rb +5 -0
- data/lib/cinch/plugins/lastfm.rb +522 -0
- metadata +109 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 152993ef98f4f263a40182239f4e8b26b330794a
|
4
|
+
data.tar.gz: 2e21e9d1705a3f3716493547e8fae317d11698b0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 78d2bfa57e5e6e5459b80f4a0699639901f583959b45acb2012a7c41ed68fc5c10a21e198e8e090ae21bcf8872525d1c4c0bcfaf2a984fb0f7a59b49af1e2403
|
7
|
+
data.tar.gz: 217ddf8274a0faed2880cce4125e69cfbc35bc0d2db78952a8e5a430ce801e20fc31c090a5702457db4466b18562ce3c850eed50f144d26731a680832c146739
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Lilian Jónsdóttir
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
Last.fm Plugin for Cinch
|
2
|
+
========================
|
3
|
+
Display recently played tracks, search artists, display top
|
4
|
+
artists/albums/tracks from specified time period, search tags, display profile
|
5
|
+
information, etc.
|
6
|
+
|
7
|
+
Usage
|
8
|
+
-----
|
9
|
+
|
10
|
+
install the gem with *gem install Cinch-Automode*, and
|
11
|
+
add it to your bot like so:
|
12
|
+
|
13
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ruby
|
14
|
+
require 'cinch'
|
15
|
+
require 'cinch/plugins/automode'
|
16
|
+
|
17
|
+
bot = Cinch::Bot.new do
|
18
|
+
configure do |c|
|
19
|
+
c.server = 'your server'
|
20
|
+
c.nick = 'your nick'
|
21
|
+
c.realname = 'your realname'
|
22
|
+
c.user = 'your user'
|
23
|
+
c.channels = ['#yourchannel']
|
24
|
+
c.plugins.plugins = [Cinch::Plugins::Automode]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
bot.start
|
29
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
30
|
+
|
31
|
+
Contained Commands
|
32
|
+
------------------
|
33
|
+
|
34
|
+
**[automode (on|off)]**
|
35
|
+
|
36
|
+
Enable/disable the plugin in the current channel. Default is off.
|
37
|
+
|
38
|
+
**[add (op|halfop|voice) nick user@host]**
|
39
|
+
|
40
|
+
Add nick with user@host to the auto-(op|halfop|voice) list
|
41
|
+
|
42
|
+
**[del (op|halfop|voice) nick user@host]**
|
43
|
+
|
44
|
+
Delete nick with user@host from the auto-(op|halfop|voice) list
|
45
|
+
|
46
|
+
**[add channel (op|halfop|voice)]**
|
47
|
+
|
48
|
+
Add the entire channel to the list, so anyone who joins gets the mode.
|
49
|
+
|
50
|
+
**[del channel (op|halfop|voice)]**
|
51
|
+
|
52
|
+
Delete the channel from the mode list.
|
53
|
+
|
54
|
+
License
|
55
|
+
-------
|
56
|
+
|
57
|
+
Licensed under The MIT License (MIT)
|
58
|
+
|
59
|
+
Please see LICENSE
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
# -*- encoding: utf-8 -*-
|
3
|
+
$LOAD_PATH.push('lib')
|
4
|
+
require 'cinch/plugins/lastfm/version.rb'
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = 'cinch-lastfm-ng'
|
8
|
+
s.version = Cinch::Lastfm::VERSION.dup
|
9
|
+
s.licenses = ['MIT']
|
10
|
+
s.date = '2016-05-22'
|
11
|
+
s.summary = 'Lastfm plugin for Cinch'
|
12
|
+
s.email = 'lilian.jonsdottir@gmail.com'
|
13
|
+
s.homepage = 'https://github.com/lilyseki/Cinch-Lastfm'
|
14
|
+
s.authors = ['Lily Jónsdóttir']
|
15
|
+
|
16
|
+
s.description = <<-EOF
|
17
|
+
Display recently played tracks, search artists, display top
|
18
|
+
artists/albums/tracks from specified time period, search tags, display profile
|
19
|
+
information, etc.
|
20
|
+
EOF
|
21
|
+
|
22
|
+
dependencies = [
|
23
|
+
[:runtime, 'sequel', '~> 4.34'],
|
24
|
+
[:runtime, 'nokogiri', '~> 1.6'],
|
25
|
+
[:runtime, 'time_diff', '~> 0.3'],
|
26
|
+
[:runtime, 'addressable', '~> 2.4']
|
27
|
+
]
|
28
|
+
|
29
|
+
s.files = Dir['**/*']
|
30
|
+
s.test_files = Dir['test/**/*'] + Dir['spec/**/*']
|
31
|
+
s.executables = Dir['bin/*'].map { |f| File.basename(f) }
|
32
|
+
s.require_paths = ['lib']
|
33
|
+
|
34
|
+
## Make sure you can build the gem on older versions of RubyGems too:
|
35
|
+
s.rubygems_version = '2.5.1'
|
36
|
+
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
37
|
+
s.specification_version = 3 if s.respond_to? :specification_version
|
38
|
+
|
39
|
+
dependencies.each do |type, name, version|
|
40
|
+
if s.respond_to?("add_#{type}_dependency")
|
41
|
+
s.send("add_#{type}_dependency", name, version)
|
42
|
+
else
|
43
|
+
s.add_dependency(name, version)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# vim:tabstop=2 softtabstop=2 expandtab shiftwidth=2 smarttab foldmethod=syntax:
|
@@ -0,0 +1,522 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# encoding=utf-8
|
3
|
+
require 'sequel' # SQLite 3 database
|
4
|
+
require 'nokogiri' # Decoding XML/HTML from lastfm api
|
5
|
+
require 'cgi' # Escaping/Unescaping HTML entities
|
6
|
+
require 'time_diff' # Calculating difference in times
|
7
|
+
require 'httparty' # Better HTTP Opening
|
8
|
+
require 'addressable/uri'
|
9
|
+
require 'webrick/httputils' # Fix for unicode URLs
|
10
|
+
|
11
|
+
module Cinch
|
12
|
+
module Plugins
|
13
|
+
# Last.fm plugin
|
14
|
+
class Lastfm
|
15
|
+
include Cinch::Plugin
|
16
|
+
|
17
|
+
def initialize(*args)
|
18
|
+
super
|
19
|
+
@base_url = 'http://ws.audioscrobbler.com/2.0/?api_key='
|
20
|
+
@api_key = config[:api_key]
|
21
|
+
@api_url = "#{@base_url}#{@api_key}&method="
|
22
|
+
# @db = Sequel.sqlite('riria.db')
|
23
|
+
filename = "#{@bot.nick.downcase}.db"
|
24
|
+
@db = Sequel.sqlite(filename)
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def get_user(nick)
|
30
|
+
return nil if @db[:lastfm].where(nick: nick).empty?
|
31
|
+
usernick = @db[:lastfm].where(nick: nick).first[:username]
|
32
|
+
usernick
|
33
|
+
end
|
34
|
+
|
35
|
+
# Remove stupid pointless tags
|
36
|
+
def stupid_tags(tagarray)
|
37
|
+
tagarray.delete('seen live') # Worst tag on all of last.fm
|
38
|
+
tagarray.delete('indie')
|
39
|
+
|
40
|
+
tagarray
|
41
|
+
end
|
42
|
+
|
43
|
+
# Debug shit
|
44
|
+
def header(title)
|
45
|
+
puts '=' * 10 + " #{title} " + '=' * 10
|
46
|
+
end
|
47
|
+
|
48
|
+
public
|
49
|
+
|
50
|
+
# And now onto the commands
|
51
|
+
match(/np(?: (.+))?/, method: :np)
|
52
|
+
def np(m, query = nil)
|
53
|
+
method = 'user.getRecentTracks'
|
54
|
+
|
55
|
+
user = query.nil? ? get_user(m.user.nick) : get_user(query.strip)
|
56
|
+
user = query.nil? ? m.user.nick : query.strip unless user
|
57
|
+
|
58
|
+
ac = '&autocorrect=1'
|
59
|
+
request = "#{@api_url}#{method}&user=#{user}"
|
60
|
+
|
61
|
+
# Last tracks
|
62
|
+
begin
|
63
|
+
page = HTTParty.get(Addressable::URI.parse(request))
|
64
|
+
doc = Nokogiri::XML(page.body)
|
65
|
+
# puts "Fetching #{request}"
|
66
|
+
|
67
|
+
if doc.xpath('//lfm')[0]['status'] == 'failed'
|
68
|
+
puts request
|
69
|
+
puts doc
|
70
|
+
m.reply "Error: #{doc.xpath('//error')[0].text}"
|
71
|
+
return
|
72
|
+
end
|
73
|
+
nowplaying = doc.xpath('//track')[0]['nowplaying']
|
74
|
+
|
75
|
+
whenplayed = doc.xpath('//track//date')[0]['uts'].to_i unless nowplaying
|
76
|
+
|
77
|
+
artist = doc.xpath('//track//artist')[0].text
|
78
|
+
title = doc.xpath('//track//name')[0].text
|
79
|
+
rescue NoMethodError
|
80
|
+
m.reply('No tracks found or username doesn\'t exist!')
|
81
|
+
return
|
82
|
+
end
|
83
|
+
|
84
|
+
begin
|
85
|
+
album = doc.xpath('//track//album')[0].text
|
86
|
+
puts "album = #{album}"
|
87
|
+
rescue NoMethodError
|
88
|
+
album = nil
|
89
|
+
end
|
90
|
+
|
91
|
+
album = nil if album == ''
|
92
|
+
|
93
|
+
# Track info
|
94
|
+
begin
|
95
|
+
header 'TRACK INFO'
|
96
|
+
doop = WEBrick::HTTPUtils.escape_form(artist)
|
97
|
+
pood = WEBrick::HTTPUtils.escape_form(title)
|
98
|
+
# puts doop
|
99
|
+
trackreq = "#{@api_url}track.getInfo&artist=#{doop}&track=#{pood}&user=#{user}#{ac}"
|
100
|
+
puts "trackreq: #{trackreq}"
|
101
|
+
query = trackreq.force_encoding('binary')
|
102
|
+
puts "query: #{query}"
|
103
|
+
page = HTTParty.get(Addressable::URI.parse(query))
|
104
|
+
trackdoc = Nokogiri::XML(page.body)
|
105
|
+
|
106
|
+
if trackdoc.xpath('//lfm')[0]['status'] == 'failed'
|
107
|
+
begin
|
108
|
+
m.reply error_code(trackdoc.xpath('//error')['code'].to_i)
|
109
|
+
return
|
110
|
+
rescue TypeError
|
111
|
+
puts 'derp'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
header 'trackdoc'
|
115
|
+
puts trackdoc
|
116
|
+
header 'end trackdoc'
|
117
|
+
# listeners = trackdoc.xpath('//track//listeners').text
|
118
|
+
# playcount = trackdoc.xpath('//track//playcount').text
|
119
|
+
userpc = trackdoc.xpath('//track//userplaycount').text
|
120
|
+
loved = trackdoc.xpath('//track//userloved').text.to_i
|
121
|
+
# trackinfo = true
|
122
|
+
userplayed = true
|
123
|
+
puts userpc
|
124
|
+
header 'END TRACK INFO'
|
125
|
+
# rescue OpenURI::HTTPError
|
126
|
+
# trackinfo = false
|
127
|
+
rescue NoMethodError
|
128
|
+
userplayed = false
|
129
|
+
end
|
130
|
+
|
131
|
+
# Artist info
|
132
|
+
begin
|
133
|
+
doop = WEBrick::HTTPUtils.escape_form(artist)
|
134
|
+
# puts doop
|
135
|
+
artistreq = "#{@api_url}artist.getInfo#{ac}&artist=#{doop}&user=#{user}"
|
136
|
+
query = artistreq.force_encoding('binary')
|
137
|
+
page = HTTParty.get(Addressable::URI.parse(query))
|
138
|
+
artistdoc = Nokogiri::XML(page.body)
|
139
|
+
# puts "Fetching #{query}"
|
140
|
+
if artistdoc.xpath('//lfm')[0]['status'] == 'failed'
|
141
|
+
m.reply error_code(artistdoc.xpath('//error')[0]['code'].to_i)
|
142
|
+
return
|
143
|
+
end
|
144
|
+
artistinfo = false
|
145
|
+
toptags = artistdoc.xpath('//tags//tag//name')
|
146
|
+
tags = []
|
147
|
+
toptags.each { |i| tags << i.text }
|
148
|
+
tags = stupid_tags(tags)
|
149
|
+
artistinfo = true unless tags.empty?
|
150
|
+
|
151
|
+
rescue NoMethodError
|
152
|
+
artistinfo = false
|
153
|
+
end
|
154
|
+
|
155
|
+
unless nowplaying
|
156
|
+
future = if whenplayed > Time.now.to_i
|
157
|
+
true
|
158
|
+
else
|
159
|
+
false
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
output = nowplaying ? '♫' : '♪'
|
164
|
+
output << " #{artist} :: #{title}"
|
165
|
+
output << " [#{album}]" if album
|
166
|
+
output << ' ♥' unless loved.zero?
|
167
|
+
unless nowplaying
|
168
|
+
output << ' :: in ' + Time.diff(Time.at(whenplayed), Time.now)[:diff].to_s if future
|
169
|
+
output << ' :: ' + Time.diff(Time.at(whenplayed), Time.now)[:diff].to_s + ' ago' unless future
|
170
|
+
end
|
171
|
+
# output << ' ::' if nowplaying
|
172
|
+
output << " :: #{userpc} plays" if userplayed && !userpc.empty?
|
173
|
+
# output << " #{playcount} by #{listeners} others." if trackinfo
|
174
|
+
if artistinfo
|
175
|
+
len = tags.length >= 3 ? 3 : tags.length
|
176
|
+
output << ' :: '
|
177
|
+
tags.first(len).each_with_index do |i, j|
|
178
|
+
output.concat j == len - 1 ? i.to_s : "#{i}, "
|
179
|
+
end
|
180
|
+
output << ' ::'
|
181
|
+
else
|
182
|
+
output << ' :: no tags ::'
|
183
|
+
end
|
184
|
+
m.reply output
|
185
|
+
end
|
186
|
+
|
187
|
+
match(/artist(?: (.+))?/, method: :artist_search)
|
188
|
+
match(/plays(?: (.+))?/, method: :artist_search)
|
189
|
+
def artist_search(m, query)
|
190
|
+
method = 'artist.getInfo'
|
191
|
+
specific_user = false
|
192
|
+
|
193
|
+
list = query.split
|
194
|
+
if list.include?('-user')
|
195
|
+
specific_user = true
|
196
|
+
user_index = list.index('-user')
|
197
|
+
band = if user_index.zero?
|
198
|
+
list[user_index + 2..-1]
|
199
|
+
else
|
200
|
+
list[0..user_index - 1] + list[user_index + 2..-1]
|
201
|
+
end
|
202
|
+
query = band.join ' '
|
203
|
+
puts query
|
204
|
+
user = list[user_index + 1]
|
205
|
+
user = get_user(user) unless get_user(user).nil?
|
206
|
+
else
|
207
|
+
user = get_user(m.user.nick)
|
208
|
+
user = m.user.nick if user.nil? || user.empty?
|
209
|
+
end
|
210
|
+
|
211
|
+
artist = query.force_encoding('binary')
|
212
|
+
artist = WEBrick::HTTPUtils.escape_form(artist)
|
213
|
+
ac = '&autocorrect=1'
|
214
|
+
|
215
|
+
artistreq = "#{@api_url}#{method}#{ac}&artist=#{artist}&user=#{user}"
|
216
|
+
page = HTTParty.get(Addressable::URI.parse(artistreq))
|
217
|
+
doc = Nokogiri::XML(page.body)
|
218
|
+
puts "Fetching #{artistreq}"
|
219
|
+
|
220
|
+
begin
|
221
|
+
a = doc.xpath('//artist//name')[0].text
|
222
|
+
toptags = doc.xpath('//tags//tag//name')
|
223
|
+
listeners = doc.xpath('//stats//listeners').text
|
224
|
+
playcount = doc.xpath('//stats//playcount').text
|
225
|
+
rescue NoMethodError
|
226
|
+
m.reply('Artist not found!')
|
227
|
+
return
|
228
|
+
end
|
229
|
+
begin
|
230
|
+
userpc = doc.xpath('//stats//userplaycount').text
|
231
|
+
userpc = nil if userpc == ''
|
232
|
+
rescue NoMethodError
|
233
|
+
userpc = nil
|
234
|
+
end
|
235
|
+
|
236
|
+
tags = []
|
237
|
+
toptags.each { |i| tags << i.text }
|
238
|
+
tags = stupid_tags(tags)
|
239
|
+
|
240
|
+
len = tags.length >= 3 ? 3 : tags.length
|
241
|
+
notags = tags.empty? ? true : false
|
242
|
+
|
243
|
+
output = a.to_s
|
244
|
+
if notags
|
245
|
+
output << ' :: no tags'
|
246
|
+
else
|
247
|
+
output << ' :: '
|
248
|
+
tags.first(len).each_with_index do |i, j|
|
249
|
+
output.concat j == len - 1 ? i.to_s : "#{i}, "
|
250
|
+
end
|
251
|
+
end
|
252
|
+
output.concat userpc ? " :: #{userpc} plays" : ' :: '
|
253
|
+
output << " by #{user} :: " if specific_user && userpc
|
254
|
+
output << ' :: ' if userpc && !specific_user
|
255
|
+
output << "#{playcount} by #{listeners} others ::"
|
256
|
+
m.reply output
|
257
|
+
end
|
258
|
+
|
259
|
+
# Currently broken per Last.fm
|
260
|
+
match(/compare(?: (.+))?/, method: :compare)
|
261
|
+
def compare(m, user1, user2 = nil)
|
262
|
+
method = 'tasteometer.compare'
|
263
|
+
user2 = get_user(m.user.nick) unless user2
|
264
|
+
|
265
|
+
creq = "#{@api_url}#{method}&type1=user&type2=user&value1=#{user1}&value2=&#{user2}"
|
266
|
+
puts creq
|
267
|
+
page = HTTParty.get(Addressable::URI.parse(creq))
|
268
|
+
doc = Nokogiri::XML(page.body)
|
269
|
+
if doc.xpath('//lfm')[0]['status'] == 'failed'
|
270
|
+
m.reply("#{doc.xpath('//error')[0]['code']}: #{doc.xpath('//error').text}")
|
271
|
+
# return
|
272
|
+
end
|
273
|
+
puts doc
|
274
|
+
end
|
275
|
+
|
276
|
+
# My probably lousy attempt at not reusing code
|
277
|
+
match(/topartists(:? (.+))?/, method: :top_artists)
|
278
|
+
def top_artists(m, p)
|
279
|
+
tops(m, 'user.getTopArtists', p, 'artists')
|
280
|
+
end
|
281
|
+
|
282
|
+
match(/toptracks(:? (.+))?/, method: :top_tracks)
|
283
|
+
def top_tracks(m, p)
|
284
|
+
tops(m, 'user.getTopTracks', p, 'tracks')
|
285
|
+
end
|
286
|
+
|
287
|
+
match(/topalbums(:? (.+))?/, method: :top_albums)
|
288
|
+
def top_albums(m, p)
|
289
|
+
tops(m, 'user.getTopAlbums', p, 'albums')
|
290
|
+
end
|
291
|
+
|
292
|
+
def tops(m, meth, period, type)
|
293
|
+
# method = 'user.getTopArtists'
|
294
|
+
method = meth
|
295
|
+
period = 'overall' if period.nil?
|
296
|
+
|
297
|
+
period.strip!
|
298
|
+
list = period.split
|
299
|
+
if list.include?('-user')
|
300
|
+
user_index = list.index('-user')
|
301
|
+
per = if user_index.zero?
|
302
|
+
list[user_index + 2..-1]
|
303
|
+
else
|
304
|
+
list[0..user_index - 1] + list[user_index + 2..-1]
|
305
|
+
end
|
306
|
+
period = per.join ' '
|
307
|
+
user = list[user_index + 1]
|
308
|
+
else
|
309
|
+
user = get_user(m.user.nick)
|
310
|
+
user = m.user.nick if user.nil? || user.empty?
|
311
|
+
end
|
312
|
+
|
313
|
+
case period
|
314
|
+
when '7d', '7day'
|
315
|
+
period = '7day'
|
316
|
+
str = '7 days'
|
317
|
+
when '1m', '1month'
|
318
|
+
period = '1month'
|
319
|
+
str = '1 month'
|
320
|
+
when '3m', '3month'
|
321
|
+
period = '3month'
|
322
|
+
str = '3 months'
|
323
|
+
when '6m', 'month'
|
324
|
+
period = '6month'
|
325
|
+
str = '6 months'
|
326
|
+
when '1y', '1year', '12m', '12month'
|
327
|
+
period = '12month'
|
328
|
+
str = '1 year'
|
329
|
+
else
|
330
|
+
period = 'overall'
|
331
|
+
str = period
|
332
|
+
end
|
333
|
+
|
334
|
+
urlget = "#{@api_url}#{method}&period=#{period}&user=#{user}&limit=10"
|
335
|
+
puts urlget
|
336
|
+
page = HTTParty.get(Addressable::URI.parse(urlget))
|
337
|
+
doc = Nokogiri::XML(page.body)
|
338
|
+
# puts "doc: #{doc.text}"
|
339
|
+
|
340
|
+
# This will only ever be true for 'overall'
|
341
|
+
output = if str == period
|
342
|
+
"#{str.capitalize} top #{type} "
|
343
|
+
else
|
344
|
+
"Top #{type} of the past #{str} "
|
345
|
+
end
|
346
|
+
|
347
|
+
# process the doc differently depending on query type (artists, tracks,
|
348
|
+
# albums, tags, etc.) There's probably a less shitty way to do this but
|
349
|
+
# oh well, I tried to not be redundant a bunch
|
350
|
+
if method == 'user.getTopArtists'
|
351
|
+
artists = []
|
352
|
+
plays_in_period = []
|
353
|
+
doc.xpath('//topartists//name').each { |i| artists << i.text }
|
354
|
+
doc.xpath('//topartists//playcount').each { |i| plays_in_period << i.text }
|
355
|
+
|
356
|
+
# Combine the two arrays into a single hash.
|
357
|
+
artplays = Hash[artists.zip(plays_in_period)]
|
358
|
+
puts "Artists: #{artists}: #{artists.class}"
|
359
|
+
puts "Artplays: #{artplays}: #{artplays.class}"
|
360
|
+
|
361
|
+
len = artplays.length >= 5 ? 5 : artplays.length
|
362
|
+
artplays.first(len).each_with_index do |(name, plays), i|
|
363
|
+
puts "name: #{name} :: plays: #{plays}, i: #{i}"
|
364
|
+
output << ":: #{name} (#{plays})"
|
365
|
+
output.concat i == len - 1 ? ' ::' : ' '
|
366
|
+
end
|
367
|
+
elsif method == 'user.getTopTracks'
|
368
|
+
artists = []
|
369
|
+
tracks = []
|
370
|
+
track_plays = []
|
371
|
+
doc.xpath('//artist//name').each { |i| artists << i.text }
|
372
|
+
doc.xpath('/lfm/toptracks/track/name').each { |i| tracks << i.text }
|
373
|
+
doc.xpath('//track//playcount').each { |i| track_plays << i.text }
|
374
|
+
|
375
|
+
puts "Artists: #{artists.length}, #{artists}"
|
376
|
+
puts "Tracks: #{tracks.length}, #{tracks}"
|
377
|
+
puts "Playcount: #{track_plays.length}, #{track_plays}"
|
378
|
+
|
379
|
+
unless artists.length == tracks.length && track_plays.length == tracks.length
|
380
|
+
# Something went horribly wrong, abort!
|
381
|
+
m.reply('Fission mailed!')
|
382
|
+
return
|
383
|
+
end
|
384
|
+
len = tracks.length >= 5 ? 5 : tracks.length
|
385
|
+
len.times do |i|
|
386
|
+
output << ":: #{artists[i]} - #{tracks[i]} (#{track_plays[i]})"
|
387
|
+
output.concat i == len - 1 ? ' ::' : ' '
|
388
|
+
end
|
389
|
+
elsif method == 'user.getTopAlbums'
|
390
|
+
artists = []
|
391
|
+
albums = []
|
392
|
+
album_plays = []
|
393
|
+
doc.xpath('//artist//name').each { |i| artists << i.text }
|
394
|
+
doc.xpath('/lfm/topalbums/album/name').each { |i| albums << i.text }
|
395
|
+
doc.xpath('//album//playcount').each { |i| album_plays << i.text }
|
396
|
+
|
397
|
+
puts "Artists: #{artists.length}, #{artists}"
|
398
|
+
puts "Albums: #{albums.length}, #{albums}"
|
399
|
+
puts "Playcount: #{album_plays.length}, #{album_plays}"
|
400
|
+
|
401
|
+
unless artists.length == albums.length && album_plays.length == albums.length
|
402
|
+
# Something went horribly wrong, abort!
|
403
|
+
m.reply('Fission mailed!')
|
404
|
+
return
|
405
|
+
end
|
406
|
+
len = albums.length >= 5 ? 5 : albums.length
|
407
|
+
len.times do |i|
|
408
|
+
output << ":: #{artists[i]} - #{albums[i]} (#{album_plays[i]})"
|
409
|
+
output.concat i == len - 1 ? ' ::' : ' '
|
410
|
+
end
|
411
|
+
end
|
412
|
+
|
413
|
+
m.reply output
|
414
|
+
end
|
415
|
+
|
416
|
+
# This doesn't seem to work either. Thanks last.fm
|
417
|
+
match(/toptags(:? (.+))?/, method: :top_tags)
|
418
|
+
def top_tags(m, u)
|
419
|
+
user = u.nil? ? get_user(m.user.nick) : get_user(u.strip)
|
420
|
+
user = u.nil? ? m.user.nick : u.strip unless user
|
421
|
+
|
422
|
+
method = 'user.getTopTags'
|
423
|
+
urlget = "#{@api_url}#{method}&user=#{user}&limit=10"
|
424
|
+
puts urlget
|
425
|
+
page = HTTParty.get(Addressable::URI.parse(urlget))
|
426
|
+
doc = Nokogiri::XML(page.body)
|
427
|
+
|
428
|
+
tags = []
|
429
|
+
counts = []
|
430
|
+
|
431
|
+
doc.xpath('//name').each { |i| tags << i }
|
432
|
+
doc.xpath('//count').each { |i| counts << i }
|
433
|
+
output = "#{user}'s most used tags "
|
434
|
+
|
435
|
+
tagusage = Hash[tags.zip(counts)]
|
436
|
+
|
437
|
+
len = tagusage.length >= 5 ? 5 : tagusage.length
|
438
|
+
tagusage.first(len).each_with_index do |(name, plays), i|
|
439
|
+
puts "name: #{name} :: plays: #{plays}, i: #{i}"
|
440
|
+
output << ":: #{name} (#{plays})"
|
441
|
+
output.concat i == len - 1 ? ' ::' : ' '
|
442
|
+
end
|
443
|
+
output = 'User has not tagged anything!' if tags.empty? || counts.empty?
|
444
|
+
m.reply output
|
445
|
+
end
|
446
|
+
|
447
|
+
match(/tag(:? (.+))?/, method: :tag_search)
|
448
|
+
def tag_search(m, query)
|
449
|
+
method = 'tag.getInfo'
|
450
|
+
urlget = "#{@api_url}#{method}&tag=#{query.strip}"
|
451
|
+
puts urlget
|
452
|
+
page = HTTParty.get(Addressable::URI.parse(urlget))
|
453
|
+
doc = Nokogiri::XML(page.body)
|
454
|
+
|
455
|
+
num_used = doc.xpath('//tag//total').text
|
456
|
+
name = doc.xpath('//tag//name').text
|
457
|
+
# Clean up the summary: remove HTML tags, truncate, etc.
|
458
|
+
summary = doc.xpath('//tag//wiki//summary').text.gsub(%r{<\/?[^>]*>}, '')
|
459
|
+
summary.sub!('Read more on Last.fm.', '')
|
460
|
+
summary = if summary.length > 220
|
461
|
+
summary[0..220] + '...'
|
462
|
+
else
|
463
|
+
summary
|
464
|
+
end
|
465
|
+
summary = '???' if summary.strip.empty?
|
466
|
+
output = "#{name} :: Used: #{num_used} times :: #{summary} ::"
|
467
|
+
output += " http://www.last.fm/tag/#{name} ::"
|
468
|
+
m.reply output
|
469
|
+
end
|
470
|
+
|
471
|
+
match(/profile(:? (.+))?/, method: :profile)
|
472
|
+
def profile(m, query)
|
473
|
+
method = 'user.getInfo'
|
474
|
+
|
475
|
+
user = query.nil? ? get_user(m.user.nick) : get_user(query.strip)
|
476
|
+
user = query.nil? ? m.user.nick : query.strip unless user
|
477
|
+
|
478
|
+
# Fetch the data
|
479
|
+
url = "#{@api_url}#{method}&user=#{user}"
|
480
|
+
page = HTTParty.get(Addressable::URI.parse(url))
|
481
|
+
doc = Nokogiri::XML(page.body)
|
482
|
+
|
483
|
+
realname = doc.xpath('//realname').text
|
484
|
+
realname = 'No name' if realname.empty?
|
485
|
+
gender = doc.xpath('//gender').text
|
486
|
+
playcount = doc.xpath('//playcount').text
|
487
|
+
userurl = doc.xpath('//url').text
|
488
|
+
country = doc.xpath('//country').text
|
489
|
+
country = 'Nowhere' if country.empty?
|
490
|
+
reg = doc.xpath('//registered')[0]['unixtime']
|
491
|
+
regdate = DateTime.strptime(reg, '%s')
|
492
|
+
|
493
|
+
output = "#{user} :: #{realname} / #{gender} / #{country}"
|
494
|
+
output << " :: Plays: #{playcount}"
|
495
|
+
output << " :: Registered on: #{regdate.day} #{regdate.strftime('%b')} #{regdate.year}"
|
496
|
+
output << " :: #{userurl}"
|
497
|
+
m.reply(output)
|
498
|
+
end
|
499
|
+
|
500
|
+
match(/fmset(?: (.+))?/, method: :fmset)
|
501
|
+
def fmset(m, username = nil)
|
502
|
+
m.reply 'You need to input a username to set your username' && return if username.nil?
|
503
|
+
username = username.strip
|
504
|
+
if @db[:lastfm].where(nick: m.user.nick).empty?
|
505
|
+
@db[:lastfm].insert(nick: m.user.nick, username: username)
|
506
|
+
else
|
507
|
+
uid = @db[:lastfm].where(nick: m.user.nick).first[:id]
|
508
|
+
@db[:lastfm].where(id: uid).update(username: username)
|
509
|
+
end
|
510
|
+
m.reply "#{m.user.nick} is now #{username}!"
|
511
|
+
end
|
512
|
+
|
513
|
+
match(/fmget(?: (.+))?/, method: :fmget)
|
514
|
+
def fmget(m)
|
515
|
+
user = get_user(m.user.nick)
|
516
|
+
m.reply user ? "#{m.user.nick} is #{user}!" : 'I don\'t know your username!'
|
517
|
+
end
|
518
|
+
end
|
519
|
+
end
|
520
|
+
end
|
521
|
+
|
522
|
+
# vim:tabstop=2 softtabstop=2 expandtab shiftwidth=2 smarttab foldmethod=syntax:
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: cinch-lastfm-ng
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Lily Jónsdóttir
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-05-22 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: sequel
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.34'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.34'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: nokogiri
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '1.6'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '1.6'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: time_diff
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.3'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.3'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: addressable
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '2.4'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '2.4'
|
69
|
+
description: |
|
70
|
+
Display recently played tracks, search artists, display top
|
71
|
+
artists/albums/tracks from specified time period, search tags, display profile
|
72
|
+
information, etc.
|
73
|
+
email: lilian.jonsdottir@gmail.com
|
74
|
+
executables: []
|
75
|
+
extensions: []
|
76
|
+
extra_rdoc_files: []
|
77
|
+
files:
|
78
|
+
- LICENSE
|
79
|
+
- README.md
|
80
|
+
- VERSION
|
81
|
+
- cinch-lastfm-ng.gemspec
|
82
|
+
- lib/cinch/plugins/lastfm.rb
|
83
|
+
- lib/cinch/plugins/lastfm/version.rb
|
84
|
+
homepage: https://github.com/lilyseki/Cinch-Lastfm
|
85
|
+
licenses:
|
86
|
+
- MIT
|
87
|
+
metadata: {}
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
require_paths:
|
91
|
+
- lib
|
92
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: '0'
|
102
|
+
requirements: []
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 2.5.1
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: Lastfm plugin for Cinch
|
108
|
+
test_files: []
|
109
|
+
has_rdoc:
|