Robbie comes in
This commit is contained in:
commit
d2cb07cb4e
|
@ -0,0 +1 @@
|
|||
tmp
|
|
@ -0,0 +1,22 @@
|
|||
PATH
|
||||
remote: .
|
||||
specs:
|
||||
robbie (0.0.1)
|
||||
httparty
|
||||
oj
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
httparty (0.8.3)
|
||||
multi_json (~> 1.0)
|
||||
multi_xml
|
||||
multi_json (1.3.6)
|
||||
multi_xml (0.5.1)
|
||||
oj (1.3.4)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
robbie!
|
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 2012 Gregory Eremin
|
||||
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
@ -0,0 +1,71 @@
|
|||
# Robbie
|
||||
|
||||
Rovi API wrapper
|
||||
|
||||
## Installation
|
||||
|
||||
Add this line to your application's Gemfile:
|
||||
```ruby
|
||||
gem "robbie"
|
||||
```
|
||||
|
||||
And then execute:
|
||||
```bash
|
||||
$ bundle
|
||||
```
|
||||
|
||||
Or install it yourself as:
|
||||
```bash
|
||||
$ gem install robbie
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
*Working with models*
|
||||
```ruby
|
||||
require "robbie"
|
||||
Robbie.setup(api_key: "your api key", api_secret: "your api secret")
|
||||
|
||||
foo = Robbie::Artist.find_by_name("foo fighters")
|
||||
# <Robbie::Artist:0x007fb9cbd7c120 @id="MA0000002613", @name="Foo Fighters", @is_group=true, @genres=[#<Robbie::Genre:0x007fb9cbd7c2b0 @id="MA0000002613", @name="Pop/Rock">]>
|
||||
|
||||
# ...or directly by id
|
||||
foo = Robbie::Artist.find_by_name("MA0000002613")
|
||||
|
||||
foo.albums.last
|
||||
# <Robbie::Album:0x007fb9cc16b790 @id="MW0002115022", @title="Wasting Light">
|
||||
|
||||
# ...or directly by id
|
||||
Robbie::Album.find("MW0002115022")
|
||||
|
||||
foo.albums.last.tracks.first
|
||||
# <Robbie::Track:0x007fa633a39540 @id="MT0041016087", @disc_id=1, @position=1, @artists=[#<Robbie::Artist:0x007fa633a397e8 @id="MN0000184043", @name="Foo Fighters">], @title="Bridge Burning", @duration=286>
|
||||
|
||||
# ...or directly by id
|
||||
Robbie::Track.find("MT0041016087")
|
||||
```
|
||||
|
||||
Autocomplete and extended autocomplete
|
||||
```ruby
|
||||
Robbie::Autocomplete.complete("b")
|
||||
# ["Beyoncé", "Bruno Mars", "Bad Meets Evil", "Bon Iver", "Bob Marley", "Big Sean", "The Band Perry", "Blake Shelton", "B.O.B", "The Black Eyed Peas"]
|
||||
|
||||
Robbie::Autocomplete.predict("b").first
|
||||
# <Robbie::Artist:0x007fa633b31ba0 @id="MN0000761179", @name="Beyoncé", @is_group=false, @genres=[#<Robbie::Genre:0x007fa633b31e48 @id="MA0000002809", @name="R&B">]>
|
||||
```
|
||||
|
||||
*You can turn response caching*
|
||||
```ruby
|
||||
# on
|
||||
Robbie.enable_cache
|
||||
# and off
|
||||
Robbie.disable_cache
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork it
|
||||
2. Create your feature branch (`git checkout -b my-new-feature`)
|
||||
3. Commit your changes (`git commit -am 'Added some feature'`)
|
||||
4. Push to the branch (`git push origin my-new-feature`)
|
||||
5. Create new Pull Request
|
|
@ -0,0 +1,39 @@
|
|||
require "digest/md5"
|
||||
require "httparty"
|
||||
require "oj"
|
||||
require "multi_json"
|
||||
|
||||
require "robbie/version"
|
||||
require "robbie/parsers/base_parser"
|
||||
require "robbie/parsers/search"
|
||||
require "robbie/parsers/artist"
|
||||
require "robbie/parsers/album"
|
||||
require "robbie/parsers/track"
|
||||
require "robbie/models/base_model"
|
||||
require "robbie/models/artist"
|
||||
require "robbie/models/album"
|
||||
require "robbie/models/track"
|
||||
require "robbie/models/genre"
|
||||
require "robbie/autocomplete"
|
||||
|
||||
module Robbie
|
||||
@@cache_enabled = true
|
||||
class << self
|
||||
def setup(params)
|
||||
const_set(:API_KEY, params[:api_key])
|
||||
const_set(:API_SECRET, params[:api_secret])
|
||||
end
|
||||
|
||||
def enable_cache
|
||||
@@cache_enabled = true
|
||||
end
|
||||
|
||||
def disable_cache
|
||||
@@cache_enabled = false
|
||||
end
|
||||
|
||||
def cache_enabled?
|
||||
@@cache_enabled
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
module Robbie
|
||||
class Autocomplete
|
||||
class << self
|
||||
def complete(q)
|
||||
Parsers::Search.autocomplete(q)
|
||||
end
|
||||
|
||||
def predict(q)
|
||||
Parsers::Search.single_stage_search(q)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
module Robbie
|
||||
class Album < BaseModel
|
||||
attr_accessor :id, :title, :year, :tracks
|
||||
|
||||
class << self
|
||||
def search(q)
|
||||
Parsers::Search.search(q).keep_if { |item| item.instance_of?(Robbie::Album) }
|
||||
end
|
||||
end
|
||||
|
||||
def tracks
|
||||
@tracks ||= Parsers::Album.find(id).tracks
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,23 @@
|
|||
module Robbie
|
||||
class Artist < BaseModel
|
||||
attr_accessor :id, :name, :is_group, :genres, :albums
|
||||
|
||||
class << self
|
||||
def search(q)
|
||||
Parsers::Search.search(q).keep_if { |item| item.instance_of?(Robbie::Artist) }
|
||||
end
|
||||
|
||||
def find_by_name(name)
|
||||
search(name).first
|
||||
end
|
||||
|
||||
def find(id)
|
||||
Parsers::Artist.find(id)
|
||||
end
|
||||
end
|
||||
|
||||
def albums
|
||||
@albums ||= Parsers::Artist.find(id).albums
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,9 @@
|
|||
module Robbie
|
||||
class BaseModel
|
||||
def initialize(values)
|
||||
values.each do |key, val|
|
||||
send(:"#{key}=", val)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
module Robbie
|
||||
class Genre < BaseModel
|
||||
attr_accessor :id, :name
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
module Robbie
|
||||
class Track < BaseModel
|
||||
attr_accessor :id, :disc_id, :position, :artists, :title, :duration
|
||||
end
|
||||
end
|
|
@ -0,0 +1,48 @@
|
|||
module Robbie
|
||||
module Parsers
|
||||
class Album < BaseParser
|
||||
class << self
|
||||
def find(album_id)
|
||||
response = query("/data/v1/album/info", {
|
||||
albumid: album_id,
|
||||
include: "tracks"
|
||||
})
|
||||
parse(response["album"])
|
||||
end
|
||||
|
||||
def parse(data)
|
||||
return if data.nil?
|
||||
|
||||
album = parse_meta(data)
|
||||
if data["tracks"].is_a?(Array)
|
||||
current_disc = 0
|
||||
position = 0
|
||||
album.tracks = data["tracks"].map do |track|
|
||||
if track["disc"] && track["disc"] != current_disc
|
||||
position = 0
|
||||
current_disc = track["disc"]
|
||||
end
|
||||
position += 1
|
||||
|
||||
Parsers::Track.parse_meta(track, current_disc, position)
|
||||
end
|
||||
end
|
||||
album
|
||||
end
|
||||
|
||||
def parse_meta(data)
|
||||
return if data.nil?
|
||||
|
||||
params = {}
|
||||
params[:id] = data["ids"]["albumId"] if data["ids"]
|
||||
params[:title] = data["title"]
|
||||
if data["album"] && data["originalReleaseDate"].is_a?(String)
|
||||
params[:year] = data["originalReleaseDate"].split("-").first
|
||||
end
|
||||
|
||||
Robbie::Album.new(params)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,40 @@
|
|||
module Robbie
|
||||
module Parsers
|
||||
class Artist < BaseParser
|
||||
class << self
|
||||
def find(artist_id)
|
||||
response = query("/data/v1/name/info", {
|
||||
nameid: artist_id,
|
||||
include: "discography",
|
||||
type: "main"
|
||||
})
|
||||
parse(response["name"])
|
||||
end
|
||||
|
||||
def parse(data)
|
||||
return if data.nil?
|
||||
|
||||
artist = parse_meta(data)
|
||||
if data["discography"] && data["discography"].is_a?(Array)
|
||||
artist.albums = data["discography"].map{ |album| Parsers::Album.parse_meta(album) }.reverse
|
||||
end
|
||||
artist
|
||||
end
|
||||
|
||||
def parse_meta(data)
|
||||
return if data.nil?
|
||||
|
||||
params = {}
|
||||
params[:id] = data["ids"]["nameId"] if data["ids"]
|
||||
params[:name] = data["name"]
|
||||
params[:is_group] = data["isGroup"]
|
||||
params[:genres] = data["musicGenres"].map{ |genre|
|
||||
Robbie::Genre.new(id: genre["id"], name: genre["name"])
|
||||
} if data["musicGenres"].is_a?(Array)
|
||||
|
||||
Robbie::Artist.new(params)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,41 @@
|
|||
module Robbie
|
||||
module Parsers
|
||||
class BaseParser
|
||||
include HTTParty
|
||||
base_uri "api.rovicorp.com"
|
||||
format :json
|
||||
|
||||
class << self
|
||||
def sig
|
||||
Digest::MD5.hexdigest("#{API_KEY}#{API_SECRET}#{Time.now.to_i}")
|
||||
end
|
||||
|
||||
def query(path, params)
|
||||
unless Robbie.const_defined?(:API_KEY) and Robbie.const_defined?(:API_SECRET)
|
||||
raise Exception.new("No API credentials given")
|
||||
end
|
||||
|
||||
params_str = params
|
||||
.merge({ apikey: API_KEY, sig: sig, format: "json" })
|
||||
.map{ |key, val| "#{key}=#{val}" }.join("&")
|
||||
|
||||
if Robbie.cache_enabled?
|
||||
cache_key = "#{path}?#{params.inspect}".scan(/\w/).join
|
||||
cache_file = File.expand_path("../../../../tmp/cache/#{cache_key}", __FILE__)
|
||||
if File.exist?(cache_file)
|
||||
MultiJson.load(File.open(cache_file).read)
|
||||
else
|
||||
data = get("#{path}?#{params_str}")
|
||||
File.open(cache_file, "w") do |file|
|
||||
file.write(MultiJson.dump(data)) unless data.nil? or data.empty?
|
||||
end
|
||||
data
|
||||
end
|
||||
else
|
||||
get("#{path}?#{params_str}")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,45 @@
|
|||
module Robbie
|
||||
module Parsers
|
||||
class Search < BaseParser
|
||||
class << self
|
||||
def search(q)
|
||||
response = query("/search/v2.1/music/search", {
|
||||
query: q.gsub(" ", "%20"),
|
||||
entitytype: "artist&entitytype=album"
|
||||
})
|
||||
parse(response["searchResponse"]["results"])
|
||||
end
|
||||
|
||||
def single_stage_search(q)
|
||||
response = query("/search/v2.1/music/singlestagesearch", {
|
||||
query: q.gsub(" ", "%20"),
|
||||
entitytype: "artist&entitytype=album",
|
||||
size: 10
|
||||
})
|
||||
parse(response["searchResponse"]["results"])
|
||||
end
|
||||
|
||||
def parse(data)
|
||||
return if data.nil?
|
||||
|
||||
data.map do |result|
|
||||
if result["type"] == "artist"
|
||||
Parsers::Artist.parse_meta(result["name"])
|
||||
elsif result["type"] == "album"
|
||||
Parsers::Album.parse_meta(result["album"])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def autocomplete(q)
|
||||
response = query("/search/v2.1/music/autocomplete", {
|
||||
query: q.gsub(" ", "%20"),
|
||||
entitytype: "artist&entitytype=album",
|
||||
size: 10
|
||||
})
|
||||
response["autocompleteResponse"]["results"]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,34 @@
|
|||
module Robbie
|
||||
module Parsers
|
||||
class Track < BaseParser
|
||||
class << self
|
||||
def find(track_id)
|
||||
response = query("/data/v1/song/info", {
|
||||
trackid: track_id
|
||||
})
|
||||
|
||||
parse_meta(response["song"])
|
||||
end
|
||||
|
||||
def parse_meta(data, disc = nil, position = nil)
|
||||
return if data.nil?
|
||||
|
||||
params = {}
|
||||
params[:id] = data["ids"]["trackId"] if data["ids"]
|
||||
params[:disc_id] = disc
|
||||
params[:position] = position
|
||||
params[:artists] = data["performers"].map{ |performer|
|
||||
Robbie::Artist.new(id: performer["id"], name: performer["name"])
|
||||
} if data["performers"].is_a?(Array)
|
||||
params[:artists] = data["primaryArtists"].map{ |artist|
|
||||
Robbie::Artist.new(id: artist["id"], name: artist["name"])
|
||||
} if data["primaryArtists"].is_a?(Array)
|
||||
params[:title] = data["title"]
|
||||
params[:duration] = data["duration"]
|
||||
|
||||
Robbie::Track.new(params)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,3 @@
|
|||
module Robbie
|
||||
VERSION = "0.0.1"
|
||||
end
|
|
@ -0,0 +1,21 @@
|
|||
# encoding: UTF-8
|
||||
require File.expand_path('../lib/robbie/version', __FILE__)
|
||||
|
||||
Gem::Specification.new do |gem|
|
||||
gem.authors = ["Gregory Eremin"]
|
||||
gem.email = %w[ magnolia_fan@me.com ]
|
||||
gem.description = %q{ Rovi API wrapper }
|
||||
gem.summary = %q{ Rovi API wrapper }
|
||||
gem.homepage = "https://github.com/magnolia-fan/robbie"
|
||||
|
||||
gem.files = %x{ git ls-files }.split($\)
|
||||
gem.executables = gem.files.grep(%r{^bin/}).map{ |file| File.basename(file) }
|
||||
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
||||
gem.name = "robbie"
|
||||
gem.require_paths = %w[ lib ]
|
||||
gem.version = Robbie::VERSION
|
||||
gem.platform = Gem::Platform::RUBY
|
||||
|
||||
gem.add_dependency "httparty"
|
||||
gem.add_dependency "oj"
|
||||
end
|
Loading…
Reference in New Issue