optimizeplayer 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.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE +22 -0
  7. data/README.md +26 -0
  8. data/Rakefile +6 -0
  9. data/bin/console +14 -0
  10. data/bin/setup +7 -0
  11. data/lib/optimize_player.rb +45 -0
  12. data/lib/optimize_player/account.rb +24 -0
  13. data/lib/optimize_player/api_object.rb +161 -0
  14. data/lib/optimize_player/asset.rb +5 -0
  15. data/lib/optimize_player/client.rb +177 -0
  16. data/lib/optimize_player/converter.rb +16 -0
  17. data/lib/optimize_player/encoding.rb +5 -0
  18. data/lib/optimize_player/errors/api_connection_error.rb +7 -0
  19. data/lib/optimize_player/errors/api_error.rb +7 -0
  20. data/lib/optimize_player/errors/bad_request.rb +7 -0
  21. data/lib/optimize_player/errors/connection_error.rb +7 -0
  22. data/lib/optimize_player/errors/forbidden.rb +7 -0
  23. data/lib/optimize_player/errors/method_not_allowed.rb +7 -0
  24. data/lib/optimize_player/errors/optimize_player_error.rb +20 -0
  25. data/lib/optimize_player/errors/resource_not_found.rb +7 -0
  26. data/lib/optimize_player/errors/socket_error.rb +7 -0
  27. data/lib/optimize_player/errors/unauthorized.rb +7 -0
  28. data/lib/optimize_player/errors/unhandled_error.rb +7 -0
  29. data/lib/optimize_player/errors/unprocessable_entity.rb +7 -0
  30. data/lib/optimize_player/folder.rb +5 -0
  31. data/lib/optimize_player/integration.rb +5 -0
  32. data/lib/optimize_player/media_info.rb +5 -0
  33. data/lib/optimize_player/project.rb +24 -0
  34. data/lib/optimize_player/proxies/account_proxy.rb +24 -0
  35. data/lib/optimize_player/proxies/asset_proxy.rb +9 -0
  36. data/lib/optimize_player/proxies/base_proxy.rb +36 -0
  37. data/lib/optimize_player/proxies/folder_proxy.rb +9 -0
  38. data/lib/optimize_player/proxies/integration_proxy.rb +9 -0
  39. data/lib/optimize_player/proxies/project_proxy.rb +14 -0
  40. data/lib/optimize_player/signer.rb +142 -0
  41. data/lib/optimize_player/version.rb +3 -0
  42. data/lib/optimizeplayer.rb +2 -0
  43. data/optimize_player.gemspec +29 -0
  44. data/spec/client_spec.rb +305 -0
  45. data/spec/converter_spec.rb +63 -0
  46. data/spec/optimize_player_spec.rb +7 -0
  47. data/spec/proxy_spec.rb +67 -0
  48. data/spec/spec_helper.rb +2 -0
  49. metadata +175 -0
@@ -0,0 +1,16 @@
1
+ module OptimizePlayer
2
+ module Converter
3
+ def self.convert_to_object(context, response)
4
+ case response
5
+ when Array
6
+ response.map { |r| convert_to_object(context, r) }
7
+ when Hash
8
+ obj_klass = response['object_class']
9
+ klass = Object.const_get("OptimizePlayer::#{obj_klass}")
10
+ klass.construct_from(context, response)
11
+ else
12
+ response
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ module OptimizePlayer
2
+ class Encoding < ApiObject
3
+
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ module OptimizePlayer
2
+ module Errors
3
+ class APIConnectionError < OptimizePlayerError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module OptimizePlayer
2
+ module Errors
3
+ class ApiError < OptimizePlayerError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module OptimizePlayer
2
+ module Errors
3
+ class BadRequest < OptimizePlayerError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module OptimizePlayer
2
+ module Errors
3
+ class ConnectionError < OptimizePlayerError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module OptimizePlayer
2
+ module Errors
3
+ class Forbidden < OptimizePlayerError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module OptimizePlayer
2
+ module Errors
3
+ class MethodNotAllowed < OptimizePlayerError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,20 @@
1
+ module OptimizePlayer
2
+ module Errors
3
+ class OptimizePlayerError < StandardError
4
+ attr_reader :status
5
+ attr_reader :error
6
+ attr_reader :message
7
+
8
+ def initialize(status=nil, error=nil, message=nil)
9
+ @status = status
10
+ @error = error
11
+ @message = message
12
+ end
13
+
14
+ def to_s
15
+ status_string = status.nil? ? "" : "(Status #{status})"
16
+ "#{status_string} #{error} - #{message}"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ module OptimizePlayer
2
+ module Errors
3
+ class ResourceNotFound < OptimizePlayerError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module OptimizePlayer
2
+ module Errors
3
+ class SocketError < OptimizePlayerError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module OptimizePlayer
2
+ module Errors
3
+ class Unauthorized < OptimizePlayerError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module OptimizePlayer
2
+ module Errors
3
+ class UnhandledError < OptimizePlayerError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ module OptimizePlayer
2
+ module Errors
3
+ class UnprocessableEntity < OptimizePlayerError
4
+
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,5 @@
1
+ module OptimizePlayer
2
+ class Folder < ApiObject
3
+
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module OptimizePlayer
2
+ class Integration < ApiObject
3
+
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module OptimizePlayer
2
+ class MediaInfo < ApiObject
3
+
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ module OptimizePlayer
2
+ class Project < ApiObject
3
+ def inspect()
4
+ cid_string = (self.respond_to?(:cid) && !self.cid.nil?) ? " cid=#{self.cid}" : ""
5
+ "#<#{self.class}:0x#{self.object_id.to_s(16)}#{cid_string}> JSON: " + JSON.pretty_generate(@data)
6
+ end
7
+
8
+ def id
9
+ cid
10
+ end
11
+
12
+ def set_position(position)
13
+ response = context.client.send_request("projects/#{id}/set_position", :put, position: position)
14
+ refresh_from(response)
15
+ self
16
+ end
17
+
18
+ def toggle_favorite
19
+ response = context.client.send_request("projects/#{id}/toggle_favorite", :put)
20
+ refresh_from(response)
21
+ self
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,24 @@
1
+ module OptimizePlayer
2
+ module Proxies
3
+ class AccountProxy
4
+ attr_reader :client
5
+
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def inspect()
11
+ "#<#{self.class}:0x#{self.object_id.to_s(16)}"
12
+ end
13
+
14
+ def fetch
15
+ response = client.send_request(entity_name, :get)
16
+ Converter.convert_to_object(self, response)
17
+ end
18
+
19
+ def entity_name
20
+ 'account'
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,9 @@
1
+ module OptimizePlayer
2
+ module Proxies
3
+ class AssetProxy < BaseProxy
4
+ def entity_name
5
+ 'assets'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,36 @@
1
+ module OptimizePlayer
2
+ module Proxies
3
+ class BaseProxy
4
+ attr_reader :client
5
+
6
+ def initialize(client)
7
+ @client = client
8
+ end
9
+
10
+ def inspect()
11
+ "#<#{self.class}:0x#{self.object_id.to_s(16)}"
12
+ end
13
+
14
+ def all(attrs={})
15
+ response = client.send_request(entity_name, :get, attrs)
16
+ Converter.convert_to_object(self, response)
17
+ end
18
+
19
+ def find(id)
20
+ response = client.send_request("#{entity_name}/#{id}", :get)
21
+ Converter.convert_to_object(self, response)
22
+ end
23
+
24
+ def create(attrs)
25
+ response = client.send_request(entity_name, :post, attrs)
26
+ Converter.convert_to_object(self, response)
27
+ end
28
+
29
+ protected
30
+
31
+ def entity_name
32
+ raise NotImplementedError.new('You should implement actions on its subclasses')
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,9 @@
1
+ module OptimizePlayer
2
+ module Proxies
3
+ class FolderProxy < BaseProxy
4
+ def entity_name
5
+ 'folders'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module OptimizePlayer
2
+ module Proxies
3
+ class IntegrationProxy < BaseProxy
4
+ def entity_name
5
+ 'integrations'
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,14 @@
1
+ module OptimizePlayer
2
+ module Proxies
3
+ class ProjectProxy < BaseProxy
4
+ def move(attrs)
5
+ client.send_request("projects/move", :post, attrs)
6
+ true
7
+ end
8
+
9
+ def entity_name
10
+ 'projects'
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,142 @@
1
+ module OptimizePlayer
2
+ class Signer
3
+ attr_accessor :algorithm, :default_opts
4
+
5
+ def initialize(algorithm = "sha1", opts = {})
6
+ default_opts = {
7
+ :auth_scheme => "HMAC",
8
+ :auth_param => "auth",
9
+ :auth_header => "Authorization",
10
+ :auth_header_format => "%{auth_scheme} %{signature}",
11
+ :query_based => false,
12
+ :use_alternate_date_header => false,
13
+ :extra_auth_params => {},
14
+ :ignore_params => []
15
+ }
16
+ @algorithm = algorithm
17
+ opts[:nonce_header] ||="X-%{scheme}-Nonce" % {:scheme => (opts[:auth_scheme] || "HMAC")}
18
+ opts[:alternate_date_header] ||= "X-%{scheme}-Date" % {:scheme => (opts[:auth_scheme] || "HMAC")}
19
+ self.default_opts = default_opts.merge(opts)
20
+ end
21
+
22
+ def generate_signature(params)
23
+ secret = params.delete(:secret)
24
+ return if '' == secret.to_s
25
+
26
+ OpenSSL::HMAC.hexdigest(algorithm, secret, canonical_representation(params))
27
+ end
28
+
29
+ def validate_url_signature(url, secret, opts = {})
30
+ opts = default_opts.merge(opts)
31
+ opts[:query_based] = true
32
+
33
+ uri = parse_url(url)
34
+ query_values = Rack::Utils.parse_nested_query(uri.query)
35
+ return false unless query_values
36
+
37
+ auth_params = query_values.delete(opts[:auth_param])
38
+ return false unless auth_params
39
+
40
+ date = auth_params["date"]
41
+ nonce = auth_params["nonce"]
42
+ compare_hashes(auth_params["signature"], :secret => secret, :method => "GET", :path => uri.path, :date => date, :nonce => nonce, :query => query_values, :headers => {})
43
+ end
44
+
45
+ def canonical_representation(params)
46
+ rep = ""
47
+
48
+ rep << "#{params[:method].upcase}\n"
49
+ rep << "date:#{params[:date]}\n"
50
+ rep << "nonce:#{params[:nonce]}\n"
51
+
52
+ (params[:headers] || {}).sort.each do |pair|
53
+ name,value = *pair
54
+ rep << "#{name.downcase}:#{value}\n"
55
+ end
56
+
57
+ rep << params[:path]
58
+
59
+ p = (params[:query] || {}).dup
60
+
61
+ if !p.empty?
62
+ query = p.sort.map do |key, value|
63
+ "%{key}=%{value}" % {
64
+ :key => Rack::Utils.unescape(key.to_s),
65
+ :value => Rack::Utils.unescape(value.to_s)
66
+ }
67
+ end.join("&")
68
+ rep << "?#{query}"
69
+ end
70
+
71
+ rep
72
+ end
73
+
74
+ def sign_request(url, secret, opts = {})
75
+ opts = default_opts.merge(opts)
76
+
77
+ uri = parse_url(url)
78
+ headers = opts[:headers] || {}
79
+
80
+ date = opts[:date] || Time.now.gmtime
81
+ date = date.gmtime.strftime('%a, %d %b %Y %T GMT') if date.respond_to? :strftime
82
+
83
+ method = opts[:method] ? opts[:method].to_s.upcase : "GET"
84
+
85
+ query_values = Rack::Utils.parse_nested_query(uri.query)
86
+
87
+ if query_values
88
+ query_values.delete_if do |k,v|
89
+ opts[:ignore_params].one? { |param| (k == param) || (k == param.to_s) }
90
+ end
91
+ end
92
+
93
+ signature = generate_signature(:secret => secret, :method => method, :path => uri.path, :date => date, :nonce => opts[:nonce], :query => query_values, :headers => opts[:headers], :ignore_params => opts[:ignore_params])
94
+
95
+ if opts[:query_based]
96
+ auth_params = opts[:extra_auth_params].merge({
97
+ "date" => date,
98
+ "signature" => signature
99
+ })
100
+ auth_params[:nonce] = opts[:nonce] unless opts[:nonce].nil?
101
+
102
+ query_values ||= {}
103
+ query_values[opts[:auth_param]] = auth_params
104
+ uri.query = Rack::Utils.build_nested_query(query_values)
105
+ else
106
+ headers[opts[:auth_header]] = opts[:auth_header_format] % opts.merge({:signature => signature})
107
+ headers[opts[:nonce_header]] = opts[:nonce] unless opts[:nonce].nil?
108
+
109
+ if opts[:use_alternate_date_header]
110
+ headers[opts[:alternate_date_header]] = date
111
+ else
112
+ headers["Date"] = date
113
+ end
114
+ end
115
+
116
+ [headers, uri.to_s]
117
+ end
118
+
119
+ def sign_url(url, secret, opts = {})
120
+ opts = default_opts.merge(opts)
121
+ opts[:query_based] = true
122
+
123
+ headers, url = *sign_request(url, secret, opts)
124
+ url
125
+ end
126
+
127
+ private
128
+
129
+ def compare_hashes(presented, computed)
130
+ if computed.length == presented.length then
131
+ computed.chars.zip(presented.chars).map {|x,y| x == y}.all?
132
+ else
133
+ false
134
+ end
135
+ end
136
+
137
+ def parse_url(url)
138
+ return url if url.is_a?(URI)
139
+ URI.parse(url)
140
+ end
141
+ end
142
+ end