etvnet-seek 0.7.2 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +18 -8
- data/README +1 -1
- data/Rakefile +27 -5
- data/VERSION +1 -1
- data/bin/etvnet-seek +8 -3
- data/etvnet-seek.gemspec +79 -42
- data/lib/etvnet_seek/accessor.rb +64 -0
- data/lib/etvnet_seek/commander.rb +37 -21
- data/lib/etvnet_seek/core/access_page.rb +23 -6
- data/lib/etvnet_seek/core/audio_page.rb +26 -0
- data/lib/etvnet_seek/core/best_hundred_page.rb +20 -0
- data/lib/etvnet_seek/core/browse_media_item.rb +1 -0
- data/lib/etvnet_seek/core/catalog_page.rb +26 -14
- data/lib/etvnet_seek/core/channels_page.rb +6 -2
- data/lib/etvnet_seek/core/group_media_item.rb +2 -0
- data/lib/etvnet_seek/core/group_page.rb +9 -23
- data/lib/etvnet_seek/core/home_page.rb +5 -2
- data/lib/etvnet_seek/core/items_page.rb +140 -0
- data/lib/etvnet_seek/core/items_page_factory.rb +47 -0
- data/lib/etvnet_seek/core/login_page.rb +3 -1
- data/lib/etvnet_seek/core/media_info.rb +3 -18
- data/lib/etvnet_seek/core/media_item.rb +10 -2
- data/lib/etvnet_seek/core/media_page.rb +54 -27
- data/lib/etvnet_seek/core/new_item.rb +2 -0
- data/lib/etvnet_seek/core/new_items_page.rb +4 -1
- data/lib/etvnet_seek/core/page.rb +2 -0
- data/lib/etvnet_seek/core/premiere_page.rb +7 -0
- data/lib/etvnet_seek/core/radio_page.rb +23 -0
- data/lib/etvnet_seek/core/search_page.rb +3 -33
- data/lib/etvnet_seek/core/service_call.rb +34 -6
- data/lib/etvnet_seek/core/top_this_week_page.rb +20 -0
- data/lib/etvnet_seek/etvnet_seek.rb +1 -4
- data/lib/etvnet_seek/main.rb +113 -84
- data/spec/etvnet_seek_spec.rb +10 -8
- data/spec/spec_helper.rb +3 -0
- data/spec/unit/pages_spec.rb +77 -0
- metadata +182 -32
- data/lib/etvnet_seek/core/base_page.rb +0 -43
- data/lib/etvnet_seek/core/page_factory.rb +0 -51
@@ -1,5 +1,11 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
require 'etvnet_seek/core/page'
|
4
|
+
require 'etvnet_seek/core/media_info'
|
5
|
+
require 'etvnet_seek/core/service_call'
|
6
|
+
|
1
7
|
class AccessPage < ServiceCall
|
2
|
-
ACCESS_URL = Page::BASE_URL + "/
|
8
|
+
ACCESS_URL = Page::BASE_URL + "/watch/"
|
3
9
|
|
4
10
|
def initialize
|
5
11
|
super(ACCESS_URL)
|
@@ -7,13 +13,24 @@ class AccessPage < ServiceCall
|
|
7
13
|
|
8
14
|
def request_media_info media_file, cookie
|
9
15
|
params = { 'bitrate' => '2', 'view' => 'submit'}
|
10
|
-
headers = { 'Cookie' => cookie }
|
11
16
|
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
if true
|
18
|
+
params['high_quality'] = ""
|
19
|
+
end
|
20
|
+
|
21
|
+
headers = { 'Cookie' => cookie, 'X-Requested-With' => 'XMLHttpRequest' }
|
22
|
+
|
23
|
+
response = post(params, headers, url + "#{media_file}/")
|
24
|
+
|
25
|
+
# MediaInfo.new Nokogiri::HTML(response.body).css("ref").at(0).attributes["href"].text
|
26
|
+
|
27
|
+
json = JSON.parse(response.body)
|
15
28
|
|
16
|
-
|
29
|
+
if response.kind_of? Net::HTTPOK
|
30
|
+
MediaInfo.new json["url"]
|
31
|
+
else
|
32
|
+
raise "Problem getting url: #{response.class.name}: #{json['msg']} "
|
33
|
+
end
|
17
34
|
end
|
18
35
|
|
19
36
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'etvnet_seek/core/items_page'
|
2
|
+
require 'etvnet_seek/core/media_item'
|
3
|
+
|
4
|
+
class AudioPage < ItemsPage
|
5
|
+
AUDIO_URL = BASE_URL + "/audio/"
|
6
|
+
|
7
|
+
def initialize url = AUDIO_URL
|
8
|
+
super(url)
|
9
|
+
end
|
10
|
+
|
11
|
+
def items
|
12
|
+
list = []
|
13
|
+
|
14
|
+
document.css("#nav a").each do |item|
|
15
|
+
text = item.css("span").text.strip
|
16
|
+
href = item['href']
|
17
|
+
|
18
|
+
unless href == '/' or href =~ /(press|register|persons)/
|
19
|
+
list << MediaItem.new(text, href)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
list
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'etvnet_seek/core/group_page'
|
2
|
+
require 'etvnet_seek/core/media_item'
|
3
|
+
|
4
|
+
class BestHundredPage < GroupPage
|
5
|
+
def items
|
6
|
+
parent = document.css(".conteiner .best").at(0).parent
|
7
|
+
parent.css("ul.best-list li")
|
8
|
+
|
9
|
+
list = get_typical_items("ul.best-list li", parent)
|
10
|
+
|
11
|
+
node = parent.css("ul.best-list").at(0).next
|
12
|
+
|
13
|
+
unless node.nil?
|
14
|
+
link = node.attributes['href'].value
|
15
|
+
text = node.children.at(0).content
|
16
|
+
|
17
|
+
list << GroupMediaItem.new(text, link)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class CatalogPage <
|
1
|
+
class CatalogPage < ItemsPage
|
2
2
|
CATALOG_URL = BASE_URL + "/catalog/"
|
3
3
|
|
4
4
|
def initialize url = CATALOG_URL
|
@@ -8,19 +8,31 @@ class CatalogPage < MediaPage
|
|
8
8
|
def items
|
9
9
|
list = []
|
10
10
|
|
11
|
-
document.css("#table-onecolumn tr").
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
11
|
+
document.css(".conteiner #results #table-onecolumn tr").each_with_index do |item, index|
|
12
|
+
next if index == 0
|
13
|
+
|
14
|
+
showtime = item.css("td[1]").text.strip
|
15
|
+
rating_image = item.css("td[3] img").at(0) ? item.css("td[3] img").at(0).attributes['src'].value.strip : ""
|
16
|
+
rating = item.css("td[4]") ? item.css("td[4]").text.strip : ""
|
17
|
+
name = item.css("td[2]").text.strip
|
18
|
+
duration = item.css("td[5]") ? item.css("td[5]").text.strip : ""
|
19
|
+
link = item.css("td[2] a").at(0)
|
20
|
+
|
21
|
+
unless link.nil?
|
22
|
+
href = link.attributes['href'].value
|
23
|
+
digit_scan = name.scan(/\((\d*).*\)/)[0]
|
24
|
+
amount_expr = digit_scan.nil? ? 0 : digit_scan[0].to_i
|
25
|
+
folder = (amount_expr > 1) ? true : false
|
26
|
+
|
27
|
+
record = BrowseMediaItem.new(name, href)
|
28
|
+
record.folder = folder
|
29
|
+
record.showtime = showtime
|
30
|
+
record.duration = duration
|
31
|
+
record.rating_image = rating_image
|
32
|
+
record.rating = rating
|
33
|
+
|
34
|
+
list << record
|
35
|
+
end
|
24
36
|
end
|
25
37
|
|
26
38
|
list
|
@@ -1,5 +1,9 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'etvnet_seek/core/page'
|
2
|
+
require 'etvnet_seek/core/items_page'
|
3
|
+
require 'etvnet_seek/core/channel_media_item'
|
4
|
+
|
5
|
+
class ChannelsPage < ItemsPage
|
6
|
+
CHANNELS_URL = Page::BASE_URL + "/tv_channels/"
|
3
7
|
|
4
8
|
def initialize url = CHANNELS_URL
|
5
9
|
super(url)
|
@@ -1,10 +1,16 @@
|
|
1
|
-
|
1
|
+
require 'etvnet_seek/core/items_page'
|
2
|
+
require 'etvnet_seek/core/group_media_item'
|
3
|
+
|
4
|
+
class GroupPage < ItemsPage
|
5
|
+
|
2
6
|
protected
|
3
7
|
|
4
|
-
def get_typical_items tag_name
|
8
|
+
def get_typical_items tag_name, parent=nil
|
5
9
|
list = []
|
6
10
|
|
7
|
-
|
11
|
+
root = parent.nil? ? document : parent
|
12
|
+
|
13
|
+
root.css(tag_name).each do |item|
|
8
14
|
href = item.css("a").at(0)
|
9
15
|
|
10
16
|
unless href.nil?
|
@@ -19,24 +25,4 @@ class GroupPage < BasePage
|
|
19
25
|
end
|
20
26
|
end
|
21
27
|
|
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
28
|
|
@@ -1,4 +1,7 @@
|
|
1
|
-
|
1
|
+
require 'etvnet_seek/core/items_page'
|
2
|
+
require 'etvnet_seek/core/media_item'
|
3
|
+
|
4
|
+
class HomePage < ItemsPage
|
2
5
|
|
3
6
|
def items
|
4
7
|
list = []
|
@@ -7,7 +10,7 @@ class HomePage < Page
|
|
7
10
|
text = item.css("span").text.strip
|
8
11
|
href = item['href']
|
9
12
|
|
10
|
-
unless href == '/' or href =~ /(person|help|register)/
|
13
|
+
unless href == '/' or href =~ /(person|help|register|press)/
|
11
14
|
list << MediaItem.new(text, href)
|
12
15
|
end
|
13
16
|
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require 'etvnet_seek/core/page'
|
2
|
+
require 'etvnet_seek/core/media_item'
|
3
|
+
|
4
|
+
class ItemsPage < Page
|
5
|
+
def items
|
6
|
+
[]
|
7
|
+
end
|
8
|
+
|
9
|
+
def title
|
10
|
+
document.css("title").text
|
11
|
+
end
|
12
|
+
|
13
|
+
def page_title
|
14
|
+
document.css(".conteiner h1").text
|
15
|
+
end
|
16
|
+
|
17
|
+
def navigation_menu
|
18
|
+
list = collect_links "#nav"
|
19
|
+
|
20
|
+
list.select { |element| not element =~ /(press|register|persons)/}
|
21
|
+
end
|
22
|
+
|
23
|
+
def category_breadcrumbs
|
24
|
+
collect_links ".info_menu-onecolumn .path_movie_menu"
|
25
|
+
end
|
26
|
+
|
27
|
+
def categories
|
28
|
+
list = []
|
29
|
+
|
30
|
+
document.css(".movie_menu-onecolumn ul li").each do |item|
|
31
|
+
href = item.css("a").at(0).attributes['href'].value
|
32
|
+
text = item.css("a").at(0).text
|
33
|
+
additional_info = item.css("span.small-text-movie-menu")
|
34
|
+
|
35
|
+
list << MediaItem.new(text, href, additional_info)
|
36
|
+
end
|
37
|
+
|
38
|
+
list
|
39
|
+
end
|
40
|
+
|
41
|
+
def title_items
|
42
|
+
list = []
|
43
|
+
|
44
|
+
document.css("#table-onecolumn th").each do |item|
|
45
|
+
link = item.css("a").at(0)
|
46
|
+
|
47
|
+
if link
|
48
|
+
href = link.attributes['href'].value
|
49
|
+
text = link.text
|
50
|
+
else
|
51
|
+
href = nil
|
52
|
+
text = item.text
|
53
|
+
end
|
54
|
+
|
55
|
+
list << MediaItem.new(text, href)
|
56
|
+
end
|
57
|
+
|
58
|
+
# root = nil
|
59
|
+
# document.css("table-onecolumn").each do |item|
|
60
|
+
# link = item.attributes['href']
|
61
|
+
#
|
62
|
+
# if link.value =~ /order_by/
|
63
|
+
# root = link.parent.parent.parent.parent.parent.parent
|
64
|
+
# break
|
65
|
+
# end
|
66
|
+
# end
|
67
|
+
#
|
68
|
+
# if root
|
69
|
+
# root.css("td").each do |item|
|
70
|
+
# node1 = item.search("table/tr/td")
|
71
|
+
# node2 = item.search("table/tr/td[2]")
|
72
|
+
# if node1.search("a").size > 0
|
73
|
+
# link = node1.css("a").first
|
74
|
+
#
|
75
|
+
# text = link.text
|
76
|
+
# href = link.attributes['href'].value
|
77
|
+
#
|
78
|
+
# if node2.search("#SPAN_all_letters").size > 0
|
79
|
+
# additional_info = node2.search("#SPAN_all_letters").at(0).inner_html
|
80
|
+
# index = additional_info.index('<a href="#"')
|
81
|
+
# additional_info = additional_info[0..index-2].strip + "]"
|
82
|
+
# else
|
83
|
+
# additional_info = nil
|
84
|
+
# end
|
85
|
+
#
|
86
|
+
# list << MediaItem.new(text, href, additional_info)
|
87
|
+
# end
|
88
|
+
# end
|
89
|
+
# end
|
90
|
+
|
91
|
+
list
|
92
|
+
end
|
93
|
+
|
94
|
+
def see_too_items
|
95
|
+
collect_links ".description .all_next_prev_movie ul li"
|
96
|
+
end
|
97
|
+
|
98
|
+
def page_browser
|
99
|
+
node = document.css(".paging .holder").first
|
100
|
+
|
101
|
+
node.nil? ? nil : node.inner_html
|
102
|
+
end
|
103
|
+
|
104
|
+
def description
|
105
|
+
document.css(".description-container").inner_html
|
106
|
+
end
|
107
|
+
|
108
|
+
protected
|
109
|
+
|
110
|
+
def collect_links path
|
111
|
+
list = []
|
112
|
+
|
113
|
+
document.css("#{path} a").each do |item|
|
114
|
+
href = item.attributes['href'].value
|
115
|
+
text = item.text
|
116
|
+
|
117
|
+
list << MediaItem.new(text, href)
|
118
|
+
end
|
119
|
+
|
120
|
+
list
|
121
|
+
end
|
122
|
+
|
123
|
+
def collect_images path
|
124
|
+
list = []
|
125
|
+
|
126
|
+
document.css("#{path} img").each do |item|
|
127
|
+
list << item.attributes['src'].value.strip
|
128
|
+
end
|
129
|
+
|
130
|
+
list
|
131
|
+
end
|
132
|
+
|
133
|
+
def additional_info node, index
|
134
|
+
children = node.parent.children
|
135
|
+
if children.size > 0
|
136
|
+
element = children.at(index)
|
137
|
+
element.text if element
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'etvnet_seek/core/home_page'
|
2
|
+
require 'etvnet_seek/core/channels_page'
|
3
|
+
require 'etvnet_seek/core/catalog_page'
|
4
|
+
require 'etvnet_seek/core/media_page'
|
5
|
+
require 'etvnet_seek/core/search_page'
|
6
|
+
require 'etvnet_seek/core/best_hundred_page'
|
7
|
+
require 'etvnet_seek/core/top_this_week_page'
|
8
|
+
require 'etvnet_seek/core/premiere_page'
|
9
|
+
require 'etvnet_seek/core/new_items_page'
|
10
|
+
require 'etvnet_seek/core/audio_page'
|
11
|
+
require 'etvnet_seek/core/radio_page'
|
12
|
+
|
13
|
+
class ItemsPageFactory
|
14
|
+
def self.create mode, params = []
|
15
|
+
url = (mode == 'search') ? nil : (params.class == String ? params : params[0])
|
16
|
+
|
17
|
+
case mode
|
18
|
+
when 'main' then
|
19
|
+
page = HomePage.new
|
20
|
+
when 'channels' then
|
21
|
+
page = ChannelsPage.new
|
22
|
+
when 'catalog' then
|
23
|
+
page = CatalogPage.new
|
24
|
+
when 'media' then
|
25
|
+
page = MediaPage.new url
|
26
|
+
when 'search' then
|
27
|
+
page = SearchPage.new *params
|
28
|
+
when 'best_hundred' then
|
29
|
+
page = BestHundredPage.new
|
30
|
+
when 'top_this_week' then
|
31
|
+
page = TopThisWeekPage.new
|
32
|
+
when 'premiere' then
|
33
|
+
page = PremierePage.new
|
34
|
+
when 'new_items' then
|
35
|
+
page = NewItemsPage.new
|
36
|
+
when 'audio' then
|
37
|
+
page = AudioPage.new url
|
38
|
+
when 'radio' then
|
39
|
+
page = RadioPage.new
|
40
|
+
else
|
41
|
+
page = nil
|
42
|
+
end
|
43
|
+
|
44
|
+
page
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require 'stringio'
|
2
2
|
|
3
|
+
require 'etvnet_seek/core/service_call'
|
4
|
+
|
3
5
|
class LoginPage < ServiceCall
|
4
6
|
LOGIN_URL = "#{Page::BASE_URL}/login/"
|
5
7
|
|
@@ -14,7 +16,7 @@ class LoginPage < ServiceCall
|
|
14
16
|
|
15
17
|
cookie = response.response['set-cookie']
|
16
18
|
|
17
|
-
|
19
|
+
# p cookie
|
18
20
|
|
19
21
|
# unless cookie.nil?
|
20
22
|
# cookie = cleanup_cookie(cookie)
|
@@ -1,23 +1,8 @@
|
|
1
|
-
require 'json'
|
2
|
-
|
3
1
|
class MediaInfo
|
4
|
-
attr_reader :
|
5
|
-
:file_length, :channel, :datetime, :popularity, :duration, :rating
|
2
|
+
attr_reader :link
|
6
3
|
|
7
|
-
def initialize
|
8
|
-
@link =
|
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"]
|
4
|
+
def initialize link
|
5
|
+
@link = link
|
21
6
|
end
|
22
7
|
|
23
8
|
def resolved?
|