dm_cloud 0.0.1 → 0.0.3

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/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # DmCloud
1
+ # DMCloud
2
2
 
3
3
  I created this gem to simplify request and responses from DailyMotion Cloud API.
4
4
  With this gem, you can :
@@ -23,9 +23,9 @@ Or install it yourself as:
23
23
 
24
24
  ## Usage
25
25
 
26
- First, your will need to specify your :user_id, :api_key and your security level.
27
- I used a file in `APP_ROOT/config/initializers/conf.rb`.
28
- You can note the securitylevel, for more information about it, take a look at ``
26
+ First, your will need to specify your :user_id, :api_key and your security level.
27
+ I used a file in `APP_ROOT/config/initializers/conf.rb`.
28
+ You can note the securitylevel, for more information about it, take a look at `lib/dm_cloud/signing.rb`.
29
29
 
30
30
  # DAILYMOTION CLOUD SETTINGS
31
31
  require 'dm_cloud'
@@ -39,23 +39,60 @@ You can note the securitylevel, for more information about it, take a look at ``
39
39
  :security_level => DMC_SECURITY_LEVEL
40
40
  })
41
41
 
42
-
43
-
44
- Second part, how to get you embed url :
42
+ Description of security levels :
43
+
44
+ * **None:**
45
+ The signed URL will be valid for everyone
46
+ * **ASNUM:**
47
+ The signed URL will only be valid for the AS of the end-user.
48
+ The ASNUM (for Autonomous System Number) stands for the network identification,
49
+ each ISP have a different ASNUM for instance.
50
+ * **IP:**
51
+ The signed URL will only be valid for the IP of the end-user.
52
+ This security level may wrongly block some users
53
+ which have their internet access load-balanced between several proxies.
54
+ This is the case in some office network or some ISPs.
55
+ * **User-Agent:**
56
+ Used in addition to one of the two former levels,
57
+ this level a limit on the exact user-agent of the end-user.
58
+ This is more secure but in some specific condition may lead to wrongly blocked users.
59
+ * **Use Once:**
60
+ The signed URL will only be usable once.
61
+ Note: should not be used with stream URLs.
62
+ * **Country:**
63
+ The URL can only be queried from specified countrie(s).
64
+ The rule can be reversed to allow all countries except some.
65
+ * **Referer:**
66
+ The URL can only be queried
67
+ if the Referer HTTP header contains a specified value.
68
+ If the URL contains a Referer header with a different value,
69
+ the request is refused. If the Referer header is missing,
70
+ the request is accepted in order to prevent from false positives as some browsers,
71
+ anti-virus or enterprise proxies may remove this header.
72
+ * **Delegate:**
73
+ This option instructs the signing algorithm
74
+ that security level information won’t be embeded into the signature
75
+ but gathered and lock at the first use.
76
+
77
+
78
+ Second part, get you embed url :
79
+ It will return a string containing the iframe with the DailyMotion Cloud player.
45
80
 
46
81
  DMCloud::Streaming.embed('your video id looks like a secret key')
47
82
 
48
- Or how to get your direct url :
83
+ Or how to get your direct url :
84
+ It will return a string containing the direct link to your file.
49
85
 
50
86
  DMCloud::Streaming.url('your video id', ['asset_name'], {options})
51
87
 
52
- The next parts will come soon, just need some time to finish its and create corresponding tests.
88
+ The next parts will come soon, just need some time to finish it
89
+ and create corresponding tests.
53
90
 
54
91
  ## Contributing
55
92
 
56
- Your welcome to share and enhance this gem.
57
- This is my first one (and not the last one) but I know some mistakes might be done by myself.
58
- I do my best and I'm open to all ideas or comments about my work.
93
+ Your welcome to share and enhance this gem.
94
+ This is my first one (and not the last one) but I know some mistakes might be done by myself.
95
+ I do my best and I'm open to all ideas or comments about my work.
59
96
 
60
97
  1. Fork it
61
98
  2. Create your feature branch (`git checkout -b my-new-feature`)
@@ -0,0 +1,132 @@
1
+ module DMCloud
2
+ module Builder
3
+ module Media
4
+ def self.create(url = '', assets_names = [], meta = {})
5
+ request = Hash.new
6
+
7
+ request['url'] = url
8
+
9
+ if not meta.empty?
10
+ request['meta'] = {}
11
+ request['meta']['author'] = meta[:author] if meta[:author]
12
+ request['meta']['author'] = meta[:title] if meta[:title]
13
+ end
14
+
15
+ request['assets_names'] = assets_names if not assets_names.empty?
16
+
17
+ request.rehash
18
+ end
19
+
20
+ def self.info(media_id, assets_names = ['source'], fields = {})
21
+ raise StandardError, "missing :media_id in params" unless media_id
22
+ request = Hash.new
23
+
24
+ puts 'media_id :' + media_id
25
+
26
+ # the media id
27
+ request['id'] = media_id
28
+ request['fields'] = []
29
+
30
+
31
+ # requested media meta datas
32
+ fields[:meta].each { |value| request['fields'] << "meta.#{value}" } if fields[:meta].present?
33
+
34
+ #the creation date as a unix timestamp
35
+ request['fields'] << 'created' if fields[:created]
36
+
37
+ # the url of the embed player
38
+ request['fields'] << 'embed_url' if fields[:embed_url]
39
+
40
+ # the ratio of the video frame as a float (eg: 16/9, 4/3, etc).
41
+ request['fields'] << 'frame_ratio' if fields[:frame_ratio]
42
+ # the worldwide statistics on the number of views
43
+ # request['fields'] << 'stats.global.last_week' if fields[:stats][:global]
44
+
45
+ # TODO: handle statistics request per country
46
+ # fields[:stats].each { |key| request << "meta.#{key.to_s}" } if fields[:meta].present?
47
+ # request['stats'][COUNTRY_CODE][TIME_INTERVAL] : the statistics on the number of views in a specific country (eg: stats.fr.total, stats.us.last_week, etc...)
48
+ # request['extended_stats'][COUNTRY_CODE][TIME_INTERVAL]
49
+
50
+ assets_names = ['source'] if assets_names.nil?
51
+ if not fields[:assets]
52
+ request = all_assets_fields(request, assets_names)
53
+ else
54
+ assets_names.each do |name|
55
+ fields[:assets].each { |value| request << "assets.#{name}.#{value.to_s}" }
56
+ end
57
+ end
58
+
59
+ request
60
+ end
61
+
62
+ def self.list(fields = {})
63
+ # raise StandardError, "missing :media_id in params" unless media_id
64
+ request = Hash.new
65
+
66
+ request['fields'] = []
67
+ # requested media meta datas
68
+ fields[:meta].each { |key| request << "meta.#{key.to_s}" } if fields[:meta].present?
69
+
70
+ #the creation date as a unix timestamp
71
+ request['fields'] << 'created' if fields[:created]
72
+
73
+ # the url of the embed player
74
+ request['fields'] << 'embed_url' if fields[:embed_url]
75
+
76
+ # the ratio of the video frame as a float (eg: 16/9, 4/3, etc).
77
+ request['fields'] << 'frame_ratio' if fields[:frame_ratio]
78
+
79
+ # TODO: handle global statistics request in another module
80
+ # the worldwide statistics on the number of views
81
+ # request << 'stats.global.last_week' if fields[:stats][:global]
82
+
83
+ # TODO: handle statistics request per country
84
+ # fields[:stats].each { |key| request << "meta.#{key.to_s}" } if fields[:meta].present?
85
+ # request['stats'][COUNTRY_CODE][TIME_INTERVAL] : the statistics on the number of views in a specific country (eg: stats.fr.total, stats.us.last_week, etc...)
86
+ # request['extended_stats'][COUNTRY_CODE][TIME_INTERVAL]
87
+
88
+ assets_names = ['source'] if assets_names.nil?
89
+ if not fields[:assets]
90
+ request = all_assets_fields(request, assets_names)
91
+ else
92
+ assets_names.each do |name|
93
+ fields[:assets].each { |value| request << "assets.#{name}.#{value.to_s}" }
94
+ end
95
+ end
96
+
97
+ request
98
+ end
99
+
100
+
101
+ protected
102
+ # This method exclude stats, but return all information for a media (video or images)
103
+ def self.all_assets_fields(request, assets_names)
104
+ assets_names.each do |name|
105
+ request['fields'] << "assets.#{name}.download_url"
106
+ request['fields'] << "assets.#{name}.status"
107
+ request['fields'] << "assets.#{name}.container"
108
+ request['fields'] << "assets.#{name}.duration"
109
+ request['fields'] << "assets.#{name}.global_bitrate"
110
+ request['fields'] << "assets.#{name}.video_codec"
111
+ request['fields'] << "assets.#{name}.video_width"
112
+ request['fields'] << "assets.#{name}.video_height"
113
+ request['fields'] << "assets.#{name}.video_bitrate"
114
+ request['fields'] << "assets.#{name}.video_rotation"
115
+ request['fields'] << "assets.#{name}.video_fps"
116
+ request['fields'] << "assets.#{name}.video_fps_mode"
117
+ request['fields'] << "assets.#{name}.video_aspect"
118
+ request['fields'] << "assets.#{name}.video_interlaced"
119
+ request['fields'] << "assets.#{name}.audio_codec"
120
+ request['fields'] << "assets.#{name}.audio_bitrate"
121
+ request['fields'] << "assets.#{name}.audio_nbr_channel"
122
+ request['fields'] << "assets.#{name}.audio_samplerate"
123
+ request['fields'] << "assets.#{name}.created"
124
+ request['fields'] << "assets.#{name}.file_extension"
125
+ request['fields'] << "assets.#{name}.file_size"
126
+ end
127
+ request
128
+ end
129
+
130
+ end
131
+ end
132
+ end
@@ -1,3 +1,5 @@
1
+ require 'dm_cloud/builder/media'
2
+
1
3
  module DMCloud
2
4
  class Media
3
5
  # Creates a new media object.
@@ -13,14 +15,14 @@ module DMCloud
13
15
  # when you set this parameter you must also set the url parameter
14
16
  # Return :
15
17
  # media_id: return the media id of the object
16
- def self.create(media_id)
17
- call = "media.create"
18
+ def self.create(options)
19
+ call_type = "media.create"
18
20
 
19
21
  params = {
20
- call: call,
21
- args: DMCloud::Builder::Media.create(args)
22
+ :call => call_type,
23
+ args: Builder::Media.create(options)
22
24
  }
23
- DMCloud::Request.execute(call, params)
25
+ DMCloud::Request.execute(call_type, params)
24
26
  end
25
27
 
26
28
  # Delete a media object with all its associated assets.
@@ -29,43 +31,55 @@ module DMCloud
29
31
  # id (media ID) – (required) the id of the media object you want to delete.
30
32
  # Return :
31
33
  # Nothing
32
- def self.delete
33
- call = "media.delete"
34
+ def self.delete(media_id)
35
+ call_type = "media.delete"
34
36
 
35
37
  params = {
36
- call: call,
38
+ :call => call_type,
37
39
  args: { id: media_id}
38
40
  }
39
- DMCloud::Request.execute(call, params)
41
+ DMCloud::Request.execute(call_type, params)
40
42
  end
41
43
 
42
- def self.info(fields = [])
43
- call = "media.info"
44
+ # Gives information about a given media object.
45
+ #
46
+ # Params :
47
+ # media_id: (media ID) – (required) the id of the new media object.
48
+ # fields (Array) – (required) the list of fields to retrieve.
49
+ # Returns:
50
+ # a multi-level structure containing about the media related to the requested fields.
51
+ def self.info(media_id, assets_names = ['source'], fields = [])
52
+ call_type = "media.info"
44
53
 
45
54
  params = {
46
- call: call,
47
- args: DMCloud::Builder::Media.info(fields)
55
+ :call => call_type,
56
+ args: DMCloud::Builder::Media.info(media_id, assets_names, fields)
48
57
  }
49
- DMCloud::Request.execute(call, params)
58
+ DMCloud::Request.execute(call_type, params)
50
59
  end
51
60
 
52
- # Gives information about a given media object.
61
+ # Returns a paginated list of media info structures.
62
+ # You must specify the fields you want to retrieve.
63
+ # The fields are described in the documentation of the method info.
53
64
  #
54
- # Params :
55
- # media_id: (media ID) – (required) the id of the new media object.
56
- # fields (Array) – (required) the list of fields to retrieve.
57
- # Returns: a multi-level structure containing about the media related to the requested fields.
58
- Return type: Object
65
+ # Parameters:
66
+ # options:
67
+ # fields (Array) – (optional default return all informations) the fields to retrieve
68
+ # page (Integer) (optional) the page number, default: 1
69
+ # per_page (Integer) – (optional) the number of objet per page, default: 10
70
+ # Returns:
71
+ # an object with information for the pagination and the result of the query.
59
72
  def self.list(options = {})
60
- call = "media.list"
73
+ call_type = "media.list"
74
+
61
75
  page = options[:page].present? ? options[:page] : 1
62
76
  per_page = options[:per_page].present? ? options[:per_page] : 10
63
77
 
64
78
  params = {
65
- call: call,
79
+ :call => call_type,
66
80
  args: DMCloud::Builder::Media.list(options)
67
81
  }
68
- DMCloud::Request.execute(call, params)
82
+ DMCloud::Request.execute(call_type, params)
69
83
  end
70
84
 
71
85
  end
@@ -1,13 +1,38 @@
1
+ require 'net/http'
2
+
1
3
  module DMCloud
2
4
  class Request
3
5
 
6
+ DAILYMOTION_API = 'http://api.dmcloud.net/api'
7
+
8
+ def self.send_request(params)
9
+ puts 'params : ' + params.to_yaml
10
+ @uri = URI.parse(DAILYMOTION_API)
11
+
12
+ http = Net::HTTP.new(@uri.host, @uri.port)
13
+ request = Net::HTTP::Post.new(@uri.request_uri)
14
+ # request.basic_auth @uri.user, @uri.password
15
+ request.content_type = 'application/json'
16
+ request.body = params.to_json
17
+
18
+ puts 'request : ' + request.to_yaml
19
+
20
+ http.request(request).body
21
+
22
+ end
23
+
4
24
 
5
25
  def self.execute(call, params = {})
6
- request = DMCloud.identify(params)
26
+ request = DMCloud::Signing.identify(params)
7
27
  params.merge!({'auth' => request})
8
- result = DMCloud::Request.new(params)
9
- DMCloud::Response.parse(call, result)
28
+ result = send_request(params)
29
+ parse_response(result)
10
30
  end
11
31
 
32
+ def self.parse_response(result)
33
+ puts 'result : ' + result.to_yaml
34
+ end
35
+
36
+
12
37
  end
13
38
  end
@@ -1,5 +1,24 @@
1
1
  module DMCloud
2
2
  class Signing
3
+ # Generate auth token for request from Media
4
+ # Params:
5
+ # request: A hash of params generated from Media methods and Media::MetaData
6
+ # Result :
7
+ # return a string which contain the auth token for the request
8
+ # <url>?auth=<expires>-<sec>-<nonce>-<md5sum>[-<pub-sec-data>]
9
+ def self.identify(request)
10
+ user_id = DMCloud.config[:user_key]
11
+ api_key = DMCloud.config[:secret_key]
12
+
13
+ normalized_request = normalize(request).to_s
14
+ params = user_id + normalized_request + api_key
15
+
16
+ checksum = Digest::MD5.hexdigest(params)
17
+ auth_token = user_id + ':' + checksum
18
+
19
+ auth_token
20
+ end
21
+
3
22
  # To sign a URL, the client needs a secret shared with Dailymotion Cloud.
4
23
  # This secret is call client secret and is available in the back-office interface.
5
24
  # Params:
@@ -142,5 +161,11 @@ module DMCloud
142
161
  end
143
162
  result
144
163
  end
164
+
165
+ def self.normalize(params)
166
+ str = params.to_json.to_s
167
+ str.gsub!(/[^A-Za-z0-9]/, '')
168
+ str
169
+ end
145
170
  end
146
171
  end
@@ -1,3 +1,3 @@
1
1
  module DMCloud
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/dm_cloud.rb CHANGED
@@ -36,14 +36,6 @@ module DMCloud
36
36
  @@config
37
37
  end
38
38
 
39
- def self.identify(request)
40
- user_id = @@config[:user_id]
41
- api_key = @@config[:api_key]
42
- checksum = md5(user_id + normalize(request) + api_key)
43
-
44
- auth_token = user_id + ':' + checksum
45
- end
46
-
47
39
  def self.create_has_library(library)
48
40
  define_singleton_method("has_#{library}?") do
49
41
  cv="@@#{library}"
@@ -58,9 +50,9 @@ module DMCloud
58
50
  class_variable_get(cv)
59
51
  end
60
52
  end
61
-
62
- create_has_library :treaming
63
53
 
54
+ create_has_library :streaming
55
+ create_has_library :media
64
56
 
65
57
  class << self
66
58
  # Load a object saved on a file.
@@ -76,8 +68,9 @@ module DMCloud
76
68
  end
77
69
 
78
70
  autoload(:Streaming, 'dm_cloud/streaming')
79
-
80
-
71
+ autoload(:Media, 'dm_cloud/media')
72
+ autoload(:Request, 'dm_cloud/request')
73
+ autoload(:Signing, 'dm_cloud/signing')
81
74
  end
82
75
 
83
- Dir.glob('dm_cloud/**/*.rb').each{ |m| require File.dirname(__FILE__) + '/dm_cloud/' + m }
76
+ # Dir.glob('dm_cloud/**/*.rb').each{ |m| require File.dirname(__FILE__) + '/dm_cloud/' + m }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dm_cloud
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -26,6 +26,7 @@ files:
26
26
  - Rakefile
27
27
  - dm_cloud.gemspec
28
28
  - lib/dm_cloud.rb
29
+ - lib/dm_cloud/builder/media.rb
29
30
  - lib/dm_cloud/media.rb
30
31
  - lib/dm_cloud/request.rb
31
32
  - lib/dm_cloud/signing.rb