etvnet-seek 0.7.2
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 +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
|
+
|