etvnet-seek 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +26 -0
- data/Gemfile +14 -0
- data/README +20 -0
- data/Rakefile +59 -0
- data/VERSION +1 -0
- data/bin/etvnet-seek +27 -0
- data/bin/etvnet-seek.bat +6 -0
- data/etvnet-seek.gemspec +98 -0
- data/lib/etvnet_seek/commander.rb +105 -0
- data/lib/etvnet_seek/cookie_helper.rb +107 -0
- data/lib/etvnet_seek/core/access_page.rb +19 -0
- data/lib/etvnet_seek/core/base_page.rb +43 -0
- data/lib/etvnet_seek/core/browse_media_item.rb +41 -0
- data/lib/etvnet_seek/core/catalog_item.rb +38 -0
- data/lib/etvnet_seek/core/catalog_page.rb +29 -0
- data/lib/etvnet_seek/core/channel_media_item.rb +17 -0
- data/lib/etvnet_seek/core/channels_page.rb +29 -0
- data/lib/etvnet_seek/core/group_media_item.rb +7 -0
- data/lib/etvnet_seek/core/group_page.rb +42 -0
- data/lib/etvnet_seek/core/home_page.rb +18 -0
- data/lib/etvnet_seek/core/login_page.rb +49 -0
- data/lib/etvnet_seek/core/media_info.rb +31 -0
- data/lib/etvnet_seek/core/media_item.rb +52 -0
- data/lib/etvnet_seek/core/media_page.rb +41 -0
- data/lib/etvnet_seek/core/new_item.rb +9 -0
- data/lib/etvnet_seek/core/new_items_page.rb +20 -0
- data/lib/etvnet_seek/core/page.rb +19 -0
- data/lib/etvnet_seek/core/page_factory.rb +51 -0
- data/lib/etvnet_seek/core/search_page.rb +42 -0
- data/lib/etvnet_seek/core/service_call.rb +32 -0
- data/lib/etvnet_seek/easy_auth.rb +52 -0
- data/lib/etvnet_seek/etvnet_seek.rb +10 -0
- data/lib/etvnet_seek/link_info.rb +37 -0
- data/lib/etvnet_seek/main.rb +180 -0
- data/lib/etvnet_seek/user_selection.rb +26 -0
- data/lib/media_converter.rb +85 -0
- data/lib/progressbar.rb +237 -0
- data/lib/runglish.rb +131 -0
- data/spec/etvnet_seek_spec.rb +28 -0
- metadata +200 -0
@@ -0,0 +1,19 @@
|
|
1
|
+
class AccessPage < ServiceCall
|
2
|
+
ACCESS_URL = Page::BASE_URL + "/watch_new/"
|
3
|
+
|
4
|
+
def initialize
|
5
|
+
super(ACCESS_URL)
|
6
|
+
end
|
7
|
+
|
8
|
+
def request_media_info media_file, cookie
|
9
|
+
params = { 'bitrate' => '2', 'view' => 'submit'}
|
10
|
+
headers = { 'Cookie' => cookie }
|
11
|
+
|
12
|
+
@url += "#{media_file}/"
|
13
|
+
|
14
|
+
response = post(params, headers)
|
15
|
+
|
16
|
+
MediaInfo.new Nokogiri::HTML(response.body).css("ref").at(0).attributes["href"].text
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class BasePage < Page
|
2
|
+
|
3
|
+
def title
|
4
|
+
document.css("title").text
|
5
|
+
end
|
6
|
+
|
7
|
+
def page_title
|
8
|
+
document.css(".conteiner h1").text
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
def collect_links path
|
14
|
+
list = []
|
15
|
+
|
16
|
+
document.css("#{path} a").each do |item|
|
17
|
+
href = item.attributes['href'].value
|
18
|
+
text = item.text
|
19
|
+
|
20
|
+
list << MediaItem.new(text, href)
|
21
|
+
end
|
22
|
+
|
23
|
+
list
|
24
|
+
end
|
25
|
+
|
26
|
+
def collect_images path
|
27
|
+
list = []
|
28
|
+
|
29
|
+
document.css("#{path} img").each do |item|
|
30
|
+
list << item.attributes['src'].value.strip
|
31
|
+
end
|
32
|
+
|
33
|
+
list
|
34
|
+
end
|
35
|
+
|
36
|
+
def additional_info node, index
|
37
|
+
children = node.parent.children
|
38
|
+
if children.size > 0
|
39
|
+
element = children.at(index)
|
40
|
+
element.text if element
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class BrowseMediaItem < MediaItem
|
2
|
+
attr_accessor :folder, :showtime, :year, :duration, :image, :rating_image, :rating, :channel
|
3
|
+
|
4
|
+
def initialize(text, link)
|
5
|
+
super(text, link)
|
6
|
+
end
|
7
|
+
|
8
|
+
def folder?
|
9
|
+
folder == true
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
if folder?
|
14
|
+
buffer = "*** Folder *** "
|
15
|
+
else
|
16
|
+
buffer = ""
|
17
|
+
end
|
18
|
+
|
19
|
+
buffer += text
|
20
|
+
|
21
|
+
unless folder?
|
22
|
+
if underscore_name
|
23
|
+
buffer += ": #{underscore_name}"
|
24
|
+
else
|
25
|
+
buffer += ": #{link}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
buffer += " --- #{showtime}" if showtime
|
30
|
+
|
31
|
+
buffer += " (#{media_file})" if not media_file.nil? and media_file.size > 0
|
32
|
+
buffer += " --- #{year}" if not year.nil? and year.size > 2
|
33
|
+
buffer += " --- #{duration}" if not duration.nil? and duration.size > 0
|
34
|
+
buffer += " --- #{channel}" if channel
|
35
|
+
buffer += " --- #{image}" if image
|
36
|
+
buffer += " --- #{rating_image}" if rating_image
|
37
|
+
|
38
|
+
buffer
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
class CatalogItem < MediaItem
|
2
|
+
attr_accessor :folder, :showtime, :duration, :year, :rating_image, :rating, :channel
|
3
|
+
|
4
|
+
def folder?
|
5
|
+
folder == true
|
6
|
+
end
|
7
|
+
|
8
|
+
def to_s
|
9
|
+
if folder?
|
10
|
+
buffer = "*** Folder *** "
|
11
|
+
else
|
12
|
+
buffer = ""
|
13
|
+
end
|
14
|
+
|
15
|
+
buffer += text
|
16
|
+
|
17
|
+
unless folder?
|
18
|
+
if underscore_name
|
19
|
+
buffer += ": #{underscore_name}"
|
20
|
+
else
|
21
|
+
buffer += ": #{link}"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
buffer += " --- #{showtime}" if showtime
|
26
|
+
|
27
|
+
buffer += " (#{media_file})" if not media_file.nil? and media_file.size > 0
|
28
|
+
buffer += " --- #{duration}" if not duration.nil? and duration.size > 0
|
29
|
+
buffer += " --- #{year}" if not year.nil? and year.size > 2
|
30
|
+
|
31
|
+
buffer += " --- #{channel}" if channel
|
32
|
+
buffer += " --- #{rating_image}" if rating_image
|
33
|
+
buffer += " --- #{rating}" if rating
|
34
|
+
|
35
|
+
buffer
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class CatalogPage < MediaPage
|
2
|
+
CATALOG_URL = BASE_URL + "/catalog/"
|
3
|
+
|
4
|
+
def initialize url = CATALOG_URL
|
5
|
+
super(url)
|
6
|
+
end
|
7
|
+
|
8
|
+
def items
|
9
|
+
list = []
|
10
|
+
|
11
|
+
document.css("#table-onecolumn tr").each do |item|
|
12
|
+
links = item.css("td a")
|
13
|
+
|
14
|
+
href = links[0]
|
15
|
+
catalog_href = links[1]
|
16
|
+
|
17
|
+
link = href.attributes['href'].value
|
18
|
+
text = href.attributes['title'].value
|
19
|
+
catalog_link = catalog_href.attributes['href'].value
|
20
|
+
|
21
|
+
item = CatalogItem.new(text, link, catalog_link)
|
22
|
+
|
23
|
+
list << item
|
24
|
+
end
|
25
|
+
|
26
|
+
list
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class ChannelMediaItem < MediaItem
|
2
|
+
attr_reader :catalog_link
|
3
|
+
|
4
|
+
def initialize(text, link, catalog_link)
|
5
|
+
super(text, link)
|
6
|
+
|
7
|
+
@catalog_link = catalog_link
|
8
|
+
end
|
9
|
+
|
10
|
+
def channel
|
11
|
+
link.scan(/\/(\w*)/)[2]
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_s
|
15
|
+
super + " (#{channel})"
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
class ChannelsPage < MediaPage
|
2
|
+
CHANNELS_URL = BASE_URL + "/tv_channels/"
|
3
|
+
|
4
|
+
def initialize url = CHANNELS_URL
|
5
|
+
super(url)
|
6
|
+
end
|
7
|
+
|
8
|
+
def items
|
9
|
+
list = []
|
10
|
+
|
11
|
+
document.css("#table-onecolumn-kanali tr").each do |item|
|
12
|
+
links = item.css("td a")
|
13
|
+
|
14
|
+
text = item.children.at(0).text.strip
|
15
|
+
|
16
|
+
href = links[0]
|
17
|
+
catalog_href = links[1]
|
18
|
+
|
19
|
+
link = href.attributes['href'].value
|
20
|
+
|
21
|
+
catalog_link = catalog_href.attributes['href'].value
|
22
|
+
|
23
|
+
list << ChannelMediaItem.new(text, link, catalog_link)
|
24
|
+
end
|
25
|
+
|
26
|
+
list
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class GroupPage < BasePage
|
2
|
+
protected
|
3
|
+
|
4
|
+
def get_typical_items tag_name
|
5
|
+
list = []
|
6
|
+
|
7
|
+
document.css(tag_name).each do |item|
|
8
|
+
href = item.css("a").at(0)
|
9
|
+
|
10
|
+
unless href.nil?
|
11
|
+
link = href.attributes['href'].value
|
12
|
+
text = href.children.at(0).content
|
13
|
+
|
14
|
+
list << GroupMediaItem.new(text, link)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
list
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class BestHundredPage < GroupPage
|
23
|
+
def items
|
24
|
+
list = get_typical_items("ul.best-list li")
|
25
|
+
|
26
|
+
node = document.css("ul.best-list").at(0).next
|
27
|
+
|
28
|
+
unless node.nil?
|
29
|
+
link = node.attributes['href'].value
|
30
|
+
text = node.children.at(0).content
|
31
|
+
|
32
|
+
list << GroupMediaItem.new(text, link)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class PremierePage < GroupPage
|
38
|
+
def items
|
39
|
+
get_typical_items("ul.recomendation-list li")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class HomePage < Page
|
2
|
+
|
3
|
+
def items
|
4
|
+
list = []
|
5
|
+
|
6
|
+
document.css("#nav a").each do |item|
|
7
|
+
text = item.css("span").text.strip
|
8
|
+
href = item['href']
|
9
|
+
|
10
|
+
unless href == '/' or href =~ /(person|help|register)/
|
11
|
+
list << MediaItem.new(text, href)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
list
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'stringio'
|
2
|
+
|
3
|
+
class LoginPage < ServiceCall
|
4
|
+
LOGIN_URL = "#{Page::BASE_URL}/login/"
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
super(LOGIN_URL)
|
8
|
+
end
|
9
|
+
|
10
|
+
def login username, password
|
11
|
+
headers = { "Content-Type" => "application/x-www-form-urlencoded" }
|
12
|
+
|
13
|
+
response = post({ 'action' => '/login/', 'username' => username, 'password'=> password }, headers)
|
14
|
+
|
15
|
+
cookie = response.response['set-cookie']
|
16
|
+
|
17
|
+
p cookie
|
18
|
+
|
19
|
+
# unless cookie.nil?
|
20
|
+
# cookie = cleanup_cookie(cookie)
|
21
|
+
# end
|
22
|
+
|
23
|
+
cookie
|
24
|
+
#[0..cookie.index(";")-1]
|
25
|
+
end
|
26
|
+
|
27
|
+
# private
|
28
|
+
#
|
29
|
+
# def cleanup_cookie cookie
|
30
|
+
# auth, expires = CookieHelper.get_auth_and_expires(cookie)
|
31
|
+
# username = CookieHelper.get_username(cookie)
|
32
|
+
# path = "/"
|
33
|
+
# domain = ".etvnet.com"
|
34
|
+
#
|
35
|
+
# cookies_text = <<-TEXT
|
36
|
+
# auth=#{auth}; expires=#{expires}; path=#{path}; domain=#{domain}
|
37
|
+
# username=#{username}; expires=#{expires}; path=#{path}; domain=#{domain}
|
38
|
+
# TEXT
|
39
|
+
#
|
40
|
+
# new_cookie = ""
|
41
|
+
#
|
42
|
+
# StringIO.new(cookies_text).each_line do |line|
|
43
|
+
# new_cookie = new_cookie + line.strip + "; "
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# new_cookie
|
47
|
+
# end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
class MediaInfo
|
4
|
+
attr_reader :name, :link, :description, :description_production, :rtsp_link, :speech_lang,
|
5
|
+
:file_length, :channel, :datetime, :popularity, :duration, :rating
|
6
|
+
|
7
|
+
def initialize params
|
8
|
+
@link = params
|
9
|
+
# @session_expired = (params["error_session_expire"] == 1)
|
10
|
+
# @description_production = params["description_production"]
|
11
|
+
# @rtsp_link = params["REDIRECT_URL_RTSP"]
|
12
|
+
# @speech_lang = params["speech_lang"]
|
13
|
+
# @name = params["name"]
|
14
|
+
# @description = params["description"]
|
15
|
+
# @file_length = params["file_length"]
|
16
|
+
# @channel = params["channel"]
|
17
|
+
# @datetime = params["datetime"]
|
18
|
+
# @popularity = params["popularity_24h"]
|
19
|
+
# @duration = params["duration"]
|
20
|
+
# @rating = params["rating"]
|
21
|
+
end
|
22
|
+
|
23
|
+
def resolved?
|
24
|
+
not @link.nil? and not @link.strip.size == 0
|
25
|
+
end
|
26
|
+
|
27
|
+
def session_expired?
|
28
|
+
@session_expired
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'nokogiri'
|
2
|
+
require 'open-uri'
|
3
|
+
|
4
|
+
class MediaItem
|
5
|
+
attr_reader :text, :link, :additional_info
|
6
|
+
attr_reader :underscore_name, :media_file
|
7
|
+
|
8
|
+
def initialize(text, link, additional_info = nil)
|
9
|
+
@text = text
|
10
|
+
@link = link
|
11
|
+
@additional_info = additional_info
|
12
|
+
|
13
|
+
@underscore_name = extract_underscore_name
|
14
|
+
@media_file = extract_media_file
|
15
|
+
end
|
16
|
+
|
17
|
+
def folder?
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_media_links?
|
22
|
+
Nokogiri::HTML(open(Page::BASE_URL + link)).css("b a.media_file").size > 0
|
23
|
+
end
|
24
|
+
|
25
|
+
def ==(object)
|
26
|
+
object.text == text and object.link == link
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_s
|
30
|
+
text
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def extract_underscore_name
|
36
|
+
return nil if link.nil?
|
37
|
+
|
38
|
+
result = link.match(/(\w*)\/(\w*)\/(\w*)\/([\w|-]*)/)
|
39
|
+
|
40
|
+
return nil if result.nil?
|
41
|
+
|
42
|
+
(result.size > 3) ? result[4] : ""
|
43
|
+
end
|
44
|
+
|
45
|
+
def extract_media_file
|
46
|
+
return nil if link.nil?
|
47
|
+
|
48
|
+
result = link.split('/')
|
49
|
+
|
50
|
+
(not result.nil? and result.size > 2) ? result[2] : ""
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class MediaPage < BasePage
|
2
|
+
def items
|
3
|
+
list = []
|
4
|
+
|
5
|
+
document.css(".conteiner table#table-onecolumn tr").each do |item|
|
6
|
+
showtime = item.css("td[1]").text.strip
|
7
|
+
name = item.css("td[2]").text.strip
|
8
|
+
rating_image = item.css("td[3] img").at(0) ? item.css("td[3] img").at(0).attributes['src'].value.strip : ""
|
9
|
+
rating = item.css("td[4]") ? item.css("td[4]").text.strip : ""
|
10
|
+
duration = item.css("td[5]") ? item.css("td[5]").text.strip : ""
|
11
|
+
year = item.css("td[6]") ? item.css("td[6]").text.strip : ""
|
12
|
+
channel = item.css("td[7]") ? item.css("td[7]").text.strip : ""
|
13
|
+
|
14
|
+
link = item.css("td[2] a").at(0).attributes['href'].value
|
15
|
+
|
16
|
+
additional_info = additional_info(item.css("td[2] a").at(0), 2)
|
17
|
+
|
18
|
+
if additional_info.strip.size > 0
|
19
|
+
folder = true
|
20
|
+
else
|
21
|
+
folder = false
|
22
|
+
end
|
23
|
+
|
24
|
+
record = BrowseMediaItem.new(name, link)
|
25
|
+
record.folder = folder
|
26
|
+
record.showtime = showtime
|
27
|
+
record.year = year
|
28
|
+
record.duration = duration
|
29
|
+
record.channel = channel
|
30
|
+
record.rating_image = rating_image
|
31
|
+
record.rating = rating
|
32
|
+
|
33
|
+
list << record
|
34
|
+
end
|
35
|
+
|
36
|
+
list
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
|