red_haze 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. data/.gitignore +7 -0
  2. data/.rspec +2 -0
  3. data/Gemfile +4 -0
  4. data/Rakefile +1 -0
  5. data/config.template.yml +4 -0
  6. data/lib/red_haze/activity.rb +5 -0
  7. data/lib/red_haze/client.rb +58 -0
  8. data/lib/red_haze/collection.rb +16 -0
  9. data/lib/red_haze/comment.rb +6 -0
  10. data/lib/red_haze/group.rb +28 -0
  11. data/lib/red_haze/helpers/resource.rb +91 -0
  12. data/lib/red_haze/helpers.rb +8 -0
  13. data/lib/red_haze/me.rb +66 -0
  14. data/lib/red_haze/playlist.rb +6 -0
  15. data/lib/red_haze/request.rb +22 -0
  16. data/lib/red_haze/track.rb +23 -0
  17. data/lib/red_haze/user.rb +35 -0
  18. data/lib/red_haze/version.rb +3 -0
  19. data/lib/red_haze.rb +28 -0
  20. data/red_haze.gemspec +28 -0
  21. data/spec/fixtures/vcr_cassettes/collection_next.yml +348 -0
  22. data/spec/fixtures/vcr_cassettes/comment_sync.yml +56 -0
  23. data/spec/fixtures/vcr_cassettes/group_contributors.yml +55 -0
  24. data/spec/fixtures/vcr_cassettes/group_members.yml +55 -0
  25. data/spec/fixtures/vcr_cassettes/group_moderators.yml +55 -0
  26. data/spec/fixtures/vcr_cassettes/group_sync.yml +55 -0
  27. data/spec/fixtures/vcr_cassettes/group_users.yml +55 -0
  28. data/spec/fixtures/vcr_cassettes/me.yml +55 -0
  29. data/spec/fixtures/vcr_cassettes/me_activities.yml +429 -0
  30. data/spec/fixtures/vcr_cassettes/me_activities_limit.yml +127 -0
  31. data/spec/fixtures/vcr_cassettes/playlist.yml +60 -0
  32. data/spec/fixtures/vcr_cassettes/track_comments.yml +79 -0
  33. data/spec/fixtures/vcr_cassettes/track_favorite_get.yml +50 -0
  34. data/spec/fixtures/vcr_cassettes/track_favorite_put.yml +50 -0
  35. data/spec/fixtures/vcr_cassettes/track_favoriters.yml +172 -0
  36. data/spec/fixtures/vcr_cassettes/track_sync.yml +82 -0
  37. data/spec/fixtures/vcr_cassettes/track_unfavorite_put.yml +50 -0
  38. data/spec/fixtures/vcr_cassettes/user_comments.yml +89 -0
  39. data/spec/fixtures/vcr_cassettes/user_favorites.yml +479 -0
  40. data/spec/fixtures/vcr_cassettes/user_follow_put.yml +65 -0
  41. data/spec/fixtures/vcr_cassettes/user_followers.yml +431 -0
  42. data/spec/fixtures/vcr_cassettes/user_follows_.yml +104 -0
  43. data/spec/fixtures/vcr_cassettes/user_follows_get.yml +50 -0
  44. data/spec/fixtures/vcr_cassettes/user_groups.yml +66 -0
  45. data/spec/fixtures/vcr_cassettes/user_playlists.yml +482 -0
  46. data/spec/fixtures/vcr_cassettes/user_sync.yml +57 -0
  47. data/spec/fixtures/vcr_cassettes/user_unfollow_put.yml +54 -0
  48. data/spec/lib/red_haze/activity_spec.rb +18 -0
  49. data/spec/lib/red_haze/client_spec.rb +43 -0
  50. data/spec/lib/red_haze/collection_spec.rb +26 -0
  51. data/spec/lib/red_haze/comment_spec.rb +30 -0
  52. data/spec/lib/red_haze/group_spec.rb +57 -0
  53. data/spec/lib/red_haze/me_spec.rb +117 -0
  54. data/spec/lib/red_haze/playlist_spec.rb +41 -0
  55. data/spec/lib/red_haze/request_spec.rb +17 -0
  56. data/spec/lib/red_haze/track_spec.rb +96 -0
  57. data/spec/lib/red_haze/user_spec.rb +110 -0
  58. data/spec/lib/red_haze_spec.rb +13 -0
  59. data/spec/spec_helper.rb +45 -0
  60. metadata +212 -0
data/.gitignore ADDED
@@ -0,0 +1,7 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ config.yml
6
+ tags
7
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in hypem.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,4 @@
1
+ :client_id: CLIENT_ID
2
+ :client_secret: CLIENT_SECRET
3
+ :redirect_uri: http://myredirect.uri/
4
+
@@ -0,0 +1,5 @@
1
+ module RedHaze
2
+ class Activity
3
+ include Helpers::Resource
4
+ end
5
+ end
@@ -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,6 @@
1
+ module RedHaze
2
+ class Comment
3
+ include Helpers::Resource
4
+
5
+ end
6
+ 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
@@ -0,0 +1,8 @@
1
+ require_relative 'helpers/resource'
2
+
3
+ module RedHaze
4
+ module Helpers
5
+
6
+
7
+ end
8
+ end
@@ -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,6 @@
1
+ module RedHaze
2
+ class Playlist
3
+ include Helpers::Resource
4
+
5
+ end
6
+ 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
@@ -0,0 +1,3 @@
1
+ module RedHaze
2
+ VERSION = "0.0.1"
3
+ 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