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 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,5 @@
1
+ module Cinch
2
+ module Lastfm
3
+ VERSION = '0.1.0'.freeze
4
+ end
5
+ end
@@ -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: