under_fire 0.6.1 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.ackrc +1 -0
- data/Changelog +2 -0
- data/README.md +142 -1
- data/lib/under_fire/album_fetch.rb +8 -8
- data/lib/under_fire/album_search.rb +12 -12
- data/lib/under_fire/album_toc_search.rb +6 -6
- data/lib/under_fire/api_request.rb +3 -3
- data/lib/under_fire/api_response.rb +4 -4
- data/lib/under_fire/base_query.rb +12 -8
- data/lib/under_fire/cli.rb +43 -24
- data/lib/under_fire/client.rb +22 -17
- data/lib/under_fire/configuration.rb +39 -11
- data/lib/under_fire/registration.rb +12 -7
- data/lib/under_fire/version.rb +1 -1
- data/spec/fixtures/.ufrc +3 -0
- data/spec/fixtures/album_response.xml +78 -0
- data/spec/lib/under_fire/album_fetch_spec.rb +6 -19
- data/spec/lib/under_fire/album_search_spec.rb +6 -13
- data/spec/lib/under_fire/album_toc_search_spec.rb +2 -11
- data/spec/lib/under_fire/cli_spec.rb +49 -0
- data/spec/lib/under_fire/configuration_spec.rb +33 -6
- data/spec/spec_helper.rb +1 -0
- data/todo.txt +0 -2
- data/under_fire.gemspec +2 -2
- metadata +24 -17
- data/lib/under_fire/toc_reader.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5e1d93ad915cfe697878585aedf307b541a00865
|
4
|
+
data.tar.gz: d1cda0cfee2c6b7ef2e661de7a2c2405b543d438
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f56978420c9b2efca82e1525d927f5247deb5781ab3751454e0148386314fd709290686a1f6c0cd90c13f59c4291d9c27b62d5303f30642ae21410a52ab47e8c
|
7
|
+
data.tar.gz: 2f4f939608621eb84705b0acdad307c0dc1c89280f1fbb2bd22db730e262148684447609b5d268940b9d8e44795f60b40f129a3086a5b20de3aa0865c99d685f
|
data/.ackrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--type=ruby
|
data/Changelog
ADDED
data/README.md
CHANGED
@@ -1,3 +1,144 @@
|
|
1
1
|
# UnderFire
|
2
2
|
|
3
|
-
Wraps Gracenote's API in Ruby goodness.
|
3
|
+
Wraps Gracenote's Web API in Ruby goodness. UnderFire provides two interfaces: a client to use from your projects and a command line interface.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
gem install under_fire
|
9
|
+
```
|
10
|
+
or in your gemfile:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem 'under_fire'
|
14
|
+
|
15
|
+
```
|
16
|
+
## Registration
|
17
|
+
|
18
|
+
Before using UnderFire, you need to obtain a `client_id` and `user_id` from Gracenote as described below.
|
19
|
+
|
20
|
+
### Obtain client_id
|
21
|
+
|
22
|
+
-To obtain a client_id, visit http://developer.gracenote.com and register yourself for a developer account. Once your account is created, go to "My Apps" and create a new app. Finaly, open your new app from your My Apps page to obtain your "Client ID for Mobile Client, Web API, and eyeQ".
|
23
|
+
|
24
|
+
-Now on your computer you need to add your `client_id` to your environment. On OSX or Linux you can do this by adding the following line to your `.bashrc`, `.zshrc` or wherever you prefer to set your environment variables:
|
25
|
+
|
26
|
+
```shell
|
27
|
+
export GRACENOTE_CLIENT_ID=your-client_id-here
|
28
|
+
|
29
|
+
```
|
30
|
+
After doing this, open a new terminal or type the following at the command prompt:
|
31
|
+
|
32
|
+
```
|
33
|
+
source ~/.bashrc
|
34
|
+
|
35
|
+
```
|
36
|
+
or
|
37
|
+
|
38
|
+
```
|
39
|
+
source ~/.zshrc
|
40
|
+
|
41
|
+
```
|
42
|
+
|
43
|
+
To test this out type the following in your terinal:
|
44
|
+
|
45
|
+
```
|
46
|
+
echo $GRACENOTE_CLIENT_ID
|
47
|
+
|
48
|
+
```
|
49
|
+
|
50
|
+
### Obtain user_id
|
51
|
+
|
52
|
+
-Now you're ready to use UnderFire's register task to obtain your `user_id`. At the command prompt, type:
|
53
|
+
|
54
|
+
```
|
55
|
+
under-fire register -c `echo $GRACENOTE_CLIENT_ID`
|
56
|
+
|
57
|
+
```
|
58
|
+
Copy your `user_id` from the output and add to your environment by entering the folloing in your `.bashrc` or `.zshrc` as you did with your `client_id` above:
|
59
|
+
|
60
|
+
```shell
|
61
|
+
export GRACENOTE_USER_ID=your-user_id-here
|
62
|
+
|
63
|
+
```
|
64
|
+
Once again, ensure that your current environment is up to date by opening a new terminal or sourcing the appropriate config file.
|
65
|
+
|
66
|
+
Now you're ready to get started.
|
67
|
+
|
68
|
+
## Usage
|
69
|
+
|
70
|
+
### Command line
|
71
|
+
|
72
|
+
UnderFire provides a command line interface (CLI) that makes it easy to explore the Gracenote Web API or combine with other UNIX tools in shell scripts. If you followed the registration instructions above, you've already used the CLI's registration task.
|
73
|
+
|
74
|
+
Here are some other things you can do:
|
75
|
+
|
76
|
+
Look up the album called "Armed Forces":
|
77
|
+
|
78
|
+
```
|
79
|
+
under-fire album -t "Armed Forces"
|
80
|
+
|
81
|
+
```
|
82
|
+
|
83
|
+
|
84
|
+
Look up "Armed Forces", fetch its cover art, and save it as "armed-forces.jpg in the current folder:
|
85
|
+
|
86
|
+
```
|
87
|
+
under-fire album -t "Armed Forces" | grep url | awk '{ print $2 }' | xargs under-fire cover -f "armed-forces.jpg" -u
|
88
|
+
|
89
|
+
```
|
90
|
+
For more information:
|
91
|
+
|
92
|
+
```
|
93
|
+
under-fire -h
|
94
|
+
|
95
|
+
```
|
96
|
+
If you want to search by a cd's table of contents, you need to provide the offset for each track on a given CD. To make things easy, I wrote a little gem called `cdtoc`. Just install this in the usual way:
|
97
|
+
|
98
|
+
```
|
99
|
+
gem install cdtoc
|
100
|
+
|
101
|
+
```
|
102
|
+
|
103
|
+
Then:
|
104
|
+
|
105
|
+
```
|
106
|
+
$ cdtoc | xargs under-fire -o
|
107
|
+
|
108
|
+
```
|
109
|
+
|
110
|
+
### Programming API
|
111
|
+
|
112
|
+
If you're familiar with the Gracenote API, you'll note that I have renamed the commands to make it easier to differentiate between them and to stay with idiomatic Ruby. So, for example, Gracenote's "ALBUM_SEARCH" is called `find_album`.
|
113
|
+
|
114
|
+
All requests, with the exception of `fetch_cover`, return an APIResponse class, which provides `to_h` and `to_s` methods. You will probably find the `to_h` method most convenient.
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
|
118
|
+
require 'under_fire/client'
|
119
|
+
|
120
|
+
# First, get a client instance
|
121
|
+
client = UnderFire::Client.new
|
122
|
+
|
123
|
+
# Search by track title
|
124
|
+
client.find_album(:track_title => 'Paranoid Android')
|
125
|
+
|
126
|
+
# or use either SINGLE_BEST or SINGLE_BEST_COVER
|
127
|
+
# SINGLE_BEST: returns the single best result as decided by Gracenote.
|
128
|
+
# SINGLE_BEST_COVER: same as above, but also returns cover URL. Currently this is the default.
|
129
|
+
|
130
|
+
album = client.find_album(:track_title => 'Paranoid Android', :mode => 'SINGLE_BEST')
|
131
|
+
|
132
|
+
# use query response to fetch the album cover.
|
133
|
+
client.fetch_cover(album, "OK_Computer_cover.jpg")
|
134
|
+
|
135
|
+
# The following searches by Gracenote album id or track id:
|
136
|
+
album = client.fetch_album(:gn_id => '86372321-2C7F28ADC369EB90E53A7F6CA3A70D56')
|
137
|
+
|
138
|
+
# If you want to limit your response to one album, use one of the two modes described above.
|
139
|
+
|
140
|
+
```
|
141
|
+
|
142
|
+
## Roadmap
|
143
|
+
|
144
|
+
More convenient APIResponse class that wraps artists and albums in their own classes.
|
@@ -7,7 +7,7 @@ module UnderFire
|
|
7
7
|
# @see https://developer.gracenote.com/sites/default/files/web/html/index.html#Music%20Web%20API/ALBUM_FETCH.html#_Toc344907262
|
8
8
|
#
|
9
9
|
# @example
|
10
|
-
# search = UnderFire::Album_Fetch.new(:gn_id => '86372321-2C7F28ADC369EB90E53A7F6CA3A70D56')
|
10
|
+
# search = UnderFire::Album_Fetch.new(:gn_id => '86372321-2C7F28ADC369EB90E53A7F6CA3A70D56')
|
11
11
|
# search.query => Response = The Beatles, Help!
|
12
12
|
class AlbumFetch < BaseQuery
|
13
13
|
# @return [String] XML string for query.
|
@@ -18,30 +18,30 @@ module UnderFire
|
|
18
18
|
|
19
19
|
# @return [String] Gracenote ID for album
|
20
20
|
attr_accessor :gn_id
|
21
|
-
|
21
|
+
|
22
22
|
# Requires album :gn_id or track :gn_id
|
23
23
|
#
|
24
24
|
# @param [Hash] args the arguments for Album_Fetch
|
25
25
|
# @option args [String] :gn_id Gracenote ID of album or track
|
26
|
-
# @option args [String] :mode Either 'SINGLE_BEST' or 'SINGLE_BEST_COVER'
|
26
|
+
# @option args [String] :mode Either 'SINGLE_BEST' or 'SINGLE_BEST_COVER'
|
27
27
|
# (Only needed if track :gn_id used)
|
28
28
|
def initialize(args)
|
29
29
|
super args
|
30
30
|
@parameters = args.reject {|k,v| k == :mode}
|
31
31
|
parameters.each do |k,v| send("#{k}=", v) end
|
32
|
-
@query = build_query
|
32
|
+
@query = build_query
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
# Builds ALBUM_FETCH-specific part of ALBUM_FETCH query and adds it to the base query
|
36
36
|
# common to all query types. Called by constructor.
|
37
37
|
#
|
38
38
|
# @return [String] XML string for ALBUM_FETCH query.
|
39
39
|
def build_query
|
40
40
|
build_base_query do |builder|
|
41
|
-
builder.
|
42
|
-
builder.
|
41
|
+
builder.QUERY(cmd: "ALBUM_FETCH"){
|
42
|
+
builder.MODE "SINGLE_BEST_COVER"
|
43
43
|
parameters.each do |k,v|
|
44
|
-
builder.
|
44
|
+
builder.GN_ID gn_id
|
45
45
|
end
|
46
46
|
}
|
47
47
|
end
|
@@ -2,20 +2,20 @@ require 'under_fire/base_query'
|
|
2
2
|
require 'builder'
|
3
3
|
|
4
4
|
module UnderFire
|
5
|
-
# Builds XML for Gracenote's ALBUM_SEARCH query.
|
5
|
+
# Builds XML for Gracenote's ALBUM_SEARCH query.
|
6
6
|
#
|
7
7
|
# @see https://developer.gracenote.com/sites/default/files/web/html/index.html#Music%20Web%20API/ALBUM_SEARCH.html#_Toc344907249
|
8
|
-
#
|
8
|
+
#
|
9
9
|
# @example
|
10
10
|
# search = UnderFire::AlbumSearch.new(:artist => 'Radiohead')
|
11
11
|
# search.query #=> XML for Gracenote ALBUM_SEARCH query for albums by Radiohead.
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# search = UnderFire::AlbumSearch.new(:track_title = > 'Paranoid Android',
|
14
14
|
# :artist => 'Radiohead',
|
15
15
|
# :mode => 'SINGLE_BEST_COVER')
|
16
|
-
# search.query #=> XML for ALBUM_SEARCH
|
17
|
-
#
|
18
|
-
#
|
16
|
+
# search.query #=> XML for ALBUM_SEARCH
|
17
|
+
#
|
18
|
+
#
|
19
19
|
class AlbumSearch < BaseQuery
|
20
20
|
# @return [String] XML string for query.
|
21
21
|
attr_reader :query
|
@@ -28,12 +28,12 @@ module UnderFire
|
|
28
28
|
|
29
29
|
# @return [String]
|
30
30
|
attr_accessor :track_title
|
31
|
-
|
31
|
+
|
32
32
|
# @return [String]
|
33
33
|
attr_accessor :album_title
|
34
|
-
|
34
|
+
|
35
35
|
# At least one of :artist, :track_title, :album_title is required (:mode is optional).
|
36
|
-
#
|
36
|
+
#
|
37
37
|
# @param [Hash] args the arguments for an Album_Search.
|
38
38
|
# @option args [String] :artist Name of the artist.
|
39
39
|
# @option args [String] :track_title Name of the song/track.
|
@@ -52,10 +52,10 @@ module UnderFire
|
|
52
52
|
# @return [String] XML string for ALBUM_SEARCH query.
|
53
53
|
def build_query
|
54
54
|
build_base_query do |builder|
|
55
|
-
builder.
|
56
|
-
builder.
|
55
|
+
builder.QUERY(CMD: "ALBUM_SEARCH"){
|
56
|
+
builder.MODE "SINGLE_BEST_COVER"
|
57
57
|
parameters.each do |k,v|
|
58
|
-
builder.
|
58
|
+
builder.TEXT(v, TYPE: k.to_s.upcase)
|
59
59
|
end
|
60
60
|
}
|
61
61
|
end
|
@@ -12,12 +12,12 @@ module UnderFire
|
|
12
12
|
class AlbumTOCSearch < BaseQuery
|
13
13
|
# @return [String] CD Table of contents.
|
14
14
|
attr_reader :toc
|
15
|
-
|
15
|
+
|
16
16
|
# @return [String] XML string for ALBUM_TOC query.
|
17
17
|
attr_reader :query
|
18
18
|
|
19
19
|
# :toc is required (:mode is optional).
|
20
|
-
#
|
20
|
+
#
|
21
21
|
# @param [Hash] args arguments to create an ALBUM_TOC query.
|
22
22
|
# @option [String] :toc CD table of contents (space-separated list of track start frames)
|
23
23
|
# @option [String] :mode Either 'SINGLE_BEST' or 'SINGLE_BEST_COVER'
|
@@ -33,10 +33,10 @@ module UnderFire
|
|
33
33
|
# @return [String] XML string for ALBUM_TOC query.
|
34
34
|
def build_query
|
35
35
|
build_base_query do |builder|
|
36
|
-
builder.
|
37
|
-
builder.
|
38
|
-
builder.
|
39
|
-
builder.
|
36
|
+
builder.QUERY(CMD: "ALBUM_TOC"){
|
37
|
+
builder.MODE mode
|
38
|
+
builder.TOC {
|
39
|
+
builder.OFFSETS toc.to_s
|
40
40
|
}
|
41
41
|
}
|
42
42
|
end
|
@@ -26,9 +26,9 @@ module UnderFire
|
|
26
26
|
req.body = query
|
27
27
|
req['Content-Type'] = 'application/xml'
|
28
28
|
res = http.request(req)
|
29
|
-
res
|
29
|
+
res
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
# @param [String] url URL that points to file.
|
33
33
|
# @param [String] filename Filename and path for saving downloaded file.
|
34
34
|
def self.get_file(url, filename)
|
@@ -36,7 +36,7 @@ module UnderFire
|
|
36
36
|
|
37
37
|
Net::HTTP.start(uri.host, uri.port) do |http|
|
38
38
|
request = Net::HTTP::Get.new uri
|
39
|
-
|
39
|
+
|
40
40
|
http.request request do |response|
|
41
41
|
open filename, 'w' do |io|
|
42
42
|
response.read_body do |chunk|
|
@@ -5,12 +5,12 @@ module UnderFire
|
|
5
5
|
class APIResponse
|
6
6
|
# @return [Hash] Response as Hash.
|
7
7
|
attr_reader :response
|
8
|
-
|
8
|
+
|
9
9
|
# @param [String] response XML string.
|
10
10
|
def initialize(response)
|
11
11
|
@response = parse_response(response)
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
# @return [Hash] Hash representation of response.
|
15
15
|
def to_h
|
16
16
|
response[:responses]
|
@@ -26,8 +26,8 @@ module UnderFire
|
|
26
26
|
response[:responses][:response][:@status] == 'OK'
|
27
27
|
end
|
28
28
|
|
29
|
-
private
|
30
|
-
|
29
|
+
private
|
30
|
+
|
31
31
|
# Recursively walks nested hash structure to return string representation.
|
32
32
|
# @return [String] Flat string representation of nest Hash.
|
33
33
|
def recursive_to_s(hash)
|
@@ -6,23 +6,27 @@ module UnderFire
|
|
6
6
|
class BaseQuery
|
7
7
|
# @return [String]
|
8
8
|
attr_reader :mode
|
9
|
-
|
9
|
+
|
10
|
+
# @return [UnderFire::Configuration]
|
11
|
+
attr_reader :config
|
12
|
+
|
10
13
|
# @param [String] mode Either 'SINGLE_BEST' or 'SINGLE_BEST_COVER' (defaults to 'SINGLE_BEST_COVER').
|
11
14
|
def initialize(mode="SINGLE_BEST_COVER")
|
12
15
|
@mode = mode || "SINGLE_BEST_COVER"
|
16
|
+
@config = Configuration.instance
|
13
17
|
end
|
14
18
|
|
15
19
|
# @yield [Builder] builder object used by subclass's build_query method.
|
16
20
|
def build_base_query(&block)
|
17
21
|
builder = Builder::XmlMarkup.new
|
18
|
-
builder.
|
19
|
-
builder.
|
20
|
-
builder.
|
21
|
-
builder.
|
22
|
+
builder.QUERIES {
|
23
|
+
builder.AUTH {
|
24
|
+
builder.CLIENT config.client_id
|
25
|
+
builder.USER config.user_id
|
22
26
|
}
|
23
|
-
builder.
|
24
|
-
builder.
|
25
|
-
builder.
|
27
|
+
builder.LANG "eng"
|
28
|
+
builder.COUNTRY "canada"
|
29
|
+
builder.APP_INFO %Q{APP="under-fire #{VERSION}", OS="#{RUBY_PLATFORM}"}
|
26
30
|
yield builder
|
27
31
|
}
|
28
32
|
end
|
data/lib/under_fire/cli.rb
CHANGED
@@ -1,25 +1,28 @@
|
|
1
1
|
require 'thor'
|
2
2
|
require 'under_fire/api_request'
|
3
|
-
require 'under_fire/
|
4
|
-
require 'under_fire/album_toc_search'
|
5
|
-
require 'under_fire/album_search'
|
6
|
-
require 'under_fire/toc_reader'
|
3
|
+
require 'under_fire/client'
|
7
4
|
|
8
5
|
module UnderFire
|
9
6
|
# Command Line interface
|
10
7
|
class CLI < Thor
|
11
8
|
include UnderFire
|
12
9
|
|
10
|
+
attr_reader :config, :client
|
11
|
+
|
13
12
|
def initialize(*)
|
14
13
|
super
|
14
|
+
@config = Configuration.instance
|
15
|
+
@client = Client.new()
|
15
16
|
end
|
16
17
|
|
17
|
-
desc "toc", "
|
18
|
-
|
18
|
+
desc "toc", "Use provided offsets to query Gracenote for album information."
|
19
|
+
method_option :offsets,
|
20
|
+
:aliases => '-o',
|
21
|
+
:desc => "Specify cd table of contents offsets",
|
22
|
+
:required => true,
|
23
|
+
:type => :array
|
19
24
|
def toc
|
20
|
-
|
21
|
-
response = APIRequest.post(search.query, Configuration.api_url)
|
22
|
-
say APIResponse.new(response.body).to_s
|
25
|
+
say client.find_by_toc(options[:offsets])
|
23
26
|
end
|
24
27
|
|
25
28
|
desc "album", "Queries Gracenote with album <title>, <song> title, or <artist> name"
|
@@ -36,31 +39,47 @@ module UnderFire
|
|
36
39
|
:desc => "Specify artist name",
|
37
40
|
:required => false
|
38
41
|
def album
|
39
|
-
|
40
|
-
request = APIRequest.post(search.query, Configuration.api_url)
|
41
|
-
say APIResponse.new(request.body).to_s
|
42
|
+
say client.find_album(options)
|
42
43
|
end
|
43
|
-
|
44
|
-
desc "id", "
|
45
|
-
method_option :gn_id,
|
44
|
+
|
45
|
+
desc "id", "Not yet implemented"
|
46
|
+
method_option :gn_id,
|
47
|
+
:aliases => ['-i', '--id'],
|
48
|
+
:required => true,
|
46
49
|
:desc => "Gracenote album or song GN_ID"
|
47
50
|
def id
|
48
|
-
|
49
|
-
|
50
|
-
say APIResponse.new(request.body).to_s
|
51
|
-
end
|
51
|
+
puts "Not implemented"
|
52
|
+
end
|
52
53
|
|
53
54
|
desc "cover", "Gets cover from Gracenote."
|
54
|
-
method_option :url,
|
55
|
+
method_option :url,
|
56
|
+
:aliases => '-u',
|
57
|
+
:required => true,
|
55
58
|
:desc => "URL provided by Gracenote for downloading cover image."
|
56
|
-
method_option :file_name,
|
57
|
-
:
|
59
|
+
method_option :file_name,
|
60
|
+
:aliases => '-f',
|
61
|
+
:required => false,
|
62
|
+
:desc => "File name for saving image.",
|
63
|
+
:default => ""
|
64
|
+
method_option :verbose,
|
65
|
+
:aliases => '-v',
|
66
|
+
:type => :boolean,
|
67
|
+
:required => false,
|
68
|
+
:default => false
|
58
69
|
def cover
|
59
|
-
say "Fetching cover"
|
70
|
+
say "Fetching cover" if options[:verbose]
|
60
71
|
url = options[:url]
|
61
72
|
file_name = options[:file_name].empty? ? "cover.jpg" : options[:file_name]
|
62
73
|
APIRequest.get_file(url, file_name)
|
63
|
-
say "saved #{file_name} in #{File.dirname __FILE__}"
|
74
|
+
say "saved #{file_name} in #{File.dirname __FILE__}" if options[:verbose]
|
75
|
+
end
|
76
|
+
|
77
|
+
desc "register", "Registers user with client_id."
|
78
|
+
method_option :client_id,
|
79
|
+
:aliases => '-c',
|
80
|
+
:required => true
|
81
|
+
def register
|
82
|
+
say client.register(options[:client_id])
|
64
83
|
end
|
65
84
|
end
|
66
85
|
end
|
data/lib/under_fire/client.rb
CHANGED
@@ -4,7 +4,6 @@ require 'under_fire/album_fetch'
|
|
4
4
|
require 'under_fire/api_request'
|
5
5
|
require 'under_fire/api_response'
|
6
6
|
require 'under_fire/configuration'
|
7
|
-
require 'under_fire/toc_reader'
|
8
7
|
|
9
8
|
require 'pry'
|
10
9
|
|
@@ -14,9 +13,9 @@ module UnderFire
|
|
14
13
|
# @example
|
15
14
|
# client = UnderFire::Client.new
|
16
15
|
# client.album_search(:artist => 'Miles Davis') #=> lots of results
|
17
|
-
#
|
16
|
+
#
|
18
17
|
# client = UnderFire::Client.new
|
19
|
-
# client.find_by_toc
|
18
|
+
# client.find_by_toc space_delimited_toc_offsets
|
20
19
|
class Client
|
21
20
|
include UnderFire
|
22
21
|
|
@@ -24,18 +23,19 @@ module UnderFire
|
|
24
23
|
attr_reader :api_url
|
25
24
|
|
26
25
|
def initialize
|
27
|
-
@api_url = Configuration.api_url
|
26
|
+
@api_url = Configuration.instance.api_url
|
28
27
|
end
|
29
28
|
|
30
|
-
# Searches for album using
|
31
|
-
# @return [APIResponse]
|
29
|
+
# Searches for album using provided toc offsets.
|
30
|
+
# @return [APIResponse]
|
32
31
|
# @see UnderFire::AlbumTOCSearch
|
33
|
-
def find_by_toc
|
34
|
-
|
32
|
+
def find_by_toc(*offsets)
|
33
|
+
offsets = offsets.join(" ")
|
34
|
+
search = AlbumTOCSearch.new(:toc => offsets)
|
35
35
|
response = APIRequest.post(search.query, api_url)
|
36
36
|
APIResponse.new(response.body)
|
37
37
|
end
|
38
|
-
|
38
|
+
|
39
39
|
# Finds album using one or more of :artist, :track_title and :album_title
|
40
40
|
# @return [APIResponse]
|
41
41
|
# @see UnderFire::AlbumSearch Description of arguments.
|
@@ -44,7 +44,7 @@ module UnderFire
|
|
44
44
|
response = APIRequest.post(search.query, api_url)
|
45
45
|
APIResponse.new(response.body)
|
46
46
|
end
|
47
|
-
|
47
|
+
|
48
48
|
# Fetches album with given album :gn_id or track :gn_id
|
49
49
|
# @return [APIResponse]
|
50
50
|
# @see UnderFire::AlbumFetch Description of arguments.
|
@@ -54,19 +54,24 @@ module UnderFire
|
|
54
54
|
APIResponse.new(response.body)
|
55
55
|
end
|
56
56
|
|
57
|
+
# Registers user with given client_id
|
58
|
+
# @return [APIResponse]
|
59
|
+
# @see UnderFire::Registration Description of arguments
|
60
|
+
def register(client_id)
|
61
|
+
search = Registration.new(client_id)
|
62
|
+
response = APIRequest.post(search.query, api_url)
|
63
|
+
APIResponse.new(response.body)
|
64
|
+
end
|
65
|
+
|
57
66
|
# Fetches cover art using results of query.
|
58
67
|
# @param [APIResponse] response
|
59
|
-
def fetch_cover(response)
|
68
|
+
def fetch_cover(response, file_name)
|
60
69
|
res = response.to_h
|
61
70
|
response_url = res['RESPONSE']['ALBUM']['URL']
|
62
71
|
title = res['RESPONSE']['ALBUM']['TITLE']
|
63
|
-
|
64
|
-
end
|
65
|
-
|
66
|
-
private
|
72
|
+
file_name = file_name || "#{title}-cover.jpg"
|
67
73
|
|
68
|
-
|
69
|
-
TOCReader.read
|
74
|
+
APIRequest.get_file(response_url, filename)
|
70
75
|
end
|
71
76
|
end
|
72
77
|
end
|
@@ -1,30 +1,38 @@
|
|
1
|
+
require 'singleton'
|
2
|
+
|
1
3
|
module UnderFire
|
2
|
-
# Configuration information.
|
3
|
-
|
4
|
+
# Configuration information.
|
5
|
+
class Configuration
|
6
|
+
include Singleton
|
7
|
+
|
8
|
+
attr_reader :config_info
|
9
|
+
|
10
|
+
def initialize
|
11
|
+
@config_info = load_config
|
12
|
+
end
|
13
|
+
|
4
14
|
# Gracenote client id stored in environment variable.
|
5
15
|
# @return [String]
|
6
16
|
def client_id
|
7
|
-
|
17
|
+
config_info.fetch(:client_id, nil).to_s
|
8
18
|
end
|
9
19
|
|
10
20
|
# Part of client id before the hyphen (used by api_url).
|
11
21
|
# @return [String]
|
12
22
|
def client_id_string
|
13
|
-
|
14
|
-
ci_string
|
23
|
+
client_id.split('-')[0]
|
15
24
|
end
|
16
25
|
|
17
26
|
# Part of client id after hyphen
|
18
27
|
# @return [String]
|
19
28
|
def client_tag
|
20
|
-
|
21
|
-
ct
|
29
|
+
client_id.split('-')[1]
|
22
30
|
end
|
23
31
|
|
24
|
-
# Gracenote user id
|
32
|
+
# Gracenote user id
|
25
33
|
# @return [String]
|
26
34
|
def user_id
|
27
|
-
|
35
|
+
config_info.fetch(:user_id, nil).to_s
|
28
36
|
end
|
29
37
|
|
30
38
|
# Gracenote API url for use in queries.
|
@@ -33,7 +41,27 @@ module UnderFire
|
|
33
41
|
"https://c#{client_id_string}.web.cddbp.net/webapi/xml/1.0/"
|
34
42
|
end
|
35
43
|
|
36
|
-
|
37
|
-
|
44
|
+
# Returns true if user has a user_id
|
45
|
+
# @return [Boolean]
|
46
|
+
def authorized?
|
47
|
+
user_id != nil
|
48
|
+
end
|
49
|
+
|
50
|
+
# Returns true if user has a client_id and user_id
|
51
|
+
# @return [Boolean]
|
52
|
+
def configured?
|
53
|
+
client_id != nil && !authorized?
|
54
|
+
end
|
55
|
+
|
56
|
+
def reset
|
57
|
+
initialize
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def load_config
|
63
|
+
{:client_id => ENV['GRACENOTE_CLIENT_ID'],
|
64
|
+
:user_id => ENV['GRACENOTE_USER_ID']}
|
65
|
+
end
|
38
66
|
end
|
39
67
|
end
|
@@ -6,21 +6,26 @@ module UnderFire
|
|
6
6
|
#
|
7
7
|
# @see https://developer.gracenote.com/sites/default/files/web/html/index.html#Music%20Web%20API/Registration%20and%20Authentication.html#_Toc344907213
|
8
8
|
class Registration
|
9
|
-
# @return [String] XML string for query
|
9
|
+
# @return [String] XML string for query
|
10
10
|
attr_reader :query
|
11
|
-
|
12
|
-
|
11
|
+
|
12
|
+
# @return [String] Gracenote Client ID
|
13
|
+
attr_reader :client_id
|
14
|
+
|
15
|
+
# @param [String] client_id Gracenote Client ID.
|
16
|
+
def initialize(client_id)
|
17
|
+
@client_id = client_id
|
13
18
|
@query = build_query
|
14
19
|
end
|
15
|
-
|
20
|
+
|
16
21
|
# Builds XML for REGISTRATION query.
|
17
22
|
#
|
18
23
|
# @return [String] XML string for REGISTRATION
|
19
24
|
def build_query
|
20
25
|
builder = Builder::XmlMarkup.new
|
21
|
-
xml = builder.
|
22
|
-
builder.
|
23
|
-
builder.
|
26
|
+
xml = builder.QUERIES {
|
27
|
+
builder.QUERY(CMD: 'REGISTER'){
|
28
|
+
builder.CLIENT client_id
|
24
29
|
}
|
25
30
|
}
|
26
31
|
xml
|
data/lib/under_fire/version.rb
CHANGED
data/spec/fixtures/.ufrc
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
|
2
|
+
<RESPONSES>
|
3
|
+
<RESPONSE STATUS="OK">
|
4
|
+
<ALBUM><GN_ID>86372321-2C7F28ADC369EB90E53A7F6CA3A70D56</GN_ID>
|
5
|
+
<ARTIST>The Beatles</ARTIST>
|
6
|
+
<TITLE>Help!</TITLE>
|
7
|
+
<PKG_LANG>ENG</PKG_LANG>
|
8
|
+
<GENRE NUM="61364" ID="25332">60's Rock</GENRE>
|
9
|
+
<TRACK_COUNT>13</TRACK_COUNT>
|
10
|
+
<TRACK>
|
11
|
+
<TRACK_NUM>1</TRACK_NUM>
|
12
|
+
<GN_ID>86372322-05CF584F3265FA67F3E0C18987973C21</GN_ID>
|
13
|
+
<TITLE>Help!</TITLE>
|
14
|
+
</TRACK>
|
15
|
+
<TRACK>
|
16
|
+
<TRACK_NUM>2</TRACK_NUM>
|
17
|
+
<GN_ID>86372323-CA2905A4F82908C761E28472D3991EDF</GN_ID>
|
18
|
+
<TITLE>The Night Before</TITLE>
|
19
|
+
</TRACK>
|
20
|
+
<TRACK>
|
21
|
+
<TRACK_NUM>3</TRACK_NUM>
|
22
|
+
<GN_ID>86372324-10C31E8C4C6F7B841A045FF6434AB1B0</GN_ID>
|
23
|
+
<TITLE>You've Got To Hide Your Love Away</TITLE>
|
24
|
+
</TRACK>
|
25
|
+
<TRACK>
|
26
|
+
<TRACK_NUM>4</TRACK_NUM>
|
27
|
+
<GN_ID>86372325-60EE527589C23B2F648156AD400FF857</GN_ID>
|
28
|
+
<TITLE>I Need You</TITLE>
|
29
|
+
</TRACK>
|
30
|
+
<TRACK>
|
31
|
+
<TRACK_NUM>5</TRACK_NUM>
|
32
|
+
<GN_ID>86372326-8DAA1AC1B819C66A28E2CD0EAD9D8222</GN_ID>
|
33
|
+
<TITLE>Another Girl</TITLE>
|
34
|
+
</TRACK>
|
35
|
+
<TRACK>
|
36
|
+
<TRACK_NUM>6</TRACK_NUM>
|
37
|
+
<GN_ID>86372327-E0DC3EC15ACDFE8E6880329970F82B78</GN_ID>
|
38
|
+
<TITLE>You're Going To Lose That Girl</TITLE>
|
39
|
+
</TRACK>
|
40
|
+
<TRACK>
|
41
|
+
<TRACK_NUM>7</TRACK_NUM>
|
42
|
+
<GN_ID>86372328-CD35818A7400061D8BC4C08D32E0BB38</GN_ID>
|
43
|
+
<TITLE>Ticket To Ride</TITLE>
|
44
|
+
</TRACK>
|
45
|
+
<TRACK>
|
46
|
+
<TRACK_NUM>8</TRACK_NUM>
|
47
|
+
<GN_ID>86372329-50EB4C1E500F3F6C895D0F8C48B9663D</GN_ID>
|
48
|
+
<TITLE>Act Naturally</TITLE>
|
49
|
+
</TRACK>
|
50
|
+
<TRACK>
|
51
|
+
<TRACK_NUM>9</TRACK_NUM>
|
52
|
+
<GN_ID>86372330-E6FA805C5DBA2E571935B0B8A7978862</GN_ID>
|
53
|
+
<TITLE>It's Only Love</TITLE>
|
54
|
+
</TRACK>
|
55
|
+
<TRACK>
|
56
|
+
<TRACK_NUM>10</TRACK_NUM>
|
57
|
+
<GN_ID>86372331-3F0E4CF181963FB330FF2001775F0FE1</GN_ID>
|
58
|
+
<TITLE>You Like Me Too Much</TITLE>
|
59
|
+
</TRACK>
|
60
|
+
<TRACK>
|
61
|
+
<TRACK_NUM>11</TRACK_NUM>
|
62
|
+
<GN_ID>86372332-5744350BE1E7DF380118F4BD93A98AA4</GN_ID>
|
63
|
+
<TITLE>Tell Me What You See</TITLE>
|
64
|
+
</TRACK>
|
65
|
+
<TRACK>
|
66
|
+
<TRACK_NUM>12</TRACK_NUM>
|
67
|
+
<GN_ID>86372333-79F674F3FBB538148DEF9ECF56AD4180</GN_ID>
|
68
|
+
<TITLE>I've Just Seen A Face</TITLE>
|
69
|
+
</TRACK>
|
70
|
+
<TRACK>
|
71
|
+
<TRACK_NUM>13</TRACK_NUM>
|
72
|
+
<GN_ID>86372334-6EF61C66E4FE46B76C79D697159F0B97</GN_ID>
|
73
|
+
<TITLE>Yesterday</TITLE>
|
74
|
+
</TRACK>
|
75
|
+
<URL TYPE="COVERART" SIZE="MEDIUM">http://web.content.cddbp.net/cds/2.0?id=28088C817AD817CB&client=866304&class=cover&origin=front&size=medium&type=image/jpeg&tag=02-KSYB0rRmIy4UaXsdI4xheDiM0wIntXI9vxq0J9-tYN8uImMSkQ8hg</URL>
|
76
|
+
</ALBUM>
|
77
|
+
</RESPONSE>
|
78
|
+
</RESPONSES>
|
@@ -5,40 +5,27 @@ require 'ox'
|
|
5
5
|
module UnderFire
|
6
6
|
describe AlbumFetch do
|
7
7
|
subject {AlbumFetch.new(:gn_id => '7F28ADC369EB90E53A7F6CA3A70D56V')}
|
8
|
-
|
9
|
-
let(:xml){
|
10
|
-
'<queries>'+
|
11
|
-
'<auth>'+
|
12
|
-
'<client>1234454</client>'+
|
13
|
-
'<user>2353452345243545-454351435kj435j345434</user>'+
|
14
|
-
'</auth>'+
|
15
|
-
'<lang>eng</lang>'+
|
16
|
-
'<country>canada</country>'+
|
17
|
-
'<query cmd="album_fetch">'+
|
18
|
-
'<gn_id>7F28ADC369EB90E53A7F6CA3A70D56V</gn_id>'+
|
19
|
-
'</query>'+
|
20
|
-
'</queries>'}
|
21
8
|
|
22
9
|
before do
|
23
|
-
|
24
|
-
|
10
|
+
ENV['UF_CONFIG_PATH'] = File.expand_path('spec/fixtures/.ufrc')
|
11
|
+
@config = UnderFire::Configuration.instance
|
25
12
|
end
|
26
13
|
|
27
14
|
describe "instantiation" do
|
28
15
|
it "accepts an album GN_ID as input" do
|
29
|
-
AlbumFetch.new(:gn_id => '7F28ADC369EB90E53A7F6CA3A70D56V').must_be_kind_of UnderFire::AlbumFetch
|
16
|
+
AlbumFetch.new(:gn_id => '7F28ADC369EB90E53A7F6CA3A70D56V').must_be_kind_of UnderFire::AlbumFetch
|
30
17
|
end
|
31
18
|
end
|
32
19
|
|
33
20
|
describe "#query" do
|
34
|
-
|
21
|
+
|
35
22
|
it "returns properly formed xml" do
|
36
23
|
#`Ox.load` returns Ox::ParseError if xml is malformed
|
37
24
|
Ox.load(subject.query).must_be_kind_of Ox::Element
|
38
25
|
end
|
39
|
-
|
26
|
+
|
40
27
|
it "returns the correct xml query" do
|
41
|
-
subject.query.must_include "
|
28
|
+
subject.query.must_include "GN_ID"
|
42
29
|
subject.query.must_include "ALBUM_FETCH"
|
43
30
|
subject.query.must_include "7F28ADC369EB90E53A7F6CA3A70D56V"
|
44
31
|
end
|
@@ -8,21 +8,9 @@ module UnderFire
|
|
8
8
|
artist: "Radiohead",
|
9
9
|
track_title: "Paranoid Android",
|
10
10
|
album_title: "OK Computer")}
|
11
|
-
let(:xml){
|
12
|
-
'<queries><auth><client>1234454</client>'+
|
13
|
-
'<user>2353452345243545-454351435kj435j345434</user></auth>'+
|
14
|
-
'<lang>eng</lang><country>canada</country>'+
|
15
|
-
'<query cmd="ALBUM_SEARCH">'+
|
16
|
-
'<mode>SINGLE_BEST_COVER</mode>'+
|
17
|
-
'<text type="ALBUM_TITLE">OK Computer</text>'+
|
18
|
-
'<text type="TRACK_TITLE">Paranoid Android</text>'+
|
19
|
-
'<text type="ARTIST">Radiohead</text>'+
|
20
|
-
'</query></queries>'
|
21
|
-
}
|
22
11
|
|
23
12
|
before do
|
24
|
-
|
25
|
-
ENV['GRACENOTE_USER_ID'] = '2353452345243545-454351435kj435j345434'
|
13
|
+
ENV['UF_CONFIG_PATH'] = File.expand_path('spec/fixtures/.ufrc')
|
26
14
|
end
|
27
15
|
|
28
16
|
it "accepts a hash of arguments" do
|
@@ -35,6 +23,11 @@ module UnderFire
|
|
35
23
|
Ox.load(subject.query).must_be_kind_of Ox::Element
|
36
24
|
end
|
37
25
|
|
26
|
+
it "returns xml with an auth element" do
|
27
|
+
subject.query.must_include "<AUTH>"
|
28
|
+
subject.query.must_include "</AUTH>"
|
29
|
+
end
|
30
|
+
|
38
31
|
describe "with all fields" do
|
39
32
|
it "returns the correct xml query" do
|
40
33
|
subject.query.must_include "Radiohead"
|
@@ -8,18 +8,9 @@ module UnderFire
|
|
8
8
|
"110612 122590 132127 141685"}
|
9
9
|
subject {AlbumTOCSearch.new(toc: toc)}
|
10
10
|
|
11
|
-
let(:xml){
|
12
|
-
'<queries><auth><client>1234454</client>'+
|
13
|
-
'<user>2353452345243545-454351435kj435j345434</user></auth>'+
|
14
|
-
'<lang>eng</lang><country>canada</country>'+
|
15
|
-
'<query cmd="ALBUM_TOC">'+
|
16
|
-
'<mode>SINGLE_BEST_COVER</mode>'+
|
17
|
-
'<toc><offsets>' + toc + '</offsets></toc>'+
|
18
|
-
'</query></queries>'}
|
19
|
-
|
20
11
|
before do
|
21
|
-
|
22
|
-
|
12
|
+
ENV['UF_CONFIG_PATH'] = File.expand_path('spec/fixtures/.ufrc')
|
13
|
+
@config = UnderFire::Configuration.instance
|
23
14
|
end
|
24
15
|
|
25
16
|
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require_relative '../../spec_helper'
|
2
|
+
require 'rr'
|
3
|
+
|
4
|
+
module UnderFire
|
5
|
+
describe CLI do
|
6
|
+
before do
|
7
|
+
@cli = CLI.new
|
8
|
+
@stdout_old = $stdout
|
9
|
+
@stdin_old = $stdin
|
10
|
+
$stdout = StringIO.new
|
11
|
+
$stdin = StringIO.new
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
$stdout = @stdout_old
|
16
|
+
$stdin = @stdin_old
|
17
|
+
end
|
18
|
+
|
19
|
+
# describe "#register" do
|
20
|
+
# before do
|
21
|
+
# response_body = '<RESPONSES><RESPONSE STATUS="OK"><USER>user_id_string</USER></RESPONSE><RESPONSES>'
|
22
|
+
# stub_request(:post, "https://c.web.cddbp.net/webapi/xml/1.0/").
|
23
|
+
# with(:body => "<QUERIES><QUERY cmd=\"REGISTER\"><CLIENT></CLIENT></QUERY></QUERIES>",
|
24
|
+
# :headers => {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type'=>'application/xml', 'User-Agent'=>'Ruby'}).
|
25
|
+
# to_return(:status => 200, :body => response_body, :headers => {})
|
26
|
+
# stub.proxy(APIResponse).new(response_body) do |res|
|
27
|
+
# stub(res).success? { true }
|
28
|
+
# stub(res).to_h { { :response => { :user => "adfadsfasa-aq34rqfafafsfdasf"}}}
|
29
|
+
# end
|
30
|
+
# end
|
31
|
+
|
32
|
+
# it "works" do
|
33
|
+
# mock($stdout).puts "\nIn order to proceed, please obtain a Gracenote Client ID."
|
34
|
+
# mock($stdout).puts "\nTo obtain a Client ID:"
|
35
|
+
# mock($stdout).puts " 1) Register at http://developer.gracenote.com."
|
36
|
+
# mock($stdout).puts " 2) Click on Add a New App."
|
37
|
+
# mock($stdout).puts " 3) Obtain your 'Client ID for Mobile Client, Web API, and eyeQ'"
|
38
|
+
# mock($stdout).puts " from the App Details."
|
39
|
+
# mock($stdout).print "\nPlease press [Enter] once you have a Client ID. "
|
40
|
+
# mock($stdout).print "Enter your client id: "
|
41
|
+
# mock($stdin).gets {"2352352452454"}
|
42
|
+
# mock($stdin).gets
|
43
|
+
# mock($stdout).puts "Saved client_id to /home/jason/.ufrc"
|
44
|
+
# mock($stdout).puts "Saved user_id to /home/jason/.ufrc"
|
45
|
+
# @cli.register
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
end
|
49
|
+
end
|
@@ -1,18 +1,45 @@
|
|
1
1
|
require_relative '../../spec_helper'
|
2
|
+
require 'pry'
|
2
3
|
|
3
4
|
module UnderFire
|
4
5
|
describe Configuration do
|
6
|
+
let(:base_dir){File.expand_path(__FILE__ + "/../../..")}
|
7
|
+
let(:config_file){File.join(base_dir, 'fixtures/.ufrc')}
|
8
|
+
|
5
9
|
before do
|
6
|
-
ENV[
|
7
|
-
ENV[
|
10
|
+
ENV["GRACENOTE_USER_ID"] = "12354534"
|
11
|
+
ENV["GRACENOTE_CLIENT_ID"] = "1252545-34543523452345"
|
12
|
+
end
|
13
|
+
|
14
|
+
after do
|
15
|
+
Configuration.instance.reset
|
8
16
|
end
|
9
17
|
|
10
|
-
|
11
|
-
|
18
|
+
describe "a completed configuration" do
|
19
|
+
|
20
|
+
it "has a client_id" do
|
21
|
+
config = Configuration.instance
|
22
|
+
config.client_id.must_equal "1252545-34543523452345"
|
23
|
+
end
|
24
|
+
|
25
|
+
it "has a user_id" do
|
26
|
+
config = Configuration.instance
|
27
|
+
config.user_id.must_equal "12354534"
|
28
|
+
end
|
12
29
|
end
|
13
30
|
|
14
|
-
|
15
|
-
|
31
|
+
describe "unconfigured" do
|
32
|
+
before do
|
33
|
+
ENV["GRACENOTE_CLIENT_ID"] = ""
|
34
|
+
ENV["GRACENOTE_USER_ID"] = ""
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "#configured?" do
|
38
|
+
it "returns false if there are no credentials" do
|
39
|
+
config = Configuration.instance
|
40
|
+
config.configured?.must_equal false
|
41
|
+
end
|
42
|
+
end
|
16
43
|
end
|
17
44
|
end
|
18
45
|
end
|
data/spec/spec_helper.rb
CHANGED
data/todo.txt
CHANGED
data/under_fire.gemspec
CHANGED
@@ -21,12 +21,12 @@ Gem::Specification.new do |spec|
|
|
21
21
|
|
22
22
|
spec.add_development_dependency "bundler", "~> 1.3"
|
23
23
|
spec.add_development_dependency "rake"
|
24
|
-
spec.add_development_dependency "pry"
|
25
|
-
spec.add_development_dependency "pry-doc"
|
24
|
+
spec.add_development_dependency "pry-plus"
|
26
25
|
spec.add_development_dependency "minitest"
|
27
26
|
spec.add_development_dependency "guard-minitest"
|
28
27
|
spec.add_development_dependency "rr"
|
29
28
|
spec.add_development_dependency "minitest-doc_reporter", "~> 0.6.0"
|
29
|
+
spec.add_development_dependency "webmock"
|
30
30
|
spec.add_development_dependency "ox"
|
31
31
|
if RbConfig::CONFIG['target_os'] =~ /mswin|mingw|cygwi/
|
32
32
|
spec.add_development_dependency "wdm", ">= 0.1.0"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: under_fire
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Thompson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -39,7 +39,7 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name: pry
|
42
|
+
name: pry-plus
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - '>='
|
@@ -53,7 +53,7 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: minitest
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - '>='
|
@@ -67,7 +67,7 @@ dependencies:
|
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name: minitest
|
70
|
+
name: guard-minitest
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - '>='
|
@@ -81,7 +81,7 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: rr
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - '>='
|
@@ -95,33 +95,33 @@ dependencies:
|
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
|
-
name:
|
98
|
+
name: minitest-doc_reporter
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- -
|
101
|
+
- - ~>
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version:
|
103
|
+
version: 0.6.0
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- -
|
108
|
+
- - ~>
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version:
|
110
|
+
version: 0.6.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
112
|
+
name: webmock
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- -
|
115
|
+
- - '>='
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 0
|
117
|
+
version: '0'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- -
|
122
|
+
- - '>='
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 0
|
124
|
+
version: '0'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: ox
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -214,8 +214,10 @@ executables:
|
|
214
214
|
extensions: []
|
215
215
|
extra_rdoc_files: []
|
216
216
|
files:
|
217
|
+
- .ackrc
|
217
218
|
- .gitignore
|
218
219
|
- .ruby-version
|
220
|
+
- Changelog
|
219
221
|
- Gemfile
|
220
222
|
- Guardfile
|
221
223
|
- LICENSE.txt
|
@@ -233,8 +235,9 @@ files:
|
|
233
235
|
- lib/under_fire/client.rb
|
234
236
|
- lib/under_fire/configuration.rb
|
235
237
|
- lib/under_fire/registration.rb
|
236
|
-
- lib/under_fire/toc_reader.rb
|
237
238
|
- lib/under_fire/version.rb
|
239
|
+
- spec/fixtures/.ufrc
|
240
|
+
- spec/fixtures/album_response.xml
|
238
241
|
- spec/lib/under_fire/album_fetch_spec.rb
|
239
242
|
- spec/lib/under_fire/album_search_spec.rb
|
240
243
|
- spec/lib/under_fire/album_toc_search_spec.rb
|
@@ -242,6 +245,7 @@ files:
|
|
242
245
|
- spec/lib/under_fire/api_response.rb
|
243
246
|
- spec/lib/under_fire/api_response_spec.rb
|
244
247
|
- spec/lib/under_fire/base_query_spec.rb
|
248
|
+
- spec/lib/under_fire/cli_spec.rb
|
245
249
|
- spec/lib/under_fire/configuration_spec.rb
|
246
250
|
- spec/sample/response.xml
|
247
251
|
- spec/sample/toc.txt
|
@@ -274,6 +278,8 @@ signing_key:
|
|
274
278
|
specification_version: 4
|
275
279
|
summary: An unofficial wrapper for the Gracenote web API
|
276
280
|
test_files:
|
281
|
+
- spec/fixtures/.ufrc
|
282
|
+
- spec/fixtures/album_response.xml
|
277
283
|
- spec/lib/under_fire/album_fetch_spec.rb
|
278
284
|
- spec/lib/under_fire/album_search_spec.rb
|
279
285
|
- spec/lib/under_fire/album_toc_search_spec.rb
|
@@ -281,6 +287,7 @@ test_files:
|
|
281
287
|
- spec/lib/under_fire/api_response.rb
|
282
288
|
- spec/lib/under_fire/api_response_spec.rb
|
283
289
|
- spec/lib/under_fire/base_query_spec.rb
|
290
|
+
- spec/lib/under_fire/cli_spec.rb
|
284
291
|
- spec/lib/under_fire/configuration_spec.rb
|
285
292
|
- spec/sample/response.xml
|
286
293
|
- spec/sample/toc.txt
|
@@ -1,19 +0,0 @@
|
|
1
|
-
require 'discid'
|
2
|
-
|
3
|
-
module UnderFire
|
4
|
-
# Reads CD and returns table of contents (start frame of each track).
|
5
|
-
#
|
6
|
-
# @example
|
7
|
-
# UnderFire.TOCReader.read
|
8
|
-
class TOCReader
|
9
|
-
# @return [Array<String>] array of start frame strings
|
10
|
-
def self.read
|
11
|
-
device = "/dev/cdrom"
|
12
|
-
disc = DiscId.read(device)
|
13
|
-
toc = []
|
14
|
-
disc.tracks {|t| toc << t.offset.to_s}
|
15
|
-
toc.join(" ")
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|