etvnet_seek 0.1.0
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/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
|