cherrypicker 0.3.2 → 0.3.3
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/cherrypick +61 -0
- data/lib/cherrypicker/cherrypick.rb +24 -0
- data/lib/cherrypicker/download.rb +40 -39
- data/lib/cherrypicker/helpers.rb +28 -26
- data/lib/cherrypicker/linkchecker.rb +89 -88
- data/lib/cherrypicker/plugins/hotfile.rb +33 -32
- data/lib/cherrypicker/plugins/megavideo.rb +71 -70
- data/lib/cherrypicker/plugins/rapidshare.rb +40 -39
- data/lib/cherrypicker/plugins/vimeo.rb +31 -30
- data/lib/cherrypicker/plugins/youtube.rb +53 -52
- data/lib/cherrypicker/version.rb +1 -1
- data/lib/cherrypicker.rb +6 -5
- metadata +6 -4
data/bin/cherrypick
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
3
|
+
require 'cherrypicker'
|
4
|
+
require 'getoptlong'
|
5
|
+
require 'pathname'
|
6
|
+
|
7
|
+
def usage()
|
8
|
+
puts "Cherrypicker lets you download from; Rapidshare, Hotfile, Hotfile, Youtube, Vimeo & Megavideo"
|
9
|
+
puts "Usage: cherrypick link [--directory|-d] [--username|-u] [--password|-p]"
|
10
|
+
puts
|
11
|
+
puts "example: cherrypick http://www.youtube.com/watch?v=I5DCwN28y8o -d \"~/Movies\""
|
12
|
+
puts "example: cherrypick http://rapidshare.com/files/453165880/test_file.txt -u \"karlentwistle\" -p \"foobar\""
|
13
|
+
end
|
14
|
+
|
15
|
+
if not ARGV[0]
|
16
|
+
usage
|
17
|
+
exit
|
18
|
+
end
|
19
|
+
|
20
|
+
parser = GetoptLong.new
|
21
|
+
parser.set_options(
|
22
|
+
["-d", "--directory", GetoptLong::REQUIRED_ARGUMENT],
|
23
|
+
["-u", "--username", GetoptLong::REQUIRED_ARGUMENT],
|
24
|
+
["-p", "--password", GetoptLong::REQUIRED_ARGUMENT]
|
25
|
+
)
|
26
|
+
|
27
|
+
username = ""
|
28
|
+
password = ""
|
29
|
+
directory = ""
|
30
|
+
|
31
|
+
loop do
|
32
|
+
|
33
|
+
opt, arg = parser.get
|
34
|
+
break if not opt
|
35
|
+
|
36
|
+
case opt
|
37
|
+
when "-u"
|
38
|
+
username = arg
|
39
|
+
when "-p"
|
40
|
+
password = arg
|
41
|
+
when "-d"
|
42
|
+
directory = arg
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
unless directory == "" || nil?
|
48
|
+
p path = Pathname.new(directory)
|
49
|
+
|
50
|
+
if not path.directory?
|
51
|
+
puts "Directory not found " + path.to_s
|
52
|
+
usage
|
53
|
+
exit
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
username = nil unless username != ""
|
58
|
+
password = nil unless password != ""
|
59
|
+
directory = nil unless directory != ""
|
60
|
+
|
61
|
+
Cherrypicker::Cherrypick.new(ARGV[0], :location => directory, :username => username, :password => password)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
module Cherrypicker
|
4
|
+
class Cherrypick
|
5
|
+
attr_accessor :link, :location, :username, :password
|
6
|
+
|
7
|
+
def initialize(link, opts={})
|
8
|
+
o = {
|
9
|
+
:location => nil,
|
10
|
+
:username => nil,
|
11
|
+
:password => nil,
|
12
|
+
}.merge(opts)
|
13
|
+
|
14
|
+
@link = link
|
15
|
+
@username = o[:username]
|
16
|
+
@password = o[:password]
|
17
|
+
@directory = o[:location]
|
18
|
+
|
19
|
+
classname = URI.parse(@link.to_s).host[/[^www\.]+/].capitalize
|
20
|
+
instance = Object.const_get('Cherrypicker').const_get("#{classname}")
|
21
|
+
instance.new(@link, :location => @location, :username => @username, :password => @password).download
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -7,52 +7,53 @@ require 'net/http'
|
|
7
7
|
require 'net/https'
|
8
8
|
require 'progressbar'
|
9
9
|
require 'open-uri'
|
10
|
-
|
11
|
-
class Download
|
12
|
-
|
10
|
+
module Cherrypicker
|
11
|
+
class Download
|
12
|
+
attr_accessor :link, :size, :location, :progress, :filename, :finished
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
14
|
+
def initialize(link, opts={})
|
15
|
+
o = {
|
16
|
+
:location => nil,
|
17
|
+
:size => nil,
|
18
|
+
:filename => nil
|
19
|
+
}.merge(opts)
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
21
|
+
@link = link
|
22
|
+
@size = o[:size]
|
23
|
+
@location = o[:location] ||= ""
|
24
|
+
@filename = o[:filename]
|
25
|
+
@progress = 0
|
26
|
+
@finished = false
|
27
27
|
|
28
|
-
|
29
|
-
|
28
|
+
download_file
|
29
|
+
end
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
31
|
+
def download_file
|
32
|
+
uri = URI.parse(@link.to_s)
|
33
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
34
|
+
http.use_ssl = true if uri.scheme == "https"
|
35
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
36
|
+
request.initialize_http_header({"User-Agent" => Cherrypicker::random_agent})
|
37
|
+
unless (uri.host.include? 'youtube.com') && (uri.request_uri.include? 'videoplayback') #youtube throws EOFError
|
38
|
+
head = http.request_head(URI.escape(uri.path))
|
39
|
+
case head
|
40
|
+
when Net::HTTPForbidden
|
41
|
+
@size = nil #no content-length no progress bar
|
42
|
+
else
|
43
|
+
@size = head['content-length'] if @size.nil? && head['content-length'].to_i > 1024
|
44
|
+
end
|
44
45
|
end
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
46
|
+
http.request(request) do |response|
|
47
|
+
bar = ProgressBar.new((@filename ||= File.basename(uri.path)), @size.to_i) unless @size.nil?
|
48
|
+
File.open(@location + (@filename ||= File.basename(uri.path)), "wb") do |file|
|
49
|
+
response.read_body do |segment|
|
50
|
+
@progress += segment.length
|
51
|
+
bar.set(@progress) unless @size.nil?
|
52
|
+
file.write(segment)
|
53
|
+
end
|
53
54
|
end
|
54
55
|
end
|
56
|
+
@finished = true
|
55
57
|
end
|
56
|
-
@finished = true
|
57
58
|
end
|
58
59
|
end
|
data/lib/cherrypicker/helpers.rb
CHANGED
@@ -4,36 +4,38 @@ require 'net/http'
|
|
4
4
|
require 'net/https'
|
5
5
|
require 'open-uri'
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
if
|
19
|
-
|
7
|
+
module Cherrypicker
|
8
|
+
def self.remote_query(url)
|
9
|
+
begin
|
10
|
+
uri = URI.parse(url)
|
11
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
12
|
+
http.use_ssl = true if uri.scheme == "https"
|
13
|
+
http.open_timeout = 3 # seconds
|
14
|
+
http.read_timeout = 3 # seconds
|
15
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
16
|
+
request.initialize_http_header({"User-Agent" => random_agent})
|
17
|
+
response = http.request(request)
|
18
|
+
if response["X-APICPU"]
|
19
|
+
if (response["X-APICPU"][/(\d*)\/\d*/, 1]).to_i > 9500
|
20
|
+
sleep 60 # seconds
|
21
|
+
end
|
20
22
|
end
|
23
|
+
return response
|
24
|
+
rescue SocketError
|
25
|
+
$stderr.print "IO failed: " + $!
|
26
|
+
raise
|
21
27
|
end
|
22
|
-
return response
|
23
|
-
rescue SocketError
|
24
|
-
$stderr.print "IO failed: " + $!
|
25
|
-
raise
|
26
28
|
end
|
27
|
-
end
|
28
29
|
|
29
|
-
def hash_to_url(hash)
|
30
|
-
|
31
|
-
|
32
|
-
|
30
|
+
def self.hash_to_url(hash)
|
31
|
+
hash.keys.inject('') do |query_string, key|
|
32
|
+
query_string << '&' unless key == hash.keys.first
|
33
|
+
query_string << "#{URI.encode(key.to_s)}=#{URI.encode(hash[key])}"
|
34
|
+
end
|
33
35
|
end
|
34
|
-
end
|
35
36
|
|
36
|
-
def random_agent
|
37
|
-
|
38
|
-
|
37
|
+
def self.random_agent
|
38
|
+
@useragent = ["Mozilla/5.0 (Macintosh; Intel Mac OS X 10_6_7) AppleWebKit/534.24 (KHTML, like Gecko) Chrome/11.0.696.50 Safari/534.24"]
|
39
|
+
return @useragent[0]
|
40
|
+
end
|
39
41
|
end
|
@@ -6,115 +6,116 @@
|
|
6
6
|
# puts rapid.filename
|
7
7
|
# puts rapid.host
|
8
8
|
# rapid.download
|
9
|
+
module Cherrypicker
|
10
|
+
class LinkChecker
|
11
|
+
attr_accessor :links, :status
|
9
12
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
else
|
18
|
-
@status = hotfile
|
13
|
+
def initialize(links)
|
14
|
+
@links = links
|
15
|
+
if links[0] =~ /^http(s|):\/\/(www.|)rapidshare.com/
|
16
|
+
@status = rapidshare
|
17
|
+
else
|
18
|
+
@status = hotfile
|
19
|
+
end
|
19
20
|
end
|
20
|
-
end
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
def rapidshare
|
23
|
+
links = self.links
|
24
|
+
files = Array.new
|
25
|
+
filenames = Array.new
|
26
|
+
singlelinks = Array.new
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
self.links.each do |link|
|
29
|
+
files << link[/files\/(\d*)\//, 1]
|
30
|
+
filenames << link[/files\/\d*\/(.*)/, 1]
|
31
|
+
end
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
33
|
+
query = "http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=checkfiles&" +
|
34
|
+
Cherrypicker::hash_to_url({
|
35
|
+
:files => files.join(","),
|
36
|
+
:filenames => filenames.join(","),
|
37
|
+
:incmd5 => '0'
|
38
|
+
})
|
39
39
|
|
40
|
-
|
40
|
+
check = Cherrypicker::remote_query(query).body.split("\n")
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
#"452966383,ROT007-WEB-2011.rar,23635847,23,1,tl2,0"
|
43
|
+
check.each_with_index do |c, index|
|
44
|
+
c[/([^,]+)\,([^,]+)\,([^,]+)\,([^,]+)\,([^,]+)\,([^,]+)\,([^,]+)/]
|
45
|
+
size = Regexp.last_match(3)
|
46
|
+
if Regexp.last_match(5) == "1"
|
47
|
+
status = "Alive"
|
48
|
+
else
|
49
|
+
status = "Dead"
|
50
|
+
end
|
51
|
+
singlelinks << Cherrypicker::SingleLink.new(links[index], "#{status}", size)
|
50
52
|
end
|
51
|
-
singlelinks << SingleLink.new(links[index], "#{status}", size)
|
52
|
-
end
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
54
|
+
links = {}
|
55
|
+
singlelinks.each do |a|
|
56
|
+
links[a.status] ||= []
|
57
|
+
links[a.status] << [a.link, a.size]
|
58
|
+
end
|
59
|
+
return links
|
58
60
|
end
|
59
|
-
return links
|
60
|
-
end
|
61
61
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
62
|
+
def hotfile
|
63
|
+
links = self.links
|
64
|
+
ids = Array.new
|
65
|
+
keys = Array.new
|
66
|
+
singlelinks = Array.new
|
67
67
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
68
|
+
links.each do |link|
|
69
|
+
link[/http\:\/\/hotfile\.com\/dl\/([^\/]+)\/([^\/]+)\/([^\/]+)/]
|
70
|
+
ids << Regexp.last_match(1)
|
71
|
+
keys << Regexp.last_match(2)
|
72
|
+
end
|
73
73
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
74
|
+
Cherrypicker::query = "http://api.hotfile.com/?action=checklinks&" +
|
75
|
+
hash_to_url({
|
76
|
+
:links => links.join(","),
|
77
|
+
:id => ids.join(","),
|
78
|
+
:keys => keys.join(","),
|
79
|
+
:files => "id,status,size"
|
80
|
+
})
|
81
81
|
|
82
|
-
|
82
|
+
check = Cherrypicker::remote_query(query).body.split("\n")
|
83
83
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
84
|
+
unless check.size == 0
|
85
|
+
#"111044909,1,Playaz-Sub_Zero-PLAYAZ015-WEB-2011-EGM.rar "
|
86
|
+
check.each_with_index do |c, index|
|
87
|
+
c[/([^,]+)\,([^,]+)\,([^,]+)/]
|
88
|
+
name = Regexp.last_match(3)
|
89
|
+
size = Regexp.last_match(1)
|
90
|
+
if Regexp.last_match(2) == "1"
|
91
|
+
status = "Alive"
|
92
|
+
else
|
93
|
+
status = "Dead"
|
94
|
+
end
|
95
|
+
singlelinks << Cherrypicker::SingleLink.new(links[index], "#{status}", size)
|
96
|
+
end
|
97
|
+
else
|
98
|
+
links.each do |link|
|
99
|
+
singlelinks << Cherrypicker::SingleLink.new(link, "Dead", nil)
|
94
100
|
end
|
95
|
-
singlelinks << SingleLink.new(links[index], "#{status}", size)
|
96
|
-
end
|
97
|
-
else
|
98
|
-
links.each do |link|
|
99
|
-
singlelinks << SingleLink.new(link, "Dead", nil)
|
100
101
|
end
|
101
|
-
end
|
102
102
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
103
|
+
links = {}
|
104
|
+
singlelinks.each do |a|
|
105
|
+
links[a.status] ||= []
|
106
|
+
links[a.status] << [a.link, a.size]
|
107
|
+
end
|
108
|
+
return links
|
107
109
|
end
|
108
|
-
return links
|
109
110
|
end
|
110
|
-
end
|
111
111
|
|
112
|
-
class SingleLink
|
113
|
-
|
112
|
+
class SingleLink
|
113
|
+
attr_accessor :link, :status, :size
|
114
114
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
115
|
+
def initialize(link, status, size)
|
116
|
+
@size = size
|
117
|
+
@link = link
|
118
|
+
@status = status
|
119
|
+
end
|
119
120
|
end
|
120
121
|
end
|
@@ -4,44 +4,45 @@
|
|
4
4
|
# hotfile.download
|
5
5
|
|
6
6
|
require 'open-uri'
|
7
|
-
|
8
|
-
class Hotfile
|
9
|
-
|
7
|
+
module Cherrypicker
|
8
|
+
class Hotfile
|
9
|
+
attr_accessor :link, :hostname, :filename, :username, :password, :size, :location, :query
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
11
|
+
def initialize(link, username, password, opts={})
|
12
|
+
if link =~ /hotfile.com\/dl\/\d*\/[0-9a-f]*\/.*.*\.html/
|
13
|
+
@link = link[/(.*)\.html/, 1] #remove .html from link
|
14
|
+
else
|
15
|
+
@link = link
|
16
|
+
end
|
17
17
|
|
18
|
-
|
18
|
+
uri = URI.parse(@link)
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
o = {
|
21
|
+
:location => nil,
|
22
|
+
:size => nil,
|
23
|
+
}.merge(opts)
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
25
|
+
@username = username
|
26
|
+
@password = password
|
27
|
+
@size = o[:size]
|
28
|
+
@location = o[:location]
|
29
|
+
@filename = File.basename(uri.path)
|
30
|
+
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
def download
|
33
|
+
Download.new(download_url, :location => @location, :size => @size, :filename => @filename)
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
def create_url
|
37
|
+
Cherrypicker::hash_to_url({
|
38
|
+
:link => @link,
|
39
|
+
:username => @username.to_s,
|
40
|
+
:password => @password.to_s,
|
41
|
+
})
|
42
|
+
end
|
43
43
|
|
44
|
-
|
45
|
-
|
44
|
+
def download_url
|
45
|
+
Cherrypicker::remote_query("http://api.hotfile.com/?action=getdirectdownloadlink&" + create_url).response.body.gsub(/\n/,'')
|
46
|
+
end
|
46
47
|
end
|
47
48
|
end
|
@@ -2,94 +2,95 @@
|
|
2
2
|
# Megavideo.new("http://www.megavideo.com/?v=2PEKD0YS", :location => "/Volumes/Storage/Desktop/cherrytest/").download
|
3
3
|
|
4
4
|
require 'open-uri'
|
5
|
+
module Cherrypicker
|
6
|
+
class Megavideo
|
7
|
+
attr_accessor :link, :filename, :location, :download_url
|
5
8
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
o = {
|
11
|
-
:location => nil,
|
12
|
-
}.merge(opts)
|
9
|
+
def initialize(link, opts={})
|
10
|
+
o = {
|
11
|
+
:location => nil,
|
12
|
+
}.merge(opts)
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
14
|
+
@link = link
|
15
|
+
@filename = ""
|
16
|
+
@location = o[:location]
|
17
|
+
@download_url = ""
|
18
|
+
@size = 0
|
19
19
|
|
20
|
-
|
20
|
+
video_id = @link[/v[\/=](\w*)&?/, 1]
|
21
21
|
|
22
|
-
|
23
|
-
|
24
|
-
|
22
|
+
#credit http://stackoverflow.com/questions/5748876/build-array-of-flashvars-using-hpricot
|
23
|
+
html = open("http://megavideo.com/?v=#{video_id}").read
|
24
|
+
flashvars = Hash[ html.scan( /flashvars\.(\w+)\s*=\s*["']?(.+?)["']?;/ ) ]
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
26
|
+
key_s = flashvars["s"]
|
27
|
+
key_un = flashvars["un"]
|
28
|
+
key_k1 = flashvars["k1"]
|
29
|
+
key_k2 = flashvars["k2"]
|
30
30
|
|
31
|
-
|
32
|
-
|
31
|
+
title = flashvars["title"]
|
32
|
+
@size = flashvars["size"].to_i * 1024 * 1024
|
33
33
|
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
@download_url = "http://www#{key_s}.megavideo.com/files/#{decrypt(key_un,key_k1,key_k2)}/#{title}.flv"
|
35
|
+
@filename = title + ".flv"
|
36
|
+
end
|
37
37
|
|
38
|
-
|
39
|
-
|
40
|
-
|
38
|
+
def decrypt(un,k1,k2) #credit http://userscripts.org/scripts/review/42944
|
39
|
+
k1 = k1.to_i
|
40
|
+
k2 = k2.to_i
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
42
|
+
#convert the hex "un" to binary
|
43
|
+
location1 = Array.new
|
44
|
+
un.each_char do |char|
|
45
|
+
#puts "#{char} => #{char.to_i(16).to_s(2)}"
|
46
|
+
location1 << ("000" + char.to_i(16).to_s(2))[-4,4]
|
47
|
+
end
|
48
48
|
|
49
|
-
|
49
|
+
location1 = location1.join("").split("")
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
location6 = Array.new
|
52
|
+
0.upto(383) do |n|
|
53
|
+
k1 = (k1 * 11 + 77213) % 81371
|
54
|
+
k2 = (k2 * 17 + 92717) % 192811
|
55
|
+
location6[n] = (k1 + k2) % 128
|
56
|
+
end
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
58
|
+
location3 = Array.new
|
59
|
+
location4 = Array.new
|
60
|
+
location5 = Array.new
|
61
|
+
location8 = Array.new
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
63
|
+
256.downto(0) do |n|
|
64
|
+
location5 = location6[n]
|
65
|
+
location4 = n % 128
|
66
|
+
location8 = location1[location5]
|
67
|
+
location1[location5] = location1[location4]
|
68
|
+
location1[location4] = location8
|
69
|
+
end
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
71
|
+
0.upto(127) do |n|
|
72
|
+
location1[n] = location1[n].to_i ^ location6[n+256] & 1
|
73
|
+
end
|
74
74
|
|
75
|
-
|
76
|
-
|
75
|
+
location12 = location1.join("")
|
76
|
+
location7 = Array.new
|
77
77
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
78
|
+
n = 0
|
79
|
+
while (n < location12.length) do
|
80
|
+
location9 = location12[n,4]
|
81
|
+
location7 << location9
|
82
|
+
n+=4
|
83
|
+
end
|
84
84
|
|
85
|
-
|
86
|
-
|
87
|
-
|
85
|
+
result = ""
|
86
|
+
location7.each do |bin|
|
87
|
+
result = result + bin.to_i(2).to_s(16)
|
88
|
+
end
|
89
|
+
result
|
88
90
|
end
|
89
|
-
result
|
90
|
-
end
|
91
91
|
|
92
|
-
|
93
|
-
|
92
|
+
def download
|
93
|
+
Download.new(@download_url, :location => @location, :size => @size)
|
94
|
+
end
|
94
95
|
end
|
95
96
|
end
|
@@ -3,51 +3,52 @@
|
|
3
3
|
# rapid = Rapidshare.new("http://rapidshare.com/files/329036215/The.Matrix.bandaa25.part06.rar", "username", "password")
|
4
4
|
# rapid.download
|
5
5
|
require 'open-uri'
|
6
|
-
|
7
|
-
class Rapidshare
|
8
|
-
|
6
|
+
module Cherrypicker
|
7
|
+
class Rapidshare
|
8
|
+
attr_accessor :link, :fileid, :filename, :hostname, :username, :password, :size, :location
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
def initialize(link, username, password, opts={})
|
11
|
+
uri = URI.parse(link)
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
13
|
+
o = {
|
14
|
+
:location => nil,
|
15
|
+
:size => nil,
|
16
|
+
}.merge(opts)
|
17
17
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
18
|
+
@link = link
|
19
|
+
@username = username
|
20
|
+
@password = password
|
21
|
+
@fileid = fileid
|
22
|
+
@size = o[:size]
|
23
|
+
@location = o[:location]
|
24
|
+
@filename = File.basename(uri.path)
|
25
|
+
@hostname = hostname
|
26
|
+
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
28
|
+
def download
|
29
|
+
Download.new(@hostname + remote_url, :location => @location, :size => @size, :filename => @filename)
|
30
|
+
end
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
def fileid
|
33
|
+
@link[/files\/(\d*)\//, 1]
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
36
|
+
def remote_url
|
37
|
+
"/cgi-bin/rsapi.cgi?sub=download&" + create_url
|
38
|
+
end
|
39
39
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
40
|
+
def create_url
|
41
|
+
Cherrypicker::hash_to_url({
|
42
|
+
:fileid => @fileid,
|
43
|
+
:filename => @filename,
|
44
|
+
:login => @username.to_s,
|
45
|
+
:password => @password.to_s,
|
46
|
+
})
|
47
|
+
end
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
def hostname
|
50
|
+
query = Cherrypicker::remote_query("http://api.rapidshare.com/cgi-bin/rsapi.cgi?sub=download&" + create_url)
|
51
|
+
query.response.response["Location"][/(.*).rapidshare.com/, 1] + ".rapidshare.com"
|
52
|
+
end
|
53
|
+
end
|
53
54
|
end
|
@@ -8,43 +8,44 @@
|
|
8
8
|
# \_/ |_|_| |_| |_|\___|\___/
|
9
9
|
# you know, for videos
|
10
10
|
#-->
|
11
|
+
module Cherrypicker
|
12
|
+
class Vimeo
|
13
|
+
attr_accessor :link, :filename, :location, :download_url
|
11
14
|
|
12
|
-
|
13
|
-
attr_accessor :link, :filename, :location, :download_url
|
14
|
-
|
15
|
-
def initialize(link, opts={})
|
15
|
+
def initialize(link, opts={})
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
o = {
|
18
|
+
:location => nil,
|
19
|
+
}.merge(opts)
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
@link = link
|
22
|
+
@filename = ""
|
23
|
+
@location = o[:location]
|
24
|
+
@download_url = ""
|
25
25
|
|
26
|
-
|
26
|
+
hostname = "http://www.vimeo.com/moogaloop/play/clip"
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
28
|
+
#the vimeo ID consists of decimal numbers in the URL
|
29
|
+
vimeo_id = @link[/\d+/]
|
30
|
+
response = Cherrypicker::remote_query("http://www.vimeo.com/moogaloop/load/clip:#{vimeo_id}")
|
31
|
+
title = response.body[/<caption>(.*)<\/caption>/, 1]
|
32
|
+
request_signature = response.body[/<request_signature>(.*)<\/request_signature>/, 1]
|
33
|
+
request_signature_expires = response.body[/<request_signature_expires>(\d+)<\/request_signature_expires>/, 1]
|
34
|
+
hd = response.body[/<isHD>(.*)<\/isHD>/, 1]
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
if hd.to_i == 0
|
37
|
+
download_url = ":#{vimeo_id}/#{request_signature}/#{request_signature_expires}"
|
38
|
+
else
|
39
|
+
download_url = ":#{vimeo_id}/#{request_signature}/#{request_signature_expires}/?q=hd"
|
40
|
+
end
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
@filename = title.delete("\"'").gsub(/[^0-9A-Za-z]/, '_') + ".flv"
|
43
|
+
reply = Cherrypicker::remote_query("#{hostname}#{download_url}")
|
44
|
+
@download_url = reply.response['location']
|
45
|
+
end
|
46
46
|
|
47
|
-
|
48
|
-
|
47
|
+
def download
|
48
|
+
Download.new(@download_url, :location => @location)
|
49
|
+
end
|
49
50
|
end
|
50
51
|
end
|
@@ -1,67 +1,68 @@
|
|
1
1
|
# Class that can download from Vimeo
|
2
2
|
# Youtube.new("http://www.youtube.com/watch?v=SF6I5VSZVqc", :location => "/Volumes/Storage/Desktop/cherrytest/").download
|
3
|
+
require 'cgi'
|
3
4
|
|
4
|
-
|
5
|
+
module Cherrypicker
|
6
|
+
class Youtube
|
7
|
+
attr_accessor :link, :filename, :location, :download_url
|
5
8
|
|
6
|
-
|
7
|
-
attr_accessor :link, :filename, :location, :download_url
|
8
|
-
|
9
|
-
def initialize(link, opts={})
|
9
|
+
def initialize(link, opts={})
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
11
|
+
o = {
|
12
|
+
:location => nil,
|
13
|
+
}.merge(opts)
|
14
14
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
15
|
+
@link = link
|
16
|
+
@filename = ""
|
17
|
+
@location = o[:location]
|
18
|
+
@download_url = ""
|
19
19
|
|
20
|
-
|
21
|
-
|
20
|
+
video_id = @link[/v[\/=](.*)/,1]
|
21
|
+
video_info = Cherrypicker::remote_query("http://www.youtube.com/get_video_info?video_id=#{video_id}").body
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
23
|
+
#converting the huge infostring into a hash. simply by splitting it at the & and then splitting it into key and value arround the =
|
24
|
+
#credit https://github.com/rb2k/viddl-rb/blob/master/plugins/youtube.rb
|
25
|
+
video_info_hash = Hash[*video_info.split("&").collect { |v|
|
26
|
+
key, value = v.split "="
|
27
|
+
value = CGI::unescape(value) if value
|
28
|
+
if key =~ /_map/
|
29
|
+
value = value.split(",")
|
30
|
+
value = if key == "fmt_map"
|
31
|
+
Hash[*value.collect{ |v|
|
32
|
+
k2, *v2 = v.split("/")
|
33
|
+
[k2, v2]
|
34
|
+
}.flatten(1)]
|
35
|
+
elsif key == "fmt_url_map" || key == "fmt_stream_map"
|
36
|
+
Hash[*value.collect { |v| v.split("|")}.flatten]
|
37
|
+
end
|
37
38
|
end
|
38
|
-
|
39
|
-
|
40
|
-
}.flatten]
|
39
|
+
[key, value]
|
40
|
+
}.flatten]
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
42
|
+
#Standard = 34 <- flv
|
43
|
+
#Medium = 18 <- mp4
|
44
|
+
#High = 35 <- flv
|
45
|
+
#720p = 22 <- mp4
|
46
|
+
#1080p = 37 <- mp4
|
47
|
+
#mobile = 17 <- 3gp
|
48
|
+
# --> 37 > 22 > 35 > 18 > 34 > 17
|
49
|
+
formats = video_info_hash["fmt_map"].keys
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
51
|
+
format_ext = {}
|
52
|
+
format_ext["37"] = ["mp4", "MP4 Highest Quality 1920x1080"]
|
53
|
+
format_ext["22"] = ["mp4", "MP4 1280x720"]
|
54
|
+
format_ext["35"] = ["flv", "FLV 854x480"]
|
55
|
+
format_ext["34"] = ["flv", "FLV 640x360"]
|
56
|
+
format_ext["18"] = ["mp4", "MP4 480x270"]
|
57
|
+
format_ext["17"] = ["3gp", "3gp"]
|
58
|
+
format_ext["5"] = ["flv", "old default?"]
|
59
59
|
|
60
|
-
|
61
|
-
|
62
|
-
|
60
|
+
@download_url = video_info_hash["fmt_url_map"][formats.first]
|
61
|
+
@filename = video_info_hash["title"].delete("\"'").gsub(/[^0-9A-Za-z]/, '_') + "." + format_ext[formats.first].first
|
62
|
+
end
|
63
63
|
|
64
|
-
|
65
|
-
|
64
|
+
def download
|
65
|
+
Download.new(@download_url, :location => @location, :filename => @filename)
|
66
|
+
end
|
66
67
|
end
|
67
68
|
end
|
data/lib/cherrypicker/version.rb
CHANGED
data/lib/cherrypicker.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
require 'cherrypicker/cherrypick'
|
1
2
|
require 'cherrypicker/download'
|
2
3
|
require 'cherrypicker/linkchecker'
|
3
4
|
require 'cherrypicker/helpers'
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
5
|
+
require 'cherrypicker/plugins/vimeo'
|
6
|
+
require 'cherrypicker/plugins/rapidshare'
|
7
|
+
require 'cherrypicker/plugins/hotfile'
|
8
|
+
require 'cherrypicker/plugins/youtube'
|
9
|
+
require 'cherrypicker/plugins/megavideo'
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: cherrypicker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.3.
|
5
|
+
version: 0.3.3
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Karl Entwistle
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-04-
|
13
|
+
date: 2011-04-23 00:00:00 +01:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -27,8 +27,8 @@ dependencies:
|
|
27
27
|
description:
|
28
28
|
email:
|
29
29
|
- Karl@Entwistle.com
|
30
|
-
executables:
|
31
|
-
|
30
|
+
executables:
|
31
|
+
- cherrypick
|
32
32
|
extensions: []
|
33
33
|
|
34
34
|
extra_rdoc_files: []
|
@@ -38,8 +38,10 @@ files:
|
|
38
38
|
- Gemfile
|
39
39
|
- README.md
|
40
40
|
- Rakefile
|
41
|
+
- bin/cherrypick
|
41
42
|
- cherrypicker.gemspec
|
42
43
|
- lib/cherrypicker.rb
|
44
|
+
- lib/cherrypicker/cherrypick.rb
|
43
45
|
- lib/cherrypicker/download.rb
|
44
46
|
- lib/cherrypicker/helpers.rb
|
45
47
|
- lib/cherrypicker/linkchecker.rb
|