etvnet_seek 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +6 -0
- data/README +11 -0
- data/Rakefile +18 -0
- data/bin/etvnet_seek +30 -0
- data/bin/etvnet_seek.bat +6 -0
- data/etvnet_seek.gemspec +41 -0
- data/lib/cookie_helper.rb +93 -0
- data/lib/etvnet_seek.rb +146 -0
- data/spec/etvnet_seek_spec.rb +23 -0
- data/spec/spec.opts +4 -0
- metadata +113 -0
data/CHANGES
ADDED
data/README
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
begin
|
2
|
+
require 'zip_it'
|
3
|
+
rescue LoadError
|
4
|
+
puts "Zipit is not available. Install it with: sudo gem install zipit"
|
5
|
+
exit
|
6
|
+
end
|
7
|
+
|
8
|
+
task :zip do
|
9
|
+
zip :archive => "etvnet_seek.zip", :dir => "."
|
10
|
+
end
|
11
|
+
|
12
|
+
desc "Run gem code locally"
|
13
|
+
task :"run:gem" do
|
14
|
+
command = "bin/etvnet_seek $1 $2"
|
15
|
+
puts ruby("#{command}")
|
16
|
+
end
|
17
|
+
|
18
|
+
task :default => :zip
|
data/bin/etvnet_seek
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems' unless RUBY_VERSION =~ /1.9.*/
|
4
|
+
|
5
|
+
$:.unshift(File::join(File::dirname(File::dirname(__FILE__)), "lib"))
|
6
|
+
|
7
|
+
require 'etvnet_seek'
|
8
|
+
|
9
|
+
client = EtvnetSeek.new
|
10
|
+
|
11
|
+
items = client.search ARGV.join(' ')
|
12
|
+
|
13
|
+
client.display_search_items items
|
14
|
+
|
15
|
+
title_number = ask("Select title : ")
|
16
|
+
|
17
|
+
dot_index = title_number.index('.')
|
18
|
+
|
19
|
+
if not dot_index.nil?
|
20
|
+
pos1 = title_number[0..dot_index-1].to_i
|
21
|
+
pos2 = title_number[dot_index+1..-1].to_i
|
22
|
+
|
23
|
+
movie_link = client.grab_movie_link items[pos1-1][:container][pos2-1][:link]
|
24
|
+
else
|
25
|
+
movie_link = client.grab_movie_link items[title_number.to_i-1][:link]
|
26
|
+
end
|
27
|
+
|
28
|
+
puts "Link: #{movie_link}"
|
29
|
+
|
30
|
+
`open #{movie_link}`
|
data/bin/etvnet_seek.bat
ADDED
data/etvnet_seek.gemspec
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
require "rake"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = %q{etvnet_seek}
|
7
|
+
s.version = "0.1.0"
|
8
|
+
|
9
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
10
|
+
|
11
|
+
s.authors = ["Alexander Shvets"]
|
12
|
+
s.date = %q{2010-02-06}
|
13
|
+
s.description = %q{Command line tool for getting mms urls from etvnet service.}
|
14
|
+
s.email = %q{alexander.shvets@gmail.com}
|
15
|
+
|
16
|
+
s.files = FileList["bin/**", "lib/**/*.rb", "spec/**", "CHANGES", "etvnet_seek.gemspec", "Rakefile", "README"]
|
17
|
+
s.test_files = FileList["spec/**/*.rb"]
|
18
|
+
|
19
|
+
s.has_rdoc = true
|
20
|
+
s.homepage = %q{http://github.com/shvets/etvnet_seek}
|
21
|
+
s.require_paths = ["lib"]
|
22
|
+
s.rubyforge_project = %q{etvnet_seek}
|
23
|
+
s.rubygems_version = %q{1.3.2}
|
24
|
+
s.summary = %q{Command line tool for getting mms urls from etvnet service.}
|
25
|
+
|
26
|
+
if s.respond_to? :specification_version then
|
27
|
+
s.specification_version = 2
|
28
|
+
end
|
29
|
+
|
30
|
+
s.platform = Gem::Platform::RUBY
|
31
|
+
s.requirements = ["none"]
|
32
|
+
s.executables = ['etvnet_seek']
|
33
|
+
s.bindir = "bin"
|
34
|
+
|
35
|
+
s.add_dependency("json_pure", ">= 1.2.0")
|
36
|
+
s.add_dependency("highline", ">= 1.5.1")
|
37
|
+
s.add_dependency("nokogiri", ">= 1.3.3")
|
38
|
+
|
39
|
+
s.add_development_dependency "rspec", ">= 1.2.8"
|
40
|
+
s.add_development_dependency "mocha", ">= 0.9.7"
|
41
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
|
4
|
+
module CookieHelper
|
5
|
+
def retrieve_cookie url, username, password
|
6
|
+
uri = URI.parse(url)
|
7
|
+
conn = Net::HTTP.new(uri.host, uri.port)
|
8
|
+
|
9
|
+
headers = { "Content-Type" => "application/x-www-form-urlencoded" }
|
10
|
+
resp, data = conn.post("/cgi-bin/video/login.fcgi",
|
11
|
+
"action=login&username=#{username}&pwd=#{password}&skip_notice=&redirect=", headers)
|
12
|
+
|
13
|
+
cookie = resp.response['set-cookie']
|
14
|
+
|
15
|
+
cleanup_cookie(cookie)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def cleanup_cookie cookie
|
21
|
+
auth, expires = get_auth_and_expires(cookie)
|
22
|
+
username = get_username(cookie)
|
23
|
+
path = "/"
|
24
|
+
domain = ".etvnet.ca"
|
25
|
+
|
26
|
+
cookies_text = <<-TEXT
|
27
|
+
auth=#{auth}; expires=#{expires}; path=#{path}; domain=#{domain}
|
28
|
+
username=#{username}; expires=#{expires}; path=#{path}; domain=#{domain}
|
29
|
+
TEXT
|
30
|
+
|
31
|
+
new_cookie = ""
|
32
|
+
require 'stringio'
|
33
|
+
StringIO.new(cookies_text).each_line do |line|
|
34
|
+
new_cookie = new_cookie + line.strip + "; "
|
35
|
+
end
|
36
|
+
|
37
|
+
new_cookie
|
38
|
+
end
|
39
|
+
|
40
|
+
def get_auth_and_expires cookie
|
41
|
+
length = "auth=".length
|
42
|
+
|
43
|
+
auth = ""
|
44
|
+
expires = ""
|
45
|
+
|
46
|
+
fragment = cookie
|
47
|
+
|
48
|
+
while true do
|
49
|
+
position = fragment.index("auth=")
|
50
|
+
|
51
|
+
break if position == -1
|
52
|
+
|
53
|
+
if fragment[position+length..position+length] != ";"
|
54
|
+
right_position = fragment[position..-1].index(";")
|
55
|
+
auth = fragment[position+length..position+right_position-1]
|
56
|
+
|
57
|
+
pos1 = position+right_position+1+"expires=".length+1
|
58
|
+
pos2 = fragment[pos1..-1].index(";")
|
59
|
+
expires = fragment[pos1..pos1+pos2-1]
|
60
|
+
break
|
61
|
+
else
|
62
|
+
fragment = fragment[position+length+1..-1]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
[auth, expires]
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_username cookie
|
70
|
+
length = "username=".length
|
71
|
+
|
72
|
+
username = ""
|
73
|
+
|
74
|
+
fragment = cookie
|
75
|
+
|
76
|
+
while true do
|
77
|
+
position = fragment.index("username=")
|
78
|
+
|
79
|
+
break if position == -1
|
80
|
+
|
81
|
+
if fragment[position+length..position+length] != ";"
|
82
|
+
right_position = fragment[position..-1].index(";")
|
83
|
+
username = fragment[position+length..position+right_position-1]
|
84
|
+
|
85
|
+
break
|
86
|
+
else
|
87
|
+
fragment = fragment[position+length+1..-1]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
username
|
92
|
+
end
|
93
|
+
end
|
data/lib/etvnet_seek.rb
ADDED
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'rubygems' unless RUBY_VERSION =~ /1.9.*/
|
2
|
+
|
3
|
+
require 'nokogiri'
|
4
|
+
require 'open-uri'
|
5
|
+
#require "readline"
|
6
|
+
require "highline/import"
|
7
|
+
require 'cgi'
|
8
|
+
require 'json'
|
9
|
+
|
10
|
+
require 'cookie_helper'
|
11
|
+
|
12
|
+
class EtvnetSeek
|
13
|
+
include CookieHelper
|
14
|
+
|
15
|
+
BASE_URL = "http://www.etvnet.ca"
|
16
|
+
SEARCH_URL = BASE_URL + "/cgi-bin/video/eitv_browse.fcgi?action=search"
|
17
|
+
ACCESS_URL = BASE_URL + "/cgi-bin/video/access.fcgi"
|
18
|
+
LOGIN_URL = BASE_URL + "/cgi-bin/video/login.fcgi"
|
19
|
+
|
20
|
+
def cookie
|
21
|
+
@cookie ||= get_cookie
|
22
|
+
end
|
23
|
+
|
24
|
+
def search keywords, order_direction = '-'
|
25
|
+
search_items SEARCH_URL + "&keywords=#{CGI.escape(keywords)}&order_direction=#{order_direction}"
|
26
|
+
end
|
27
|
+
|
28
|
+
def search_items url
|
29
|
+
doc = Nokogiri::HTML(open(url))
|
30
|
+
|
31
|
+
list = []
|
32
|
+
|
33
|
+
doc.css("table tr[2] td table").each do |item|
|
34
|
+
links = item.css(".media_file")
|
35
|
+
|
36
|
+
links.each_with_index do |link, index|
|
37
|
+
if index % 2 != 0
|
38
|
+
href = link.attributes['href'].value
|
39
|
+
|
40
|
+
new_link = list.select {|l| l[:link] == href}.empty?
|
41
|
+
|
42
|
+
if new_link
|
43
|
+
record = {:link => href,
|
44
|
+
:name => link.content.strip,
|
45
|
+
# :first_time => link.parent.parent.previous.previous.previous.previous.content.strip,
|
46
|
+
# :year => link.parent.parent.next.next.content.strip,
|
47
|
+
# :how_long => link.parent.parent.next.next.next.next.content.strip
|
48
|
+
}
|
49
|
+
|
50
|
+
if href =~ /action=browse_container/
|
51
|
+
record[:container] = search_items(href)
|
52
|
+
else
|
53
|
+
result = href.match(/(\w*)\/(\w*)\/(\w*)\/([\w|-]*)/)
|
54
|
+
|
55
|
+
record[:media_file] = (result.size > 2) ? result[3] : ""
|
56
|
+
record[:english_name] = (result.size > 3) ? result[4] : ""
|
57
|
+
end
|
58
|
+
|
59
|
+
list << record
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
list
|
66
|
+
end
|
67
|
+
|
68
|
+
def display_search_items items
|
69
|
+
items.each_with_index do |item1, index1|
|
70
|
+
|
71
|
+
if item1[:container].nil?
|
72
|
+
puts "#{index1+1}. #{item1[:english_name]} --- #{item1[:media_file]} --- #{item1[:name]}"
|
73
|
+
else
|
74
|
+
puts "#{index1+1}. #{item1[:name]}"
|
75
|
+
|
76
|
+
item1[:container].each_with_index do |item2, index2|
|
77
|
+
puts " #{index1+1}.#{index2+1}. #{item2[:english_name]} --- #{item2[:media_file]} --- #{item2[:name]}"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def grab_movie_link link
|
84
|
+
result = link.match(/(\w*)\/(\w*)\/(\w*)\/([\w|-]*)/)
|
85
|
+
|
86
|
+
media_file = (not result.nil? and result.size > 2) ? result[3] : ""
|
87
|
+
|
88
|
+
media_info = request_media_info media_file, cookie
|
89
|
+
|
90
|
+
mms_link(media_info)
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
|
95
|
+
def get_cookie
|
96
|
+
file_name = ENV['HOME'] + "/.etvnet-seek"
|
97
|
+
|
98
|
+
if File.exist? file_name
|
99
|
+
cookie = read_user_file file_name
|
100
|
+
else
|
101
|
+
username = ask("Enter username : " )
|
102
|
+
password = ask("Enter password : " ) { |q| q.echo = '*' }
|
103
|
+
|
104
|
+
cookie = retrieve_cookie LOGIN_URL, username, password
|
105
|
+
|
106
|
+
write_user_file file_name, cookie
|
107
|
+
end
|
108
|
+
|
109
|
+
cookie
|
110
|
+
end
|
111
|
+
|
112
|
+
def read_user_file file_name
|
113
|
+
File.open(file_name, 'r') do |file|
|
114
|
+
return file.gets
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def write_user_file file_name, cookie
|
119
|
+
File.open(file_name, 'w') do |file|
|
120
|
+
file.puts cookie
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def request_media_info media_file, cookie
|
125
|
+
url = URI.parse(ACCESS_URL)
|
126
|
+
conn = Net::HTTP.new(url.host, url.port)
|
127
|
+
|
128
|
+
headers = { 'Cookie' => cookie }
|
129
|
+
|
130
|
+
request = Net::HTTP::Post.new(url.request_uri, headers)
|
131
|
+
|
132
|
+
request.set_form_data(
|
133
|
+
{ 'action' => 'start_video', 'bitrate' => '600',
|
134
|
+
'media_file'=> media_file, 'replay' => '1', 'skin' => 'JSON'
|
135
|
+
}
|
136
|
+
)
|
137
|
+
|
138
|
+
response = conn.request(request)
|
139
|
+
|
140
|
+
response.body
|
141
|
+
end
|
142
|
+
|
143
|
+
def mms_link media_info
|
144
|
+
JSON.parse(media_info)["PARAMETERS"]["REDIRECT_URL"]
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
|
3
|
+
require 'rubygems' unless RUBY_VERSION =~ /1.9.*/
|
4
|
+
|
5
|
+
#require 'spec'
|
6
|
+
|
7
|
+
require 'etvnet_seek'
|
8
|
+
|
9
|
+
describe EtvnetSeek do
|
10
|
+
|
11
|
+
before :each do
|
12
|
+
@client = EtvnetSeek.new
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return search menu items" do
|
16
|
+
keywords = "красная шапочка"
|
17
|
+
|
18
|
+
@client.search(keywords).size.should > 0
|
19
|
+
items = @client.search(keywords)
|
20
|
+
@client.display_search_items items
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
data/spec/spec.opts
ADDED
metadata
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: etvnet_seek
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Alexander Shvets
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-02-06 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: json_pure
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.2.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: highline
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.5.1
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: nokogiri
|
37
|
+
type: :runtime
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.3.3
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: rspec
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.2.8
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: mocha
|
57
|
+
type: :development
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 0.9.7
|
64
|
+
version:
|
65
|
+
description: Command line tool for getting mms urls from etvnet service.
|
66
|
+
email: alexander.shvets@gmail.com
|
67
|
+
executables:
|
68
|
+
- etvnet_seek
|
69
|
+
extensions: []
|
70
|
+
|
71
|
+
extra_rdoc_files: []
|
72
|
+
|
73
|
+
files:
|
74
|
+
- bin/etvnet_seek
|
75
|
+
- bin/etvnet_seek.bat
|
76
|
+
- lib/cookie_helper.rb
|
77
|
+
- lib/etvnet_seek.rb
|
78
|
+
- spec/etvnet_seek_spec.rb
|
79
|
+
- spec/spec.opts
|
80
|
+
- CHANGES
|
81
|
+
- etvnet_seek.gemspec
|
82
|
+
- Rakefile
|
83
|
+
- README
|
84
|
+
has_rdoc: true
|
85
|
+
homepage: http://github.com/shvets/etvnet_seek
|
86
|
+
licenses: []
|
87
|
+
|
88
|
+
post_install_message:
|
89
|
+
rdoc_options: []
|
90
|
+
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: "0"
|
98
|
+
version:
|
99
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: "0"
|
104
|
+
version:
|
105
|
+
requirements:
|
106
|
+
- none
|
107
|
+
rubyforge_project: etvnet_seek
|
108
|
+
rubygems_version: 1.3.5
|
109
|
+
signing_key:
|
110
|
+
specification_version: 2
|
111
|
+
summary: Command line tool for getting mms urls from etvnet service.
|
112
|
+
test_files:
|
113
|
+
- spec/etvnet_seek_spec.rb
|