dm_cloud 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 +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +64 -0
- data/Rakefile +1 -0
- data/dm_cloud.gemspec +19 -0
- data/lib/dm_cloud/media.rb +72 -0
- data/lib/dm_cloud/request.rb +13 -0
- data/lib/dm_cloud/signing.rb +146 -0
- data/lib/dm_cloud/streaming.rb +67 -0
- data/lib/dm_cloud/version.rb +3 -0
- data/lib/dm_cloud.rb +83 -0
- metadata +58 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Jeremy Mortelette
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# DmCloud
|
2
|
+
|
3
|
+
I created this gem to simplify request and responses from DailyMotion Cloud API.
|
4
|
+
With this gem, you can :
|
5
|
+
- get generated embed code as a string
|
6
|
+
- get direct access url to your files (I used this to provide video flux to TV-connected application)
|
7
|
+
- (I'm working on ) video creation, delete, paginated lists and video informations (a/v encodings, bitrate, video lenght...)
|
8
|
+
- (I'm working on ) CRUD on videos' meta-data
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
gem 'dm_cloud'
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install dm_cloud
|
23
|
+
|
24
|
+
## Usage
|
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 ``
|
29
|
+
|
30
|
+
# DAILYMOTION CLOUD SETTINGS
|
31
|
+
require 'dm_cloud'
|
32
|
+
DMC_USER_ID = 'your user id'
|
33
|
+
DMC_SECRET = 'your api key'
|
34
|
+
DMC_SECURITY_LEVEL = :none
|
35
|
+
|
36
|
+
DMCloud.configure( {
|
37
|
+
:user_key => DMC_USER_ID,
|
38
|
+
:secret_key => DMC_SECRET,
|
39
|
+
:security_level => DMC_SECURITY_LEVEL
|
40
|
+
})
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
Second part, how to get you embed url :
|
45
|
+
|
46
|
+
DMCloud::Streaming.embed('your video id looks like a secret key')
|
47
|
+
|
48
|
+
Or how to get your direct url :
|
49
|
+
|
50
|
+
DMCloud::Streaming.url('your video id', ['asset_name'], {options})
|
51
|
+
|
52
|
+
The next parts will come soon, just need some time to finish its and create corresponding tests.
|
53
|
+
|
54
|
+
## Contributing
|
55
|
+
|
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.
|
59
|
+
|
60
|
+
1. Fork it
|
61
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
62
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
63
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
64
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/dm_cloud.gemspec
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'dm_cloud/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "dm_cloud"
|
8
|
+
gem.version = DMCloud::VERSION
|
9
|
+
gem.authors = ["Jeremy Mortelette"]
|
10
|
+
gem.email = ["mortelette.jeremy@gmail.com"]
|
11
|
+
gem.description = 'This gem will simplify usage of DailyMotion Cloud API, it represent api in ruby style, with automated handler for search and upload files'
|
12
|
+
gem.summary = 'Simplify DailyMotion Cloud API usage'
|
13
|
+
gem.homepage = ""
|
14
|
+
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module DMCloud
|
2
|
+
class Media
|
3
|
+
# Creates a new media object.
|
4
|
+
# This method can either create an empty media object
|
5
|
+
# or also download a media with the url paramater
|
6
|
+
# and use it as the source to encode the ASSET_NAME listed in assets_names
|
7
|
+
# Params :
|
8
|
+
# args:
|
9
|
+
# url: SCHEME://USER:PASSWORD@HOSTNAME/MY/PATH/FILENAME.EXTENSION (could be ftp or http)
|
10
|
+
# author: an author name
|
11
|
+
# title: a title for the film
|
12
|
+
# assets_names: (Array) – (optional) the list of ASSET_NAME you want to transcode,
|
13
|
+
# when you set this parameter you must also set the url parameter
|
14
|
+
# Return :
|
15
|
+
# media_id: return the media id of the object
|
16
|
+
def self.create(media_id)
|
17
|
+
call = "media.create"
|
18
|
+
|
19
|
+
params = {
|
20
|
+
call: call,
|
21
|
+
args: DMCloud::Builder::Media.create(args)
|
22
|
+
}
|
23
|
+
DMCloud::Request.execute(call, params)
|
24
|
+
end
|
25
|
+
|
26
|
+
# Delete a media object with all its associated assets.
|
27
|
+
#
|
28
|
+
# Parameters:
|
29
|
+
# id (media ID) – (required) the id of the media object you want to delete.
|
30
|
+
# Return :
|
31
|
+
# Nothing
|
32
|
+
def self.delete
|
33
|
+
call = "media.delete"
|
34
|
+
|
35
|
+
params = {
|
36
|
+
call: call,
|
37
|
+
args: { id: media_id}
|
38
|
+
}
|
39
|
+
DMCloud::Request.execute(call, params)
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.info(fields = [])
|
43
|
+
call = "media.info"
|
44
|
+
|
45
|
+
params = {
|
46
|
+
call: call,
|
47
|
+
args: DMCloud::Builder::Media.info(fields)
|
48
|
+
}
|
49
|
+
DMCloud::Request.execute(call, params)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Gives information about a given media object.
|
53
|
+
#
|
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
|
59
|
+
def self.list(options = {})
|
60
|
+
call = "media.list"
|
61
|
+
page = options[:page].present? ? options[:page] : 1
|
62
|
+
per_page = options[:per_page].present? ? options[:per_page] : 10
|
63
|
+
|
64
|
+
params = {
|
65
|
+
call: call,
|
66
|
+
args: DMCloud::Builder::Media.list(options)
|
67
|
+
}
|
68
|
+
DMCloud::Request.execute(call, params)
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module DMCloud
|
2
|
+
class Signing
|
3
|
+
# To sign a URL, the client needs a secret shared with Dailymotion Cloud.
|
4
|
+
# This secret is call client secret and is available in the back-office interface.
|
5
|
+
# Params:
|
6
|
+
# expires: An expiration timestamp.
|
7
|
+
# sec-level: A security level mask.
|
8
|
+
# url-no-query: The URL without the query-string.
|
9
|
+
# nonce: A 8 characters-long random alphanumeric lowercase string to make the signature unique.
|
10
|
+
# secret: The client secret.
|
11
|
+
# sec-data: If sec-level doesn’t have the DELEGATED bit activated,
|
12
|
+
# this component contains concatenated informations
|
13
|
+
# for all activated sec levels.
|
14
|
+
# pub-sec-data: Some sec level data have to be passed in clear in the signature.
|
15
|
+
# To generate this component the parameters are serialized using x-www-form-urlencoded, compressed with gzip and encoded in base64.
|
16
|
+
# Result :
|
17
|
+
# return a string which contain the signed url like
|
18
|
+
# <url>?auth=<expires>-<sec>-<nonce>-<md5sum>[-<pub-sec-data>]
|
19
|
+
def self.sign(stream)
|
20
|
+
raise StandardError, "missing :stream in params" unless stream
|
21
|
+
security = security(DMCloud.config[:security_level])
|
22
|
+
sec_data = security_data(DMCloud.config[:security_level])
|
23
|
+
|
24
|
+
base = {
|
25
|
+
:sec_level => security(DMCloud.config[:security_level]),
|
26
|
+
:url_no_query => stream,
|
27
|
+
:expires => (Time.now + 1.hour).to_i,
|
28
|
+
:nonce => SecureRandom.hex(16)[0,8],
|
29
|
+
:secret => DMCloud.config[:secret_key]
|
30
|
+
}
|
31
|
+
base.merge!(:sec_data => sec_data, :pub_sec_data => sec_data) unless sec_data.nil?
|
32
|
+
puts base
|
33
|
+
digest_struct = build_digest_struct(base)
|
34
|
+
|
35
|
+
check_sum = Digest::MD5.hexdigest(digest_struct)
|
36
|
+
|
37
|
+
signed_url = [base[:expires], base[:sec_level], base[:nonce], check_sum].compact
|
38
|
+
signed_url.merge!(:pub_sec_data => sec_data) unless sec_data.nil?
|
39
|
+
|
40
|
+
puts signed_url
|
41
|
+
|
42
|
+
signed_url = signed_url.join('-')
|
43
|
+
signed_url
|
44
|
+
end
|
45
|
+
|
46
|
+
# Prepare datas for signing
|
47
|
+
# Params :
|
48
|
+
# base : contains media id and others for url signing
|
49
|
+
def self.build_digest_struct(base)
|
50
|
+
result = []
|
51
|
+
base.each_pair { |key, value| result << value }
|
52
|
+
result.join('')
|
53
|
+
end
|
54
|
+
|
55
|
+
# The client must choose a security level for the signature.
|
56
|
+
# Security level defines the mechanism used by Dailymotion Cloud architecture
|
57
|
+
# to ensure the signed URL will be used by a single end-user.
|
58
|
+
# Params :
|
59
|
+
# type :
|
60
|
+
# None: The signed URL will be valid for everyone
|
61
|
+
# ASNUM: The signed URL will only be valid for the AS of the end-user.
|
62
|
+
# The ASNUM (for Autonomous System Number) stands for the network identification,
|
63
|
+
# each ISP have a different ASNUM for instance.
|
64
|
+
# IP: The signed URL will only be valid for the IP of the end-user.
|
65
|
+
# This security level may wrongly block some users
|
66
|
+
# which have their internet access load-balanced between several proxies.
|
67
|
+
# This is the case in some office network or some ISPs.
|
68
|
+
# User-Agent: Used in addition to one of the two former levels,
|
69
|
+
# this level a limit on the exact user-agent of the end-user.
|
70
|
+
# This is more secure but in some specific condition may lead to wrongly blocked users.
|
71
|
+
# Use Once: The signed URL will only be usable once.
|
72
|
+
# Note: should not be used with stream URLs.
|
73
|
+
# Country: The URL can only be queried from specified countrie(s).
|
74
|
+
# The rule can be reversed to allow all countries except some.
|
75
|
+
# Referer: The URL can only be queried
|
76
|
+
# if the Referer HTTP header contains a specified value.
|
77
|
+
# If the URL contains a Referer header with a different value,
|
78
|
+
# the request is refused. If the Referer header is missing,
|
79
|
+
# the request is accepted in order to prevent from false positives as some browsers,
|
80
|
+
# anti-virus or enterprise proxies may remove this header.
|
81
|
+
# Delegate: This option instructs the signing algorithm
|
82
|
+
# that security level information won’t be embeded into the signature
|
83
|
+
# but gathered and lock at the first use.
|
84
|
+
# Result :
|
85
|
+
# Return a string which contain the signed url like
|
86
|
+
# http://cdn.dmcloud.net/route/<user_id>/<media_id>/<asset_name>.<asset_extension>?auth=<auth_token>
|
87
|
+
def self.security(type = nil)
|
88
|
+
type = :none unless type
|
89
|
+
type = type.to_sym if type.class == String
|
90
|
+
|
91
|
+
result = case type
|
92
|
+
when :none
|
93
|
+
0 # None
|
94
|
+
when :delegate
|
95
|
+
1 << 0 # None
|
96
|
+
when :asnum
|
97
|
+
1 << 1 # The number part of the end-user AS prefixed by the ‘AS’ string (ie: as=AS41690)
|
98
|
+
when :ip
|
99
|
+
1 << 2 # The end-user quad dotted IP address (ie: ip=195.8.215.138)
|
100
|
+
when :user_agent
|
101
|
+
1 << 3 # The end-user browser user-agent (parameter name is ua)
|
102
|
+
when :use_once
|
103
|
+
1 << 4 # None
|
104
|
+
when :country
|
105
|
+
1 << 5 # A list of 2 characters long country codes in lowercase by comas. If the list starts with a dash, the rule is inverted (ie: cc=fr,gb,de or cc=-fr,it). This data have to be stored in pub-sec-data component
|
106
|
+
when :referer
|
107
|
+
1 << 6 # A list of URL prefixes separated by spaces stored in the pub-sec-data component (ex: rf=http;//domain.com/a/+http:/domain.com/b/).
|
108
|
+
end
|
109
|
+
result
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.security_data(type, value = nil)
|
113
|
+
type = type.to_sym if type.class == String
|
114
|
+
|
115
|
+
result = case type
|
116
|
+
when :asnum
|
117
|
+
"as=#{value}" # The number part of the end-user AS prefixed by the ‘AS’ string (ie: as=AS41690)
|
118
|
+
when :ip
|
119
|
+
"ip=#{value}" # The end-user quad dotted IP address (ie: ip=195.8.215.138)
|
120
|
+
when :user_agent
|
121
|
+
"ua=#{value}" # The end-user browser user-agent (parameter name is ua)
|
122
|
+
when :country
|
123
|
+
"cc=#{value}" # A list of 2 characters long country codes in lowercase by comas. If the list starts with a dash, the rule is inverted (ie: cc=fr,gb,de or cc=-fr,it). This data have to be stored in pub-sec-data component
|
124
|
+
when :referer
|
125
|
+
"rf=#{value}" # A list of URL prefixes separated by spaces stored in the pub-sec-data component (ex: rf=http;//domain.com/a/+http:/domain.com/b/).
|
126
|
+
else
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
result
|
130
|
+
end
|
131
|
+
|
132
|
+
def self.security_pub_sec_data(type, value)
|
133
|
+
type = type.to_sym if type.class == String
|
134
|
+
|
135
|
+
result = case type
|
136
|
+
when :country
|
137
|
+
"cc=#{value}" # A list of 2 characters long country codes in lowercase by comas. If the list starts with a dash, the rule is inverted (ie: cc=fr,gb,de or cc=-fr,it). This data have to be stored in pub-sec-data component
|
138
|
+
when :referer
|
139
|
+
"rf=#{value}" # A list of URL prefixes separated by spaces stored in the pub-sec-data component (ex: rf=http;//domain.com/a/+http:/domain.com/b/).
|
140
|
+
else
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
result
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require "time"
|
2
|
+
require "openssl"
|
3
|
+
require "base64"
|
4
|
+
require 'digest/md5'
|
5
|
+
|
6
|
+
module DMCloud
|
7
|
+
class Streaming
|
8
|
+
# Default URL to get embed content ou direct url
|
9
|
+
DIRECT_STREAM = '[PROTOCOL]://cdn.dmcloud.net/route/[USER_ID]/[MEDIA_ID]/[ASSET_NAME].[ASSET_EXTENSION]'
|
10
|
+
EMBED_STREAM = '[PROTOCOL]://api.dmcloud.net/embed/[USER_ID]/[MEDIA_ID]?auth=[AUTH_TOKEN]&skin=[SKIN_ID]'
|
11
|
+
EMBED_IFRAME = '<iframe width=[WIDTH] height=[HEIGHT] frameborder="0" scrolling="no" src="[EMBED_URL]"></iframe>'
|
12
|
+
# Get embeded player
|
13
|
+
# Params :
|
14
|
+
# media_id: this is the id of the media (eg: 4c922386dede830447000009)
|
15
|
+
# options:
|
16
|
+
# skin_id: (optional) the id of the custom skin for the video player
|
17
|
+
# width: (optional) the width for the video player frame
|
18
|
+
# height: (optional) the height for the video player frame
|
19
|
+
# Result :
|
20
|
+
# return a string which contain the signed url like
|
21
|
+
# <iframe width="848" height="480" frameborder="0" scrolling="no" src="http://api.dmcloud.net/embed/<user_id>/<media_id>?auth=<auth_token>&skin=<skin_id>"></iframe>
|
22
|
+
def self.embed(media_id, options = {})
|
23
|
+
raise StandardError, "missing :media_id in params" unless media_id
|
24
|
+
|
25
|
+
skin_id = options[:skin_id].present? ? options[:skin_id] : 'modern1'
|
26
|
+
width = options[:width].present? ? options[:width] : '848'
|
27
|
+
height = options[:height].present? ? options[:height] : '480'
|
28
|
+
|
29
|
+
stream = EMBED_STREAM
|
30
|
+
stream.gsub!('[PROTOCOL]', DMCloud.config[:protocol])
|
31
|
+
stream.gsub!('[USER_ID]', DMCloud.config[:user_key])
|
32
|
+
stream.gsub!('[MEDIA_ID]', media_id)
|
33
|
+
stream.gsub!('[SKIN_ID]', skin_id)
|
34
|
+
stream += '?auth=[AUTH_TOKEN]'.gsub!('[AUTH_TOKEN]', DMCloud::Signing.sign(stream))
|
35
|
+
|
36
|
+
frame = EMBED_IFRAME
|
37
|
+
frame.gsub!('[WIDTH]', width)
|
38
|
+
frame.gsub!('[HEIGHT]', height)
|
39
|
+
frame.gsub!('[EMBED_URL]', stream)
|
40
|
+
frame
|
41
|
+
end
|
42
|
+
|
43
|
+
# Get media url for direct link to the file on DailyMotion Cloud
|
44
|
+
# Params :
|
45
|
+
# media_id: this is the id of the media (eg: 4c922386dede830447000009)
|
46
|
+
# asset_name: the name of the asset you want to stream (eg: mp4_h264_aac)
|
47
|
+
# asset_extension: the extension of the asset, most of the time it is the first part of the asset name (eg: mp4)
|
48
|
+
# Result :
|
49
|
+
# return a string which contain the signed url like
|
50
|
+
# http://cdn.dmcloud.net/route/<user_id>/<media_id>/<asset_name>.<asset_extension>?auth=<auth_token>
|
51
|
+
def self.url(media_id, asset_name, asset_extension = nil)
|
52
|
+
asset_extension = asset_name.split('_').first unless asset_extension
|
53
|
+
|
54
|
+
raise StandardError, "missing :media_id in params" unless media_id
|
55
|
+
raise StandardError, "missing :asset_name in params" unless asset_name
|
56
|
+
|
57
|
+
stream = DIRECT_STREAM
|
58
|
+
stream.gsub!('[PROTOCOL]', DMCloud.config[:protocol])
|
59
|
+
stream.gsub!('[USER_ID]', DMCloud.config[:user_key])
|
60
|
+
stream.gsub!('[MEDIA_ID]', media_id)
|
61
|
+
stream.gsub!('[ASSET_NAME]', asset_name)
|
62
|
+
stream.gsub!('[ASSET_EXTENSION]', asset_extension)
|
63
|
+
stream += '?auth=[AUTH_TOKEN]'.gsub!('[AUTH_TOKEN]', DMCloud::Signing.sign(stream))
|
64
|
+
stream
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
data/lib/dm_cloud.rb
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
require "dm_cloud/version"
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module DMCloud
|
5
|
+
|
6
|
+
# Configuration defaults
|
7
|
+
@@config = {
|
8
|
+
:security_level => 'none',
|
9
|
+
:protocol => 'http'
|
10
|
+
}
|
11
|
+
|
12
|
+
YAML_INITIALIZER_PATH = File.dirname(__FILE__)
|
13
|
+
@valid_config_keys = @@config.keys
|
14
|
+
|
15
|
+
# Configure through hash
|
16
|
+
def self.configure(opts = {})
|
17
|
+
opts.each {|k,v| @@config[k.to_sym] = v } # if @valid_config_keys.include? k.to_sym}
|
18
|
+
end
|
19
|
+
|
20
|
+
# Configure through yaml file
|
21
|
+
def self.configure_with(yaml_file_path = nil)
|
22
|
+
yaml_file_path = YAML_INITIALIZER_PATH unless yaml_file_path
|
23
|
+
begin
|
24
|
+
config = YAML::load(IO.read(path_to_yaml_file))
|
25
|
+
rescue Errno::ENOENT
|
26
|
+
log(:warning, "YAML configuration file couldn't be found. Using defaults."); return
|
27
|
+
rescue Psych::SyntaxError
|
28
|
+
log(:warning, "YAML configuration file contains invalid syntax. Using defaults."); return
|
29
|
+
end
|
30
|
+
|
31
|
+
configure(config)
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.config
|
35
|
+
@@config = configure unless @@config
|
36
|
+
@@config
|
37
|
+
end
|
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
|
+
def self.create_has_library(library)
|
48
|
+
define_singleton_method("has_#{library}?") do
|
49
|
+
cv="@@#{library}"
|
50
|
+
if !class_variable_defined? cv
|
51
|
+
begin
|
52
|
+
require library.to_s
|
53
|
+
class_variable_set(cv,true)
|
54
|
+
rescue LoadError
|
55
|
+
class_variable_set(cv,false)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
class_variable_get(cv)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
create_has_library :treaming
|
63
|
+
|
64
|
+
|
65
|
+
class << self
|
66
|
+
# Load a object saved on a file.
|
67
|
+
def load(filename)
|
68
|
+
if File.exists? filename
|
69
|
+
o=false
|
70
|
+
File.open(filename,"r") {|fp| o=Marshal.load(fp) }
|
71
|
+
o
|
72
|
+
else
|
73
|
+
false
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
autoload(:Streaming, 'dm_cloud/streaming')
|
79
|
+
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
Dir.glob('dm_cloud/**/*.rb').each{ |m| require File.dirname(__FILE__) + '/dm_cloud/' + m }
|
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: dm_cloud
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jeremy Mortelette
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-25 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: This gem will simplify usage of DailyMotion Cloud API, it represent api
|
15
|
+
in ruby style, with automated handler for search and upload files
|
16
|
+
email:
|
17
|
+
- mortelette.jeremy@gmail.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- .gitignore
|
23
|
+
- Gemfile
|
24
|
+
- LICENSE.txt
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- dm_cloud.gemspec
|
28
|
+
- lib/dm_cloud.rb
|
29
|
+
- lib/dm_cloud/media.rb
|
30
|
+
- lib/dm_cloud/request.rb
|
31
|
+
- lib/dm_cloud/signing.rb
|
32
|
+
- lib/dm_cloud/streaming.rb
|
33
|
+
- lib/dm_cloud/version.rb
|
34
|
+
homepage: ''
|
35
|
+
licenses: []
|
36
|
+
post_install_message:
|
37
|
+
rdoc_options: []
|
38
|
+
require_paths:
|
39
|
+
- lib
|
40
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
47
|
+
none: false
|
48
|
+
requirements:
|
49
|
+
- - ! '>='
|
50
|
+
- !ruby/object:Gem::Version
|
51
|
+
version: '0'
|
52
|
+
requirements: []
|
53
|
+
rubyforge_project:
|
54
|
+
rubygems_version: 1.8.24
|
55
|
+
signing_key:
|
56
|
+
specification_version: 3
|
57
|
+
summary: Simplify DailyMotion Cloud API usage
|
58
|
+
test_files: []
|