lily 0.1.2 → 0.1.31
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +52 -0
- data/bin/lily +1 -1
- data/lib/lily.rb +187 -21
- data/lib/lily/version.rb +1 -1
- data/lily.gemspec +1 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b9c20e3200112a22d65b821ed4f1252882b89242
|
4
|
+
data.tar.gz: c9eac958938d4546719eb6e03f76540af25a2199
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4c3c85ab8162ee4b64d94f42ce6a61c8440bdcb157ab20e8a7f6ec53a4f80eb22cbaa2f07c242db80d841b5eff31009234a742c1ecbff08abc4a492319658a7a
|
7
|
+
data.tar.gz: 8ec4c202e217f42d17a0e0386eebb403be8b0908b7a0d091415fae6edf0c30d92d0fef2a202032908e703f46d73c78eaacd272938b2a712a4bd028a40a94965c
|
data/README.md
CHANGED
@@ -16,3 +16,55 @@ gem install lily-*gem # Install the gem
|
|
16
16
|
|
17
17
|
lily init # Initialize :)
|
18
18
|
```
|
19
|
+
|
20
|
+
## Usage
|
21
|
+
|
22
|
+
What's a CLI without usage docs? A bad one. Below you'll find out how Lily can be used. Keep in mind, you can reference every command Lily has with `lily help`
|
23
|
+
|
24
|
+
### Initializing
|
25
|
+
Initializing Lily is very easy. Just run `lily init`, log in with LastFM, and you're set.
|
26
|
+
|
27
|
+
### Scrobbling
|
28
|
+
Lily's scrobbling feature is very useful, particularly for scrobbling things that can't be scrobbled automatically. For example, when you listen to a vinyl, a CD, that song you really like on the radio, or just something that bugged out and didn't scrobble. Here's how you do that:
|
29
|
+
|
30
|
+
#### Scrobbling Songs
|
31
|
+
Lily can simply and easily scrobble any individual song for you, assuming you just finished listening to it.
|
32
|
+
|
33
|
+
**Syntax:** `lily scrobble song (<song> <artist>) [<album>]`
|
34
|
+
|
35
|
+
**Examples:**
|
36
|
+
|
37
|
+
```bash
|
38
|
+
lily scrobble song "Here Comes the Sun" "The Beatles" # scrobbles Here Comes the Sun from Abbey Road, the most popular album it is on
|
39
|
+
|
40
|
+
lily scrobble song "Here Comes the Sun" "The Beatles" "The Beatles Ballads" # if you're a hipster, you can optionally specify the exact album you're listening to the song on
|
41
|
+
```
|
42
|
+
|
43
|
+
#### Scrobbling Albums
|
44
|
+
Scrobbling albums with Lily is really awesome. If the `--live` flag is not included, Lily will automatically start your album in the past, as if you just finished listening to the whole thing, and then scrobble the album track by track, just like you listened to it. On the other hand, if the `--live` flag *is* included, it will scrobble tracks in the future, as if you just started listening to the whole album.
|
45
|
+
|
46
|
+
**Syntax:** `lily scrobble album (<album> <artist> | <eponymous album>) [--live]`
|
47
|
+
|
48
|
+
**Examples:**
|
49
|
+
|
50
|
+
```bash
|
51
|
+
lily scrobble album "The Beatles" "The White Album" # scrobble the white album by its unofficial fan name
|
52
|
+
lily scrobble album "The Beatles" # scrobble album by its officially eponymous name, and save a few keystrokes
|
53
|
+
```
|
54
|
+
|
55
|
+
### Loving and Unloving
|
56
|
+
Lily can love and unlove songs and albums for you as well. The syntax to this is very similar to the syntax for scrobbling songs and albums, just with `love` or `unlove` instead of `scrobble`.
|
57
|
+
|
58
|
+
**Syntax for songs:** `lily (love | unlove) song (<song> <artist>) [<album>]`
|
59
|
+
|
60
|
+
**Syntax for albums:** `lily (love | unlove) album (<album> <artist> | <eponymous album>)`
|
61
|
+
|
62
|
+
**Examples:**
|
63
|
+
|
64
|
+
```bash
|
65
|
+
lily love album "The Beatles"
|
66
|
+
lily unlove album "The Beatles" "Abbey Road"
|
67
|
+
|
68
|
+
lily love song "Here Comes the Sun" "The Beatles" "The Beatles Ballads"
|
69
|
+
lily unlove song "Here Comes the Sun" "The Beatles"
|
70
|
+
```
|
data/bin/lily
CHANGED
data/lib/lily.rb
CHANGED
@@ -14,6 +14,7 @@ class Lily
|
|
14
14
|
"private" => "85fbaa6644c31d879c3e004fbddb82bf"
|
15
15
|
}
|
16
16
|
@lily_json = self.get_lily_json
|
17
|
+
@api_url = "http://ws.audioscrobbler.com/2.0/"
|
17
18
|
@token ||= self.token
|
18
19
|
end
|
19
20
|
|
@@ -34,9 +35,7 @@ class Lily
|
|
34
35
|
params = params.sort_by { |key, value| key }
|
35
36
|
params.each do |key, value|
|
36
37
|
path_arr.push("#{key}=" + URI.encode(value.to_s))
|
37
|
-
if (key != "format")
|
38
|
-
sig_str += key + value.to_s
|
39
|
-
end
|
38
|
+
sig_str += key + value.to_s if (key != "format")
|
40
39
|
end
|
41
40
|
sig_str += @keys.private
|
42
41
|
sig = Digest::MD5.hexdigest(sig_str)
|
@@ -44,6 +43,17 @@ class Lily
|
|
44
43
|
path = path_arr.join("&")
|
45
44
|
return path
|
46
45
|
end
|
46
|
+
|
47
|
+
def get_album_info(album, artist)
|
48
|
+
url = "#{@api_url}?method=album.getinfo&api_key=#{@keys.public}&artist=#{URI.encode(artist)}&album=#{URI.encode(album)}&format=json"
|
49
|
+
res = JSON.parse(HTTP.get(url))
|
50
|
+
|
51
|
+
begin
|
52
|
+
res.album
|
53
|
+
rescue
|
54
|
+
puts "Album does not exist."
|
55
|
+
end
|
56
|
+
end
|
47
57
|
|
48
58
|
def token
|
49
59
|
url = "http://ws.audioscrobbler.com/2.0/?method=auth.getToken&api_key=#{@keys.public}&api_sig=#{@keys.private}&format=json"
|
@@ -56,6 +66,7 @@ class Lily
|
|
56
66
|
lastfmURL = "http://www.last.fm/api/auth/?api_key=#{@keys.public}&token=#{@token}"
|
57
67
|
print "Press Enter once you've given access..."
|
58
68
|
Launchy.open(lastfmURL)
|
69
|
+
STDIN.gets
|
59
70
|
end
|
60
71
|
|
61
72
|
def session_key
|
@@ -70,25 +81,170 @@ class Lily
|
|
70
81
|
end
|
71
82
|
|
72
83
|
def scrobble
|
73
|
-
#
|
74
|
-
|
75
|
-
|
76
|
-
url = "http://ws.audioscrobbler.com/2.0/"
|
84
|
+
# last.fm/api/show/track.scrobble
|
85
|
+
command = @args.shift
|
77
86
|
timestamp = Time.now.utc.to_i # UTC time since unix epoch in seconds
|
78
87
|
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
"sk" => @lily_json.session_key,
|
83
|
-
"timestamp" => timestamp,
|
84
|
-
"track" => track,
|
85
|
-
"api_key" => @keys.public,
|
86
|
-
"format" => "json"
|
87
|
-
})
|
88
|
+
if command == "song"
|
89
|
+
# song
|
90
|
+
track, artist = @args[0], @args[1]
|
88
91
|
|
89
|
-
|
92
|
+
if @args[2] then album = @args[2] end # album name is optional
|
90
93
|
|
91
|
-
|
94
|
+
body = self.format_params({
|
95
|
+
"artist" => artist,
|
96
|
+
"method" => "track.scrobble",
|
97
|
+
"sk" => @lily_json.session_key,
|
98
|
+
"timestamp" => timestamp,
|
99
|
+
"track" => track,
|
100
|
+
"api_key" => @keys.public,
|
101
|
+
"format" => "json",
|
102
|
+
"album" => album
|
103
|
+
})
|
104
|
+
|
105
|
+
res = HTTP.post(@api_url, :body => body)
|
106
|
+
|
107
|
+
puts "#{track} by #{artist} has been scrobbled."
|
108
|
+
elsif command == "album"
|
109
|
+
# album
|
110
|
+
|
111
|
+
# we got eponymous albums covered :)
|
112
|
+
if @args[1] == nil then album, artist = @args[0], @args[0] else album, artist = @args[0], @args[1] end
|
113
|
+
|
114
|
+
album_info = get_album_info(album, artist)
|
115
|
+
album_length = 0
|
116
|
+
|
117
|
+
# get full length of album in seconds
|
118
|
+
album_info.tracks.track.each do |track|
|
119
|
+
album_length += track.duration.to_i
|
120
|
+
end
|
121
|
+
|
122
|
+
puts "Whole album length: #{album_length} seconds."
|
123
|
+
|
124
|
+
# set time when album should have started (a.k.a. album length ago), or if the '--live' option is specified then just start it right now
|
125
|
+
if @args[-1] == "--live" then time = timestamp else time = timestamp - album_length end
|
126
|
+
|
127
|
+
puts "Scrobbling your album starting at " + Time.at(time).utc.strftime("%I:%M:%S %p") + " UTC"
|
128
|
+
|
129
|
+
# begin scrobbling
|
130
|
+
album_info.tracks.track.each do |track|
|
131
|
+
time += track.duration.to_i
|
132
|
+
|
133
|
+
# scrobble track
|
134
|
+
body = self.format_params({
|
135
|
+
"artist" => track.artist.name,
|
136
|
+
"method" => "track.scrobble",
|
137
|
+
"sk" => @lily_json.session_key,
|
138
|
+
"timestamp" => time,
|
139
|
+
"track" => track.name,
|
140
|
+
"api_key" => @keys.public,
|
141
|
+
"format" => "json",
|
142
|
+
"album" => album_info.name
|
143
|
+
})
|
144
|
+
|
145
|
+
res = HTTP.post(@api_url, :body => body)
|
146
|
+
end
|
147
|
+
|
148
|
+
puts "#{album} by #{artist} has been scrobbled."
|
149
|
+
else
|
150
|
+
puts "huh"
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def love
|
155
|
+
# last.fm/api/show/track.love
|
156
|
+
command = @args.shift
|
157
|
+
|
158
|
+
if command == "song"
|
159
|
+
track, artist = @args[0], @args[1]
|
160
|
+
if @args[2] then album = @args[2] end # album name is optional
|
161
|
+
|
162
|
+
body = self.format_params({
|
163
|
+
"track" => track,
|
164
|
+
"artist" => artist,
|
165
|
+
"method" => "track.love",
|
166
|
+
"sk" => @lily_json.session_key,
|
167
|
+
"api_key" => @keys.public,
|
168
|
+
"format" => "json",
|
169
|
+
"album" => album
|
170
|
+
})
|
171
|
+
|
172
|
+
res = HTTP.post(@api_url, :body => body)
|
173
|
+
|
174
|
+
puts "#{track} by #{artist} has been loved ♥"
|
175
|
+
elsif command == "album"
|
176
|
+
# we've got you covered, eponymous albums
|
177
|
+
if @args[1] == nil then album, artist = @args[0], @args[0] else album, artist = @args[0], @args[1] end
|
178
|
+
|
179
|
+
album_info = get_album_info(album, artist)
|
180
|
+
album_length = 0
|
181
|
+
|
182
|
+
album_info.tracks.track.each do |track|
|
183
|
+
body = self.format_params({
|
184
|
+
"track" => track.name,
|
185
|
+
"artist" => artist,
|
186
|
+
"method" => "track.love",
|
187
|
+
"sk" => @lily_json.session_key,
|
188
|
+
"api_key" => @keys.public,
|
189
|
+
"format" => "json",
|
190
|
+
"album" => album
|
191
|
+
})
|
192
|
+
|
193
|
+
res = HTTP.post(@api_url, :body => body)
|
194
|
+
end
|
195
|
+
|
196
|
+
puts "#{album} by #{artist} has been loved ♥"
|
197
|
+
else
|
198
|
+
puts "huh"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
def unlove
|
203
|
+
# last.fm/api/show/track.unlove
|
204
|
+
command = @args.shift
|
205
|
+
|
206
|
+
if command == "song"
|
207
|
+
track, artist = @args[0], @args[1]
|
208
|
+
if @args[2] then album = @args[2] end # album name is optional
|
209
|
+
|
210
|
+
body = self.format_params({
|
211
|
+
"track" => track,
|
212
|
+
"artist" => artist,
|
213
|
+
"method" => "track.unlove",
|
214
|
+
"sk" => @lily_json.session_key,
|
215
|
+
"api_key" => @keys.public,
|
216
|
+
"format" => "json",
|
217
|
+
"album" => album
|
218
|
+
})
|
219
|
+
|
220
|
+
res = HTTP.post(@api_url, :body => body)
|
221
|
+
|
222
|
+
puts "#{track} by #{artist} has been unloved :("
|
223
|
+
elsif command == "album"
|
224
|
+
# we've got you covered, eponymous albums
|
225
|
+
if @args[1] == nil then album, artist = @args[0], @args[0] else album, artist = @args[0], @args[1] end
|
226
|
+
|
227
|
+
album_info = get_album_info(album, artist)
|
228
|
+
album_length = 0
|
229
|
+
|
230
|
+
album_info.tracks.track.each do |track|
|
231
|
+
body = self.format_params({
|
232
|
+
"track" => track.name,
|
233
|
+
"artist" => artist,
|
234
|
+
"method" => "track.unlove",
|
235
|
+
"sk" => @lily_json.session_key,
|
236
|
+
"api_key" => @keys.public,
|
237
|
+
"format" => "json",
|
238
|
+
"album" => album
|
239
|
+
})
|
240
|
+
|
241
|
+
res = HTTP.post(@api_url, :body => body)
|
242
|
+
end
|
243
|
+
|
244
|
+
puts "#{album} by #{artist} has been unloved :("
|
245
|
+
else
|
246
|
+
puts "huh"
|
247
|
+
end
|
92
248
|
end
|
93
249
|
|
94
250
|
def run
|
@@ -97,19 +253,29 @@ class Lily
|
|
97
253
|
case first
|
98
254
|
when 'scrobble' then self.scrobble
|
99
255
|
when 'init' then self.init
|
256
|
+
when 'love' then self.love
|
257
|
+
when 'unlove' then self.unlove
|
100
258
|
else self.help
|
101
259
|
end
|
102
260
|
end
|
103
261
|
|
104
262
|
def help
|
105
|
-
puts "
|
263
|
+
puts """
|
264
|
+
Lily, the Last.fm CLI.
|
265
|
+
|
266
|
+
Usage:
|
267
|
+
lily init
|
268
|
+
lily help
|
269
|
+
lily (scrobble | love | unlove) song (<song> <artist>) [<album>]
|
270
|
+
lily (love | unlove) album (<album> <artist> | <eponymous album>)
|
271
|
+
lily scrobble album (<album> <artist> | <eponymous album>) [--live]
|
272
|
+
"""
|
106
273
|
end
|
107
274
|
|
108
275
|
def init
|
109
276
|
auth
|
110
|
-
STDIN.gets # wow, hack
|
111
277
|
session_key
|
112
|
-
puts "Initialized successfully"
|
278
|
+
puts "Initialized ~/.lily.json successfully"
|
113
279
|
end
|
114
280
|
|
115
281
|
def version
|
data/lib/lily/version.rb
CHANGED
data/lily.gemspec
CHANGED
@@ -2,12 +2,11 @@
|
|
2
2
|
require File.expand_path('../lib/lily/version', __FILE__)
|
3
3
|
|
4
4
|
Gem::Specification.new do |gem|
|
5
|
-
gem.authors = ['Josh Trommel']
|
5
|
+
gem.authors = ['Josh Trommel', 'Ethan Arterberry']
|
6
6
|
gem.email = ['joshtrommel@gmail.com']
|
7
7
|
gem.description = 'A simple Last.fm client'
|
8
8
|
gem.summary = 'Last.fm\'s website is trash, and having a client for it is nice.'
|
9
9
|
gem.homepage = 'https://github.com/trmml/lily'
|
10
|
-
|
11
10
|
gem.files = `git ls-files`.split($\)
|
12
11
|
gem.executables = ['lily']
|
13
12
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
metadata
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lily
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.31
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Josh Trommel
|
8
|
+
- Ethan Arterberry
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date: 2016-03-
|
12
|
+
date: 2016-03-06 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
15
|
name: bundler
|