red_haze 0.0.1
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.
- data/.gitignore +7 -0
- data/.rspec +2 -0
- data/Gemfile +4 -0
- data/Rakefile +1 -0
- data/config.template.yml +4 -0
- data/lib/red_haze/activity.rb +5 -0
- data/lib/red_haze/client.rb +58 -0
- data/lib/red_haze/collection.rb +16 -0
- data/lib/red_haze/comment.rb +6 -0
- data/lib/red_haze/group.rb +28 -0
- data/lib/red_haze/helpers/resource.rb +91 -0
- data/lib/red_haze/helpers.rb +8 -0
- data/lib/red_haze/me.rb +66 -0
- data/lib/red_haze/playlist.rb +6 -0
- data/lib/red_haze/request.rb +22 -0
- data/lib/red_haze/track.rb +23 -0
- data/lib/red_haze/user.rb +35 -0
- data/lib/red_haze/version.rb +3 -0
- data/lib/red_haze.rb +28 -0
- data/red_haze.gemspec +28 -0
- data/spec/fixtures/vcr_cassettes/collection_next.yml +348 -0
- data/spec/fixtures/vcr_cassettes/comment_sync.yml +56 -0
- data/spec/fixtures/vcr_cassettes/group_contributors.yml +55 -0
- data/spec/fixtures/vcr_cassettes/group_members.yml +55 -0
- data/spec/fixtures/vcr_cassettes/group_moderators.yml +55 -0
- data/spec/fixtures/vcr_cassettes/group_sync.yml +55 -0
- data/spec/fixtures/vcr_cassettes/group_users.yml +55 -0
- data/spec/fixtures/vcr_cassettes/me.yml +55 -0
- data/spec/fixtures/vcr_cassettes/me_activities.yml +429 -0
- data/spec/fixtures/vcr_cassettes/me_activities_limit.yml +127 -0
- data/spec/fixtures/vcr_cassettes/playlist.yml +60 -0
- data/spec/fixtures/vcr_cassettes/track_comments.yml +79 -0
- data/spec/fixtures/vcr_cassettes/track_favorite_get.yml +50 -0
- data/spec/fixtures/vcr_cassettes/track_favorite_put.yml +50 -0
- data/spec/fixtures/vcr_cassettes/track_favoriters.yml +172 -0
- data/spec/fixtures/vcr_cassettes/track_sync.yml +82 -0
- data/spec/fixtures/vcr_cassettes/track_unfavorite_put.yml +50 -0
- data/spec/fixtures/vcr_cassettes/user_comments.yml +89 -0
- data/spec/fixtures/vcr_cassettes/user_favorites.yml +479 -0
- data/spec/fixtures/vcr_cassettes/user_follow_put.yml +65 -0
- data/spec/fixtures/vcr_cassettes/user_followers.yml +431 -0
- data/spec/fixtures/vcr_cassettes/user_follows_.yml +104 -0
- data/spec/fixtures/vcr_cassettes/user_follows_get.yml +50 -0
- data/spec/fixtures/vcr_cassettes/user_groups.yml +66 -0
- data/spec/fixtures/vcr_cassettes/user_playlists.yml +482 -0
- data/spec/fixtures/vcr_cassettes/user_sync.yml +57 -0
- data/spec/fixtures/vcr_cassettes/user_unfollow_put.yml +54 -0
- data/spec/lib/red_haze/activity_spec.rb +18 -0
- data/spec/lib/red_haze/client_spec.rb +43 -0
- data/spec/lib/red_haze/collection_spec.rb +26 -0
- data/spec/lib/red_haze/comment_spec.rb +30 -0
- data/spec/lib/red_haze/group_spec.rb +57 -0
- data/spec/lib/red_haze/me_spec.rb +117 -0
- data/spec/lib/red_haze/playlist_spec.rb +41 -0
- data/spec/lib/red_haze/request_spec.rb +17 -0
- data/spec/lib/red_haze/track_spec.rb +96 -0
- data/spec/lib/red_haze/user_spec.rb +110 -0
- data/spec/lib/red_haze_spec.rb +13 -0
- data/spec/spec_helper.rb +45 -0
- metadata +212 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/config.template.yml
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require "httparty"
|
2
|
+
|
3
|
+
module RedHaze
|
4
|
+
class Client
|
5
|
+
include HTTParty
|
6
|
+
attr_accessor :client_id, :client_secret, :redirect_uri,
|
7
|
+
:access_token, :expires_in, :refresh_token
|
8
|
+
|
9
|
+
TOKEN_ENDPOINT = "https://api.soundcloud.com/oauth2/token"
|
10
|
+
CONNECT_ENDPOINT = "https://soundcloud.com/connect"
|
11
|
+
|
12
|
+
def initialize(options={})
|
13
|
+
options_check(options)
|
14
|
+
update_from_response(options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def authorize_url
|
18
|
+
raise "Missing redirect_uri" unless redirect_uri
|
19
|
+
params = "client_id=#{client_id}&redirect_uri=#{redirect_uri}&response_type=code"
|
20
|
+
URI.encode "#{CONNECT_ENDPOINT}?#{params}"
|
21
|
+
end
|
22
|
+
|
23
|
+
def get_token_from_code(code)
|
24
|
+
body = { client_id: client_id,
|
25
|
+
client_secret: client_secret,
|
26
|
+
redirect_uri: redirect_uri,
|
27
|
+
code: code,
|
28
|
+
grant_type: 'authorization_code' }
|
29
|
+
|
30
|
+
response = self.class.post TOKEN_ENDPOINT, body: body,
|
31
|
+
headers: {'Content-Type' => 'application/x-www-form-urlencoded'}
|
32
|
+
|
33
|
+
raise response.inspect unless response.code == 200
|
34
|
+
update_from_response(response)
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def options_check(options)
|
41
|
+
keys = options.keys
|
42
|
+
unless (keys.include?(:client_id) && keys.include?(:client_secret)) ||
|
43
|
+
keys.include?(:access_token)
|
44
|
+
raise "missing client_id and client_secret, or access_token"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def update_from_response(response)
|
49
|
+
@client_id = response[:client_id]
|
50
|
+
@client_secret = response[:client_secret]
|
51
|
+
@redirect_uri = response[:redirect_uri]
|
52
|
+
@access_token = response[:access_token]
|
53
|
+
@expires_in = response[:expires_in]
|
54
|
+
@refresh_token = response[:refresh_token]
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module RedHaze
|
2
|
+
class Collection
|
3
|
+
include Helpers::Resource
|
4
|
+
attr_reader :items, :next_href, :future_href
|
5
|
+
def initialize(arg)
|
6
|
+
@items = arg['collection'].collect { |r| Activity.new(r) }
|
7
|
+
@next_href = arg['next_href']
|
8
|
+
@future_href = arg['future_href']
|
9
|
+
end
|
10
|
+
|
11
|
+
def next
|
12
|
+
self.class.new Request.get(@next_href)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module RedHaze
|
2
|
+
class Group
|
3
|
+
include Helpers::Resource
|
4
|
+
|
5
|
+
attr_reader :id
|
6
|
+
|
7
|
+
def members
|
8
|
+
get_endpoint("/members")
|
9
|
+
end
|
10
|
+
|
11
|
+
def moderators
|
12
|
+
get_endpoint("/moderators")
|
13
|
+
end
|
14
|
+
|
15
|
+
def contributors
|
16
|
+
get_endpoint("/contributors")
|
17
|
+
end
|
18
|
+
|
19
|
+
def contributors
|
20
|
+
get_endpoint("/contributors")
|
21
|
+
end
|
22
|
+
|
23
|
+
def users
|
24
|
+
get_endpoint("/users")
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module RedHaze
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
module Resource
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :id
|
10
|
+
|
11
|
+
def initialize(arg)
|
12
|
+
case arg
|
13
|
+
when Fixnum then @id = arg
|
14
|
+
when Hash then initialize_from_hash(arg)
|
15
|
+
else raise "Not a valid Resource initialize arg: #{arg.inspect}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def sync
|
20
|
+
initialize_from_hash Request.get(url)
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def get_endpoint(endpoint, args={})
|
25
|
+
self.class.import_from_response Request.get(url + endpoint, args)
|
26
|
+
end
|
27
|
+
|
28
|
+
def put_endpoint(endpoint, args={})
|
29
|
+
default_args = {headers: {'Content-Length' => "0"}}
|
30
|
+
args.merge! default_args
|
31
|
+
Request.put(url + endpoint, args).parsed_response
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete_endpoint(endpoint, args={})
|
35
|
+
Request.delete(url + endpoint, args).parsed_response
|
36
|
+
end
|
37
|
+
|
38
|
+
def url
|
39
|
+
class_name = self.class.name.downcase.split('::')[-1]
|
40
|
+
class_name == 'me' ? '/me' : "/#{class_name}s/#{id}"
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def initialize_from_hash(arg)
|
46
|
+
arg.each_pair do |key, value|
|
47
|
+
case key
|
48
|
+
when 'created_at'
|
49
|
+
value = DateTime.parse(value)
|
50
|
+
when 'user', 'creator', 'track', 'origin'
|
51
|
+
value = self.class.instance_from_hash(value)
|
52
|
+
when 'tags'
|
53
|
+
value = value.split(',')
|
54
|
+
end
|
55
|
+
instance_variable_set "@#{key}", value
|
56
|
+
self.class.class_eval { attr_reader key }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module ClassMethods
|
61
|
+
|
62
|
+
def instance_from_hash(arg)
|
63
|
+
case
|
64
|
+
when arg['kind']
|
65
|
+
class_name = arg.delete('kind').capitalize
|
66
|
+
eval(class_name).new(arg)
|
67
|
+
when arg['type']
|
68
|
+
Activity.new arg
|
69
|
+
when arg['collection']
|
70
|
+
Collection.new arg
|
71
|
+
when arg.values.first['kind']
|
72
|
+
instance_from_hash arg.values.first
|
73
|
+
else
|
74
|
+
raise arg.inspect
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
def import_from_response(response)
|
80
|
+
if response.is_a? Array
|
81
|
+
response.collect { |i| instance_from_hash(i) }
|
82
|
+
elsif response.is_a? Hash
|
83
|
+
instance_from_hash response
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/red_haze/me.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'red_haze/user'
|
2
|
+
|
3
|
+
module RedHaze
|
4
|
+
class Me < User
|
5
|
+
FILTERS = [:all, :tracks_affiliated, :tracks_exclusive, :own]
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
unless RedHaze.client.access_token
|
9
|
+
raise "You cannot access this object without a client access_token"
|
10
|
+
end
|
11
|
+
sync
|
12
|
+
end
|
13
|
+
|
14
|
+
def activities(args = {})
|
15
|
+
filter = args.delete(:filter) || :all
|
16
|
+
raise "Bad Activities filter: #{filter}" unless FILTERS.include?(filter)
|
17
|
+
|
18
|
+
filter = filter.to_s.sub('_','/')
|
19
|
+
|
20
|
+
get_endpoint("/activities/#{filter}", query: args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def follow!(arg)
|
24
|
+
put_endpoint "/followings/#{item_id(arg)}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def unfollow!(arg)
|
28
|
+
delete_endpoint "/followings/#{item_id(arg)}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def follows?(arg)
|
32
|
+
existence_check "/me/followings", arg
|
33
|
+
end
|
34
|
+
|
35
|
+
def favorite!(arg)
|
36
|
+
put_endpoint "/favorites/#{item_id(arg)}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def unfavorite!(arg)
|
40
|
+
delete_endpoint "/favorites/#{item_id(arg)}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def favorite?(arg)
|
44
|
+
existence_check "/me/favorites", arg
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def item_id(arg)
|
50
|
+
unless [RedHaze::User, RedHaze::Track, Fixnum].include?(arg.class)
|
51
|
+
raise ArgumentError
|
52
|
+
end
|
53
|
+
arg.is_a?(Fixnum) ? arg : arg.id
|
54
|
+
end
|
55
|
+
|
56
|
+
# if the resource exists, we are redirected to a 404 page
|
57
|
+
# this will rescue on the first redirect and thus return true
|
58
|
+
def existence_check(path, arg)
|
59
|
+
response = Request.get "#{path}/#{item_id(arg)}", no_follow: true
|
60
|
+
response.code == 200
|
61
|
+
rescue HTTParty::RedirectionTooDeep
|
62
|
+
true
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
|
3
|
+
module RedHaze
|
4
|
+
class Request
|
5
|
+
include HTTParty
|
6
|
+
debug_output
|
7
|
+
headers 'Accept' => 'application/json'
|
8
|
+
|
9
|
+
def self.setup(client_id,access_token=nil)
|
10
|
+
params = {}
|
11
|
+
if access_token
|
12
|
+
base_uri 'https://api.soundcloud.com'
|
13
|
+
params[:oauth_token] = access_token
|
14
|
+
else
|
15
|
+
base_uri 'http://api.soundcloud.com'
|
16
|
+
params[:client_id] = client_id
|
17
|
+
end
|
18
|
+
default_params params
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RedHaze
|
2
|
+
class Track
|
3
|
+
include Helpers::Resource
|
4
|
+
|
5
|
+
def favoriters
|
6
|
+
get_endpoint('/favoriters')
|
7
|
+
end
|
8
|
+
|
9
|
+
def comments
|
10
|
+
get_endpoint('/comments')
|
11
|
+
end
|
12
|
+
|
13
|
+
def shared_to
|
14
|
+
get_endpoint('/shared_to/users')
|
15
|
+
end
|
16
|
+
|
17
|
+
def owner
|
18
|
+
sync if user_id.nil?
|
19
|
+
User.new(user_id)
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module RedHaze
|
2
|
+
class User
|
3
|
+
include Helpers::Resource
|
4
|
+
|
5
|
+
def followings(user_id=nil)
|
6
|
+
if user_id.nil?
|
7
|
+
get_endpoint('/followings')
|
8
|
+
else
|
9
|
+
response = get("/followings/#{user_id}")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def followers
|
14
|
+
get_endpoint('/followers')
|
15
|
+
end
|
16
|
+
|
17
|
+
def comments
|
18
|
+
get_endpoint('/comments')
|
19
|
+
end
|
20
|
+
|
21
|
+
def favorites
|
22
|
+
get_endpoint('/favorites')
|
23
|
+
end
|
24
|
+
|
25
|
+
def groups
|
26
|
+
get_endpoint('/groups')
|
27
|
+
end
|
28
|
+
|
29
|
+
def playlists
|
30
|
+
get_endpoint('/playlists')
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/red_haze.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require "red_haze/version"
|
2
|
+
require 'red_haze/helpers'
|
3
|
+
require "red_haze/client"
|
4
|
+
require "red_haze/request"
|
5
|
+
require "red_haze/playlist"
|
6
|
+
require "red_haze/me"
|
7
|
+
require "red_haze/user"
|
8
|
+
require "red_haze/track"
|
9
|
+
require "red_haze/comment"
|
10
|
+
require "red_haze/group"
|
11
|
+
require "red_haze/activity"
|
12
|
+
require "red_haze/collection"
|
13
|
+
|
14
|
+
module RedHaze
|
15
|
+
class << self
|
16
|
+
attr_accessor :client
|
17
|
+
|
18
|
+
def configure(options = {})
|
19
|
+
@client = Client.new(options)
|
20
|
+
Request.setup(@client.client_id, @client.access_token)
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
def configure_from_file(path)
|
25
|
+
configure YAML.load_file(path)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/red_haze.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "red_haze/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "red_haze"
|
7
|
+
s.version = RedHaze::VERSION
|
8
|
+
s.authors = ["Jack Anderson"]
|
9
|
+
s.email = ["hi@janderson.me"]
|
10
|
+
s.homepage = "https://github.com/JackCA/red_haze"
|
11
|
+
s.summary = "a robust Ruby wrapper for the Soundcloud API"
|
12
|
+
|
13
|
+
s.rubyforge_project = "red_haze"
|
14
|
+
s.required_ruby_version = Gem::Requirement.new(">= 1.9.2")
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_development_dependency "webmock"
|
22
|
+
s.add_development_dependency "vcr"
|
23
|
+
s.add_development_dependency "rspec"
|
24
|
+
s.add_development_dependency "rake"
|
25
|
+
s.add_dependency 'httparty'
|
26
|
+
s.add_dependency 'multi_json'
|
27
|
+
|
28
|
+
end
|