red_haze 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|