chocolate_rain 0.0.1 → 0.0.2
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/chocolate_rain.gemspec +3 -4
- data/lib/chocolate_rain/daemon.rb +67 -0
- data/lib/chocolate_rain/ftp_files_and_upload.rb +54 -0
- data/lib/chocolate_rain/mail_rain/inbox.rb +39 -0
- data/lib/chocolate_rain/mail_rain/mail_handler.rb +53 -0
- data/lib/chocolate_rain/version.rb +1 -1
- data/lib/chocolate_rain/y_video.rb +49 -0
- data/lib/chocolate_rain.rb +45 -4
- metadata +22 -39
- data/generators/youtube_model/USAGE +0 -3
- data/generators/youtube_model/templates/config.yml +0 -6
- data/generators/youtube_model/templates/model.rb +0 -17
- data/generators/youtube_model/templates/unit_test.rb +0 -7
- data/generators/youtube_model/youtube_model_generator.rb +0 -15
- data/lib/.DS_Store +0 -0
- data/lib/gdata/auth/authsub.rb +0 -161
- data/lib/gdata/auth/clientlogin.rb +0 -102
- data/lib/gdata/client/apps.rb +0 -27
- data/lib/gdata/client/base.rb +0 -182
- data/lib/gdata/client/blogger.rb +0 -28
- data/lib/gdata/client/booksearch.rb +0 -28
- data/lib/gdata/client/calendar.rb +0 -58
- data/lib/gdata/client/contacts.rb +0 -28
- data/lib/gdata/client/doclist.rb +0 -28
- data/lib/gdata/client/finance.rb +0 -28
- data/lib/gdata/client/gbase.rb +0 -28
- data/lib/gdata/client/gmail.rb +0 -28
- data/lib/gdata/client/health.rb +0 -28
- data/lib/gdata/client/notebook.rb +0 -28
- data/lib/gdata/client/photos.rb +0 -29
- data/lib/gdata/client/spreadsheets.rb +0 -28
- data/lib/gdata/client/webmaster_tools.rb +0 -28
- data/lib/gdata/client/youtube.rb +0 -47
- data/lib/gdata/client.rb +0 -84
- data/lib/gdata/g_data.rb +0 -22
- data/lib/gdata/http/default_service.rb +0 -82
- data/lib/gdata/http/mime_body.rb +0 -95
- data/lib/gdata/http/request.rb +0 -74
- data/lib/gdata/http/response.rb +0 -44
- data/lib/gdata/http.rb +0 -18
- data/lib/youtube_helpers.rb +0 -58
- data/lib/youtube_model.rb +0 -341
data/chocolate_rain.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |s|
|
|
8
8
|
s.authors = ["Kevin Hopkins"]
|
9
9
|
s.email = ["kevin@wearefound.com"]
|
10
10
|
s.homepage = ""
|
11
|
-
s.summary = %q{
|
12
|
-
s.description = %q{
|
11
|
+
s.summary = %q{Monitor E-Mail and FTP for videos to upload to YouTube}
|
12
|
+
s.description = %q{Monitor E-Mail and FTP for videos to upload to YouTube}
|
13
13
|
|
14
14
|
s.rubyforge_project = "chocolate_rain"
|
15
15
|
|
@@ -21,6 +21,5 @@ Gem::Specification.new do |s|
|
|
21
21
|
# specify any dependencies here; for example:
|
22
22
|
# s.add_development_dependency "rspec"
|
23
23
|
# s.add_runtime_dependency "rest-client"
|
24
|
-
s.
|
25
|
-
|
24
|
+
s.add_dependency "youtube_it"
|
26
25
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
module Daemon
|
4
|
+
WorkingDirectory = File.expand_path(File.dirname(__FILE__))
|
5
|
+
|
6
|
+
class Base
|
7
|
+
def self.pid_fn
|
8
|
+
File.join(WorkingDirectory, "#{name}.pid")
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.daemonize
|
12
|
+
Controller.daemonize(self)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
module PidFile
|
17
|
+
def self.store(daemon, pid)
|
18
|
+
File.open(daemon.pid_fn, 'w') {|f| f << pid}
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.recall(daemon)
|
22
|
+
IO.read(daemon.pid_fn).to_i rescue nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
module Controller
|
27
|
+
def self.daemonize(daemon)
|
28
|
+
case !ARGV.empty? && ARGV[0]
|
29
|
+
when 'start'
|
30
|
+
start(daemon)
|
31
|
+
when 'stop'
|
32
|
+
stop(daemon)
|
33
|
+
when 'restart'
|
34
|
+
stop(daemon)
|
35
|
+
start(daemon)
|
36
|
+
else
|
37
|
+
puts "Invalid command. Please specify start, stop or restart."
|
38
|
+
exit
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.start(daemon)
|
43
|
+
fork do
|
44
|
+
Process.setsid
|
45
|
+
exit if fork
|
46
|
+
PidFile.store(daemon, Process.pid)
|
47
|
+
Dir.chdir WorkingDirectory
|
48
|
+
File.umask 0000
|
49
|
+
STDIN.reopen "/dev/null"
|
50
|
+
STDOUT.reopen "/dev/null", "a"
|
51
|
+
STDERR.reopen STDOUT
|
52
|
+
trap("TERM") {daemon.stop; exit}
|
53
|
+
daemon.start
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.stop(daemon)
|
58
|
+
if !File.file?(daemon.pid_fn)
|
59
|
+
puts "Pid file not found. Is the daemon started?"
|
60
|
+
exit
|
61
|
+
end
|
62
|
+
pid = PidFile.recall(daemon)
|
63
|
+
FileUtils.rm(daemon.pid_fn)
|
64
|
+
pid && Process.kill("TERM", pid)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'net/ftp'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'youtube_it'
|
4
|
+
|
5
|
+
module YouTuber
|
6
|
+
# Youtube Creds
|
7
|
+
def upload(f)
|
8
|
+
YT_CLIENT ||= YouTubeIt::Client.new(:username => "whyhermancain" , :password => "999m3@nsj0bs" , :dev_key => "AI39si79BSRx1X9AtG5zNxo-wk5YGiIHa-FAt5BNvb2poO7AVdNJEYoCgxg-JilsgHbNr0IUFk8j490v_LOZ8iPKueOUea6DdQ")
|
9
|
+
|
10
|
+
YT_CLIENT.video_upload(File.open("#{Rails.root.to_s}/public/videos/#{f}"), :title => "#{f}", :description => "Testimonial Video", :category => "Entertainment", :keywords => %w[herman cain whyhermancain republican politics testimonal donate donation], :list => "denied", :comments => "denied", :rate => "denied", :commentVote => "denied", :videoRespond => "denied", :embed => "denied", :syndicate => "denied")
|
11
|
+
puts "completed #{f}"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# FTP creds
|
16
|
+
URL = "fx0j7sls.rtmphost.com"
|
17
|
+
USERNAME = "fx0j7sls"
|
18
|
+
PASSWORD = "oi890_{PO"
|
19
|
+
DIRECTORY = "/fx0j7sls_apps/VideoGallery/streams/_definst_"
|
20
|
+
FORMAT = "flv"
|
21
|
+
|
22
|
+
@local_files = []
|
23
|
+
|
24
|
+
ftp = Net::FTP.new
|
25
|
+
ftp.connect(URL, 21)
|
26
|
+
ftp.login(USERNAME, PASSWORD)
|
27
|
+
|
28
|
+
|
29
|
+
ftp.chdir(DIRECTORY)
|
30
|
+
filenames = ftp.nlst("*.#{FORMAT}") # comes back as array
|
31
|
+
|
32
|
+
# loop by index
|
33
|
+
filenames.each_index do |i|
|
34
|
+
puts "working with index: #{i}"
|
35
|
+
localfile = "#{Rails.root.to_s}/public/videos/#{i}.#{FORMAT}"
|
36
|
+
ftp.getbinaryfile(filenames[i], localfile)
|
37
|
+
puts "got #{i}.#{FORMAT}"
|
38
|
+
@local_files << "#{i}.#{FORMAT}"
|
39
|
+
puts "*** \n"
|
40
|
+
end
|
41
|
+
|
42
|
+
filenames.each do |filename|
|
43
|
+
puts "Deleting #{filename}"
|
44
|
+
ftp.delete("#{filename}") # deleting from server so we don't re-download
|
45
|
+
puts "complete.\n***\n"
|
46
|
+
end
|
47
|
+
|
48
|
+
puts "Starting upload stack\n...\n......"
|
49
|
+
@local_files.each do |f|
|
50
|
+
YT_CLIENT.video_upload(File.open("#{Rails.root.to_s}/public/videos/#{f}"), :title => "#{f}", :description => "Testimonial Video", :category => "Entertainment", :keywords => %w[herman cain whyhermancain republican politics testimonal donate donation], :list => "denied", :comments => "denied", :rate => "denied", :commentVote => "denied", :videoRespond => "denied", :embed => "denied", :syndicate => "denied")
|
51
|
+
puts "completed #{f}"
|
52
|
+
end
|
53
|
+
|
54
|
+
puts "...el fine..."
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'net/pop'
|
2
|
+
require 'mail'
|
3
|
+
require 'daemon'
|
4
|
+
require 'y_video'
|
5
|
+
require 'mail_handler'
|
6
|
+
|
7
|
+
class MailFetcher < Daemon::Base
|
8
|
+
def self.start
|
9
|
+
loop do
|
10
|
+
puts "Running Mail Importer..."
|
11
|
+
pop = Net::POP3.new('mail.hasflavor.com')
|
12
|
+
|
13
|
+
pop.start("app@hasflavor.com", "oi890po")
|
14
|
+
|
15
|
+
if pop.mails.empty?
|
16
|
+
puts "NO MAIL"
|
17
|
+
else
|
18
|
+
i = 0
|
19
|
+
puts "receiving mail..."
|
20
|
+
pop.each_mail do |m|
|
21
|
+
MailHandler.receive(m.pop)
|
22
|
+
m.delete
|
23
|
+
i += 1
|
24
|
+
end
|
25
|
+
puts "#{pop.mails.size} mails popped"
|
26
|
+
end
|
27
|
+
pop.finish
|
28
|
+
puts "Finished Mail Importer."
|
29
|
+
|
30
|
+
sleep(10)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.stop
|
35
|
+
puts "Stopping Mail Fetcher Daemon"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
MailFetcher.start
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'mail'
|
2
|
+
require 'stringio'
|
3
|
+
require 'y_video'
|
4
|
+
|
5
|
+
class MailHandler < ActionMailer::Base
|
6
|
+
def resend(sender, recipient, subject, body)
|
7
|
+
mail(:from => sender,
|
8
|
+
:to => recipient,
|
9
|
+
:subject => subject,
|
10
|
+
:body => body)
|
11
|
+
puts "Mail sent to #{recipient}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def receive(email)
|
15
|
+
to_email = "apx05eq15zgx@m.youtube.com"
|
16
|
+
resend_multipart(email)
|
17
|
+
end
|
18
|
+
|
19
|
+
def resend_multipart(email)
|
20
|
+
email.attachments.each do |att|
|
21
|
+
fn = att.filename
|
22
|
+
v = YVideo.new()
|
23
|
+
begin
|
24
|
+
f = StringIO.new(att.body.decoded)
|
25
|
+
v.filename = fn
|
26
|
+
v.file_object = f
|
27
|
+
v.title = fn
|
28
|
+
begin
|
29
|
+
v.save
|
30
|
+
puts "Saving to S3 succeeded"
|
31
|
+
rescue Exception => e
|
32
|
+
puts "S3 Failed miserably: #{e.message}"
|
33
|
+
end
|
34
|
+
rescue Exception => e
|
35
|
+
puts "Unable to save data for #{fn} because of #{e.message}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
text_body = email.parts.select{|p| p.content_type.include? "text/plain" }.first.body.to_s
|
40
|
+
puts "Email subject: #{email.subject}"
|
41
|
+
begin
|
42
|
+
resent = MailHandler.resend(["whyhermancain@gmail.com"], ["support@wearefound.com"], "[CAIN] Successful Upload", "A new testimonial video has been uploaded via email to s3. Its url is http://s3.amazonaws.com/whyHermanCain/#{v.filename}")
|
43
|
+
resent.deliver
|
44
|
+
puts "sent"
|
45
|
+
rescue
|
46
|
+
return
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def upload(f)
|
51
|
+
puts "completed #{f}"
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'youtube_it'
|
2
|
+
require 'aws/s3'
|
3
|
+
|
4
|
+
class YVideo
|
5
|
+
attr_accessor :filename, :file_object, :title, :description, :category, :keywords, :list, :comments, :rate, :commentVote, :videoRespond, :embed, :syndicate
|
6
|
+
|
7
|
+
@@YCONN = YouTubeIt::Client.new(:username => "whyhermancain" , :password => "999m3@nsj0bs" , :dev_key => "AI39si79BSRx1X9AtG5zNxo-wk5YGiIHa-FAt5BNvb2poO7AVdNJEYoCgxg-JilsgHbNr0IUFk8j490v_LOZ8iPKueOUea6DdQ")
|
8
|
+
@@y = YAML.load(File.open("#{Rails.root.to_s}/config/s3.yml"))
|
9
|
+
AWS::S3::Base.establish_connection!(
|
10
|
+
:access_key_id => @@y[(Rails.env)]["access_key_id"],
|
11
|
+
:secret_access_key => @@y[(Rails.env)]["secret_access_key"]
|
12
|
+
)
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@filename = nil
|
16
|
+
@description = nil
|
17
|
+
@category = nil
|
18
|
+
@keywords = []
|
19
|
+
@list = "denied"
|
20
|
+
@comments = "denied"
|
21
|
+
@rate = "denied"
|
22
|
+
@commentVote = "denied"
|
23
|
+
@videoRespond = "denied"
|
24
|
+
@embed = "denied"
|
25
|
+
@syndicate = "denied"
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_hash
|
29
|
+
self.instance_variables.inject({}) { |hash,var| hash[var.to_s.delete("@")] = self.instance_variable_get(var); hash }
|
30
|
+
end
|
31
|
+
|
32
|
+
def upload
|
33
|
+
@@YCONN.video_upload(File.open("#{Rails.root.to_s}/public/videos/#{f}"), :title => "#{f}", :description => "Testimonial Video", :category => "Entertainment", :keywords => %w[herman cain whyhermancain republican politics testimonal donate donation], :list => "denied", :comments => "denied", :rate => "denied", :commentVote => "denied", :videoRespond => "denied", :embed => "denied", :syndicate => "denied")
|
34
|
+
end
|
35
|
+
|
36
|
+
def save
|
37
|
+
puts "in save"
|
38
|
+
begin
|
39
|
+
bucket = AWS::S3::Bucket.find(@@y[(Rails.env)]["bucket"])
|
40
|
+
rescue
|
41
|
+
bucket = AWS::S3::Bucket.create(@@y[(Rails.env)]["bucket"])
|
42
|
+
end
|
43
|
+
if AWS::S3::S3Object.store(self.filename, self.file_object, @@y[(Rails.env)]["bucket"], :access => :public_read)
|
44
|
+
return true
|
45
|
+
else
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/lib/chocolate_rain.rb
CHANGED
@@ -1,5 +1,46 @@
|
|
1
|
-
require
|
1
|
+
require 'logger'
|
2
|
+
%w(
|
3
|
+
version
|
4
|
+
daemon
|
5
|
+
y_video
|
6
|
+
mail_rain/mail_handler
|
7
|
+
mail_rain/inbox
|
8
|
+
).each{|m| require File.dirname(__FILE__) + '/chocolate_rain/' + m }
|
2
9
|
|
3
|
-
|
4
|
-
|
5
|
-
|
10
|
+
class ChocolateRain
|
11
|
+
|
12
|
+
# Base error class for the extension
|
13
|
+
class Error < RuntimeError
|
14
|
+
end
|
15
|
+
|
16
|
+
# URL-escape a string. Stolen from Camping (wonder how many Ruby libs in the wild can say the same)
|
17
|
+
def self.esc(s) #:nodoc:
|
18
|
+
s.to_s.gsub(/[^ \w.-]+/n){'%'+($&.unpack('H2'*$&.size)*'%').upcase}.tr(' ', '+')
|
19
|
+
end
|
20
|
+
|
21
|
+
# Set the logger for the library
|
22
|
+
def self.logger=(any_logger)
|
23
|
+
@logger = any_logger
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get the logger for the library (by default will log to STDOUT). TODO: this is where we grab the Rails logger too
|
27
|
+
def self.logger
|
28
|
+
@logger ||= create_default_logger
|
29
|
+
end
|
30
|
+
|
31
|
+
# Gets mixed into the classes to provide the logger method
|
32
|
+
module Logging #:nodoc:
|
33
|
+
|
34
|
+
# Return the base logger set for the library
|
35
|
+
def logger
|
36
|
+
YouTubeIt.logger
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
def self.create_default_logger
|
42
|
+
logger = Logger.new(STDOUT)
|
43
|
+
logger.level = Logger::DEBUG
|
44
|
+
logger
|
45
|
+
end
|
46
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chocolate_rain
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,9 +9,20 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-11-
|
13
|
-
dependencies:
|
14
|
-
|
12
|
+
date: 2011-11-23 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: youtube_it
|
16
|
+
requirement: &2152231740 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2152231740
|
25
|
+
description: Monitor E-Mail and FTP for videos to upload to YouTube
|
15
26
|
email:
|
16
27
|
- kevin@wearefound.com
|
17
28
|
executables: []
|
@@ -22,41 +33,13 @@ files:
|
|
22
33
|
- Gemfile
|
23
34
|
- Rakefile
|
24
35
|
- chocolate_rain.gemspec
|
25
|
-
- generators/youtube_model/USAGE
|
26
|
-
- generators/youtube_model/templates/config.yml
|
27
|
-
- generators/youtube_model/templates/model.rb
|
28
|
-
- generators/youtube_model/templates/unit_test.rb
|
29
|
-
- generators/youtube_model/youtube_model_generator.rb
|
30
|
-
- lib/.DS_Store
|
31
36
|
- lib/chocolate_rain.rb
|
37
|
+
- lib/chocolate_rain/daemon.rb
|
38
|
+
- lib/chocolate_rain/ftp_files_and_upload.rb
|
39
|
+
- lib/chocolate_rain/mail_rain/inbox.rb
|
40
|
+
- lib/chocolate_rain/mail_rain/mail_handler.rb
|
32
41
|
- lib/chocolate_rain/version.rb
|
33
|
-
- lib/
|
34
|
-
- lib/gdata/auth/clientlogin.rb
|
35
|
-
- lib/gdata/client.rb
|
36
|
-
- lib/gdata/client/apps.rb
|
37
|
-
- lib/gdata/client/base.rb
|
38
|
-
- lib/gdata/client/blogger.rb
|
39
|
-
- lib/gdata/client/booksearch.rb
|
40
|
-
- lib/gdata/client/calendar.rb
|
41
|
-
- lib/gdata/client/contacts.rb
|
42
|
-
- lib/gdata/client/doclist.rb
|
43
|
-
- lib/gdata/client/finance.rb
|
44
|
-
- lib/gdata/client/gbase.rb
|
45
|
-
- lib/gdata/client/gmail.rb
|
46
|
-
- lib/gdata/client/health.rb
|
47
|
-
- lib/gdata/client/notebook.rb
|
48
|
-
- lib/gdata/client/photos.rb
|
49
|
-
- lib/gdata/client/spreadsheets.rb
|
50
|
-
- lib/gdata/client/webmaster_tools.rb
|
51
|
-
- lib/gdata/client/youtube.rb
|
52
|
-
- lib/gdata/g_data.rb
|
53
|
-
- lib/gdata/http.rb
|
54
|
-
- lib/gdata/http/default_service.rb
|
55
|
-
- lib/gdata/http/mime_body.rb
|
56
|
-
- lib/gdata/http/request.rb
|
57
|
-
- lib/gdata/http/response.rb
|
58
|
-
- lib/youtube_helpers.rb
|
59
|
-
- lib/youtube_model.rb
|
42
|
+
- lib/chocolate_rain/y_video.rb
|
60
43
|
homepage: ''
|
61
44
|
licenses: []
|
62
45
|
post_install_message:
|
@@ -74,11 +57,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
74
57
|
requirements:
|
75
58
|
- - ! '>='
|
76
59
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
60
|
+
version: '0'
|
78
61
|
requirements: []
|
79
62
|
rubyforge_project: chocolate_rain
|
80
63
|
rubygems_version: 1.8.6
|
81
64
|
signing_key:
|
82
65
|
specification_version: 3
|
83
|
-
summary:
|
66
|
+
summary: Monitor E-Mail and FTP for videos to upload to YouTube
|
84
67
|
test_files: []
|
@@ -1,17 +0,0 @@
|
|
1
|
-
class <%= class_name %> < YouTubeModel::Base #inherits from ActiveResource::Base
|
2
|
-
self.default_youtube_options= {:itemPerPage => 10}
|
3
|
-
|
4
|
-
schema do
|
5
|
-
attribute :title, :string
|
6
|
-
attribute :description, :string
|
7
|
-
attribute :keywords, :string
|
8
|
-
attribute :category, :string
|
9
|
-
attribute :file, :string
|
10
|
-
attribute :token, :string
|
11
|
-
end
|
12
|
-
|
13
|
-
validates_presence_of :title
|
14
|
-
validates_presence_of :token #needed on remote crud operation
|
15
|
-
validates_presence_of :file, :if => Proc.new{|<%=singular_name%>| <%=singular_name%>.new? }
|
16
|
-
|
17
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
class YoutubeModelGenerator < Rails::Generators::NamedBase
|
2
|
-
|
3
|
-
desc "Generate youtube_model files, Usage: rails g youtube_model ModelName"
|
4
|
-
|
5
|
-
source_root File.expand_path('../templates', __FILE__)
|
6
|
-
|
7
|
-
check_class_collision
|
8
|
-
|
9
|
-
def manifest
|
10
|
-
template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
|
11
|
-
template 'unit_test.rb', File.join('test/unit', class_path, "#{file_name}_test.rb")
|
12
|
-
template 'config.yml', File.join('config', "#{file_name}_config.yml")
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
data/lib/.DS_Store
DELETED
Binary file
|
data/lib/gdata/auth/authsub.rb
DELETED
@@ -1,161 +0,0 @@
|
|
1
|
-
# Copyright (C) 2008 Google Inc.
|
2
|
-
#
|
3
|
-
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
-
# you may not use this file except in compliance with the License.
|
5
|
-
# You may obtain a copy of the License at
|
6
|
-
#
|
7
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
-
#
|
9
|
-
# Unless required by applicable law or agreed to in writing, software
|
10
|
-
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
-
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
-
# See the License for the specific language governing permissions and
|
13
|
-
# limitations under the License.
|
14
|
-
|
15
|
-
require 'cgi'
|
16
|
-
require 'openssl'
|
17
|
-
require 'base64'
|
18
|
-
|
19
|
-
module GData
|
20
|
-
module Auth
|
21
|
-
|
22
|
-
# This class implements AuthSub signatures for Data API requests.
|
23
|
-
# It can be used with a GData::Client::GData object.
|
24
|
-
class AuthSub
|
25
|
-
|
26
|
-
# The URL of AuthSubRequest.
|
27
|
-
REQUEST_HANDLER = 'https://www.google.com/accounts/AuthSubRequest'
|
28
|
-
# The URL of AuthSubSessionToken.
|
29
|
-
SESSION_HANDLER = 'https://www.google.com/accounts/AuthSubSessionToken'
|
30
|
-
# The URL of AuthSubRevokeToken.
|
31
|
-
REVOKE_HANDLER = 'https://www.google.com/accounts/AuthSubRevokeToken'
|
32
|
-
# The URL of AuthSubInfo.
|
33
|
-
INFO_HANDLER = 'https://www.google.com/accounts/AuthSubTokenInfo'
|
34
|
-
# 2 ** 64, the largest 64 bit unsigned integer
|
35
|
-
BIG_INT_MAX = 18446744073709551616
|
36
|
-
|
37
|
-
# AuthSub access token.
|
38
|
-
attr_accessor :token
|
39
|
-
# Private RSA key used to sign secure requests.
|
40
|
-
attr_reader :private_key
|
41
|
-
|
42
|
-
# Initialize the class with a new token. Optionally pass a private
|
43
|
-
# key or custom URLs.
|
44
|
-
def initialize(token, options = {})
|
45
|
-
if token.nil?
|
46
|
-
raise ArgumentError, "Token cannot be nil."
|
47
|
-
elsif token.class != String
|
48
|
-
raise ArgumentError, "Token must be a String."
|
49
|
-
end
|
50
|
-
|
51
|
-
@token = token
|
52
|
-
|
53
|
-
options.each do |key, value|
|
54
|
-
self.send("#{key}=", value)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
# Set the private key to use with this AuthSub token.
|
59
|
-
# The key can be an OpenSSL::PKey::RSA object, a string containing a
|
60
|
-
# private key in PEM format, or a string specifying a path to a PEM
|
61
|
-
# file that contains the private key.
|
62
|
-
def private_key=(key)
|
63
|
-
begin
|
64
|
-
if key.nil? or key.class == OpenSSL::PKey::RSA
|
65
|
-
@private_key = key
|
66
|
-
elsif File.exists?(key)
|
67
|
-
key_from_file = File.read(key)
|
68
|
-
@private_key = OpenSSL::PKey::RSA.new(key_from_file)
|
69
|
-
else
|
70
|
-
@private_key = OpenSSL::PKey::RSA.new(key)
|
71
|
-
end
|
72
|
-
rescue
|
73
|
-
raise ArgumentError, "Not a valid private key."
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
# Sign a GData::Http::Request object with a valid AuthSub Authorization
|
78
|
-
# header.
|
79
|
-
def sign_request!(request)
|
80
|
-
header = "AuthSub token=\"#{@token}\""
|
81
|
-
|
82
|
-
if @private_key
|
83
|
-
time = Time.now.to_i
|
84
|
-
nonce = OpenSSL::BN.rand_range(BIG_INT_MAX)
|
85
|
-
method = request.method.to_s.upcase
|
86
|
-
data = "#{method} #{request.url} #{time} #{nonce}"
|
87
|
-
sig = @private_key.sign(OpenSSL::Digest::SHA1.new, data)
|
88
|
-
sig = Base64.encode64(sig).gsub(/\n/, '')
|
89
|
-
header = "#{header} sigalg=\"rsa-sha1\" data=\"#{data}\""
|
90
|
-
header = "#{header} sig=\"#{sig}\""
|
91
|
-
end
|
92
|
-
|
93
|
-
request.headers['Authorization'] = header
|
94
|
-
end
|
95
|
-
|
96
|
-
# Upgrade the current token into a session token.
|
97
|
-
def upgrade
|
98
|
-
request = GData::HTTP::Request.new(SESSION_HANDLER)
|
99
|
-
sign_request!(request)
|
100
|
-
service = GData::HTTP::DefaultService.new
|
101
|
-
response = service.make_request(request)
|
102
|
-
if response.status_code != 200
|
103
|
-
raise GData::Client::AuthorizationError.new(response)
|
104
|
-
end
|
105
|
-
|
106
|
-
@token = response.body[/Token=(.*)/,1]
|
107
|
-
return @token
|
108
|
-
|
109
|
-
end
|
110
|
-
|
111
|
-
# Return some information about the current token. If the current token
|
112
|
-
# is a one-time use token, this operation will use it up!
|
113
|
-
def info
|
114
|
-
request = GData::HTTP::Request.new(INFO_HANDLER)
|
115
|
-
sign_request!(request)
|
116
|
-
service = GData::HTTP::DefaultService.new
|
117
|
-
response = service.make_request(request)
|
118
|
-
if response.status_code != 200
|
119
|
-
raise GData::Client::AuthorizationError.new(response)
|
120
|
-
end
|
121
|
-
|
122
|
-
result = {}
|
123
|
-
result[:target] = response.body[/Target=(.*)/,1]
|
124
|
-
result[:scope] = response.body[/Scope=(.*)/,1]
|
125
|
-
result[:secure] = response.body[/Secure=(.*)/,1]
|
126
|
-
return result
|
127
|
-
|
128
|
-
end
|
129
|
-
|
130
|
-
# Revoke the token.
|
131
|
-
def revoke
|
132
|
-
request = GData::HTTP::Request.new(REVOKE_HANDLER)
|
133
|
-
sign_request!(request)
|
134
|
-
service = GData::HTTP::DefaultService.new
|
135
|
-
response = service.make_request(request)
|
136
|
-
if response.status_code != 200
|
137
|
-
raise GData::Client::AuthorizationError.new(response)
|
138
|
-
end
|
139
|
-
|
140
|
-
end
|
141
|
-
|
142
|
-
# Return the proper URL for an AuthSub approval page with the requested
|
143
|
-
# scope. next_url should be a URL that points back to your code that
|
144
|
-
# will receive the token. domain is optionally a Google Apps domain.
|
145
|
-
def self.get_url(next_url, scope, secure = false, session = true,
|
146
|
-
domain = nil)
|
147
|
-
next_url = CGI.escape(next_url)
|
148
|
-
scope = CGI.escape(scope)
|
149
|
-
secure = secure ? 1 : 0
|
150
|
-
session = session ? 1 : 0
|
151
|
-
body = "next=#{next_url}&scope=#{scope}&session=#{session}" +
|
152
|
-
"&secure=#{secure}"
|
153
|
-
if domain
|
154
|
-
domain = CGI.escape(domain)
|
155
|
-
body = "#{body}&hd=#{domain}"
|
156
|
-
end
|
157
|
-
return "#{REQUEST_HANDLER}?#{body}"
|
158
|
-
end
|
159
|
-
end
|
160
|
-
end
|
161
|
-
end
|