ex_ua 0.0.2 → 0.0.3

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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5b80529d1a796a452c402596e0911c611cd09544
4
+ data.tar.gz: d576cc7c09db8586703340fce9e73bc9e2eca226
5
+ SHA512:
6
+ metadata.gz: 75a02afae964de65c138426ec6d792e1c18d8234353d796c8153d3d66c5d802eda8870c8ee0bb15126a07059b07d8462e6f06ad44a44a8cca9dc8b26a794fe1c
7
+ data.tar.gz: b276646a9b6d09b7505bc7f5f268cb4bfa82a73efe4ad8fa469e2e2c765abc0aa79614c893a6cfd7e81edd6110467b36e240c8b94bb92bc06ed568f00148d169
data/README.md CHANGED
@@ -3,6 +3,8 @@ Description
3
3
 
4
4
  ex_ua library gives you some API to access http://ex.ua/
5
5
 
6
+ Docs: http://rubydoc.info/github/Antti/ex_ua/master/frames
7
+
6
8
  Install
7
9
  =======
8
10
 
@@ -16,5 +18,6 @@ Example usage
16
18
  client = ExUA::Client.new
17
19
  base_categories = client.base_categories('ru') # Gives you array of all base categories for a given language
18
20
  category = base_categories.first # Select first category (usually video)
19
- sub_categories = category.categories
20
-
21
+ sub_categories = category.categories # Select sub-categories of a category
22
+ example_video_category = sub_categories.first.categories.first
23
+ download_items = example_video_category.items # Here you'll have an array of download items in a given category with #download_url
data/ex_ua.gemspec CHANGED
@@ -19,6 +19,8 @@ Gem::Specification.new do |s|
19
19
  s.require_paths = ["lib"]
20
20
 
21
21
  # specify any dependencies here; for example:
22
- s.add_development_dependency "rspec"
23
- s.add_runtime_dependency "mechanize"
22
+ s.add_development_dependency "rspec", '>= 2.10.0'
23
+ s.add_development_dependency "rake", '>= 0.9.0'
24
+ s.add_runtime_dependency "httparty", '>= 0.10.0'
25
+ s.add_runtime_dependency "nokogiri", '>= 1.5.0'
24
26
  end
@@ -1,14 +1,24 @@
1
+ # @author Andrii Dmytrenko
2
+ require 'cgi'
1
3
  module ExUA
2
4
  # Represents a category
5
+ # @example Usage
6
+ # #You usually get categories thru ExUA::Client object
7
+ # client = ExUA::Client.new
8
+ # categories = client.base_categories('ru')
9
+ # sub_categories = categories.first.categories
10
+ # items = sub_categories.first.categories.first.items
3
11
  class Category
12
+ class NotFound < StandardError; end
4
13
  attr_reader :id,:parent, :url
5
14
 
6
- # @params[ExUA::Client] ex_ua client
7
- # @params[Fixnum] id Category id
8
- # @params[Hash] options
9
- def initialize(ex_ua, id, options={})
10
- @ex_ua,@id = ex_ua, id
11
- @url = options[:url] || url_from_id(id)
15
+ # @param[ExUA::Client] ex_ua client
16
+ # @param[Fixnum] id Category id
17
+ # @param[Hash] options
18
+ def initialize(ex_ua, options={})
19
+ @ex_ua = ex_ua
20
+ @id = options[:id]
21
+ @url = strip_url(options[:url]) || url_from_id(id)
12
22
  @name = options.delete(:name)
13
23
  @parent = options.delete(:parent)
14
24
  end
@@ -22,30 +32,38 @@ module ExUA
22
32
  end
23
33
 
24
34
  # Canonical url
35
+ # @return [String]
25
36
  def canonical_url
26
37
  @canonical_url ||= page_content.root.xpath("//link[@rel='canonical']/@href").first.value
27
38
  end
28
39
 
29
40
  # Category name
41
+ # @return [String]
30
42
  def name
31
43
  @name ||= page_content.root.xpath("//meta[@name='title']/@content").first.value
32
44
  end
33
45
 
34
46
  # Category description
47
+ # @return [String]
35
48
  def description
36
49
  @description ||= page_content.root.xpath("//meta[@name='description']/@content").first.value
37
50
  end
38
51
 
39
52
  # Category picture
53
+ # @return [String] url for a picture
40
54
  def picture
41
- @picture ||= page_content.root.xpath("//link[@rel='image_src']/@href").first.value.split("?").first
55
+ @picture ||= (
56
+ pic = page_content.root.xpath("//link[@rel='image_src']/@href").first
57
+ pic && pic.value.split("?").first
58
+ )
42
59
  end
43
60
 
44
61
  # List of subcategories
62
+ # @return [Array<ExUA::Category>]
45
63
  def categories
46
64
  page_content.search('table.include_0 a b').map do |link|
47
- if match = link.parent.attributes["href"].value.match(%r{/view/(?<id>\d+)\?r=(?<r>\d+)})
48
- Category.new(@ex_ua,match[:id], parent: self, name: link.text)
65
+ if match = link.parent.attributes["href"].value.match(%r{/(?<url>\d+)\?r=(?<r>\d+)})
66
+ Category.new(@ex_ua, parent: self, url: match['url'], name: link.text)
49
67
  end
50
68
  end.compact
51
69
  end
@@ -61,45 +79,45 @@ module ExUA
61
79
  end
62
80
 
63
81
  # Next category
82
+ # @return [ExUA::Category]
64
83
  def next
65
- Category.new(@ex_ua, self.id, url: next_url)
84
+ raise NotFound, "No link to a next category found" unless next?
85
+ Category.new(@ex_ua, id: self.id, url: next_url)
66
86
  end
67
87
 
68
88
  # Previous category
89
+ # @return [ExUA::Category]
69
90
  def prev
70
- Category.new(@ex_ua, self.id, url: prev_url)
91
+ raise NotFound, "No link to a previous category found" unless prev?
92
+ Category.new(@ex_ua, id: self.id, url: prev_url)
71
93
  end
72
94
 
73
95
  # Current page number
96
+ # @return [Fixnum]
74
97
  def page
75
- CGI.parse(URI.parse(@url).query||"")["p"].first || 0
98
+ CGI.parse(URI.parse(@url).query||"")["p"].first.to_i || 0
76
99
  end
77
100
 
78
101
  # Download items
102
+ # @return [Array<ExUA::Item>]
79
103
  def items
80
104
  table_rows = page_content.search('table.list tr')
81
105
  table_rows.map do |tr|
82
106
  tr.search("a[title!='']")
83
107
  end.reject(&:empty?).map do |links|
84
- Item.new.tap do |item|
85
- links.each { |link|
86
- case link.attributes["href"].value
87
- when %r{^/get/}
88
- item.title = link.attributes["title"].value
89
- item.id = link.attributes["href"].value.match(%r{^/get/(\d+)})[1].to_i
90
- when %r{^/load}
91
- item.additional_servers||=[]
92
- item.additional_servers << link.attributes["title"].value.match(%r{fs(\d+)})[1].to_i
93
- end
94
- }
95
- end
108
+ Item.parse_links(links)
96
109
  end
97
110
  end
98
111
 
99
112
  protected
100
113
 
114
+ def strip_url(url)
115
+ return unless url
116
+ url.sub(ExUA::BASE_URL, '')
117
+ end
118
+
101
119
  def page_content
102
- @page_content||=@ex_ua.agent.get("#{ExUA::BASE_URL}#{@url}")
120
+ @page_content||=@ex_ua.get(url)
103
121
  end
104
122
 
105
123
  def url_from_id(id)
@@ -107,11 +125,17 @@ module ExUA
107
125
  end
108
126
 
109
127
  def next_url
110
- @next_url||=page_content.root.xpath("//link[@rel='next']/@href").first.tap{|a| a.value if a}
128
+ @next_url||=(
129
+ e = page_content.root.xpath("//link[@rel='next']/@href").first
130
+ e && e.value
131
+ )
111
132
  end
112
133
 
113
134
  def prev_url
114
- @prev_url||=page_content.root.xpath("//link[@rel='prev']/@href").first.tap{|a| a.value if a}
135
+ @prev_url||=(
136
+ e = page_content.root.xpath("//link[@rel='prev']/@href").first
137
+ e && e.value
138
+ )
115
139
  end
116
140
  end
117
141
  end
@@ -0,0 +1,30 @@
1
+ require 'httparty'
2
+ require 'nokogiri'
3
+
4
+ module ExUA
5
+ # Client for ExUA
6
+ # @example Usage
7
+ # client = ExUA::Client.new
8
+ # categories = client.base_categories('ru')
9
+ #
10
+ class Client
11
+ # List of available languages
12
+ # @return [Array<String>]
13
+ def available_languages
14
+ @available_langauges||=get('/').search('select[name=lang] option').inject({}){|acc,el| acc[el.attributes["value"].value]=el.text;acc}
15
+ end
16
+
17
+ # List of base categories for a given language
18
+ # @param[String] lang Language
19
+ # @example Usage
20
+ # client.base_categories('ru')
21
+ # @return [Array<ExUA::Category>]
22
+ def base_categories(lang)
23
+ ExUA::KNOWN_BASE_CATEGORIES.map{|cat| Category.new(self, url: "/#{lang}/#{cat}")}
24
+ end
25
+
26
+ def get(url)
27
+ Nokogiri.parse(HTTParty.get("#{ExUA::BASE_URL}#{url}").body)
28
+ end
29
+ end
30
+ end
data/lib/ex_ua/item.rb CHANGED
@@ -1,8 +1,24 @@
1
+ # @author Andrii Dmytrenko
1
2
  module ExUA
2
3
  # Download item
3
4
  class Item < Struct.new(:id, :title, :additional_servers)
5
+ def self.parse_links(links)
6
+ self.new.tap do |item|
7
+ links.each { |link|
8
+ case link.attributes["href"].value
9
+ when %r{^/get/}
10
+ item.title = link.attributes["title"].value
11
+ item.id = link.attributes["href"].value.match(%r{^/get/(\d+)})[1].to_i
12
+ when %r{^/load}
13
+ item.additional_servers||=[]
14
+ item.additional_servers << link.attributes["title"].value.match(%r{fs(\d+)})[1].to_i
15
+ end
16
+ }
17
+ end
18
+ end
4
19
  # Actual download url.
5
20
  # You can add ?fs_id=server_id param to download form #additional_servers
21
+ # @return[String] download_url
6
22
  def download_url
7
23
  "#{ExUA::BASE_URL}#{url}"
8
24
  end
data/lib/ex_ua/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module ExUa
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/lib/ex_ua.rb CHANGED
@@ -1,39 +1,10 @@
1
- module ExUA
2
- BASE_URL='http://ex.ua'
3
- end
1
+ # @author Andrii Dmytrenko
4
2
  require "ex_ua/version"
3
+ require 'ex_ua/client'
5
4
  require "ex_ua/item"
6
5
  require "ex_ua/category"
7
- require 'mechanize'
8
6
 
9
7
  module ExUA
10
- # Client for ExUA
11
- # @example Usage
12
- # client = ExUA::Client.new
13
- # categories = client.base_categories('ru')
14
- #
15
- class Client
16
- attr_reader :agent
17
-
18
- def initialize
19
- @agent = Mechanize.new
20
- end
21
-
22
- def inspect
23
- "#<#{self.class}>"
24
- end
25
-
26
- # List of available languages
27
- def available_languages
28
- @available_langauges||=@agent.get(BASE_URL).search('select[name=lang] option').inject({}){|acc,el| acc[el.attributes["value"].value]=el.text;acc}
29
- end
30
-
31
- # List of base categories for a given language
32
- # @param[String] lang Language
33
- # @example
34
- # client.base_categories('ru')
35
- def base_categories(lang)
36
- %w[video audio images texts games software].map{|cat| Category.new(self, nil, url: "/#{lang}/#{cat}")}
37
- end
38
- end
8
+ BASE_URL='http://www.ex.ua'
9
+ KNOWN_BASE_CATEGORIES = %w[video audio images texts games software]
39
10
  end
@@ -1,4 +1,41 @@
1
1
  require 'spec_helper'
2
2
  describe ExUA::Category do
3
- pending
4
- end
3
+ context "general 1 page category" do
4
+ subject{ExUA::Category.new(client, url: 'ru_video.html')}
5
+ describe '#categories' do
6
+ it 'returns list of child categories' do
7
+ subject.categories.should be_kind_of(Array)
8
+ end
9
+ it 'has current category as a parent category for all childs' do
10
+ subject.categories.all?{|c| c.parent == subject}.should be_true
11
+ end
12
+ end
13
+ its(:items){should_not be_nil}
14
+ its(:name){should eq("\u0412\u0438\u0434\u0435\u043E [RU - \u0440\u0443\u0441\u0441\u043A\u0438\u0439]")}
15
+ its(:description){should_not be_nil}
16
+ its(:canonical_url){should_not be_nil}
17
+ its(:next?){should be_false}
18
+ its(:prev?){should be_false}
19
+ end
20
+ context "general few pages category" do
21
+ subject{ExUA::Category.new(client, url: 'foreign_video_russia.html')}
22
+ describe '#next' do
23
+ it 'returns a category with same url, but different page number' do
24
+ subject.next.url.should eq('/ru/video/foreign?r=23775&p=1')
25
+ end
26
+ end
27
+ describe '#prev' do
28
+ it 'returns a category with same url, but different page number' do
29
+ pending 'find a page with prev'
30
+ expect(subject.prev.url).to eq('')
31
+ end
32
+ it 'raises error when no prev url found' do
33
+ expect{subject.prev}.to raise_error(ExUA::Category::NotFound)
34
+ end
35
+ end
36
+ end
37
+ context "item category" do
38
+ subject{ExUA::Category.new(client, url: 'video_test.html')}
39
+ its(:picture){should_not be_nil}
40
+ end
41
+ end
data/spec/client_spec.rb CHANGED
@@ -1,4 +1,17 @@
1
1
  require 'spec_helper'
2
2
  describe ExUA::Client do
3
- pending
4
- end
3
+ describe '#available_languages' do
4
+ it 'returns list of available languages' do
5
+ client.available_languages.should be_kind_of(Hash)
6
+ end
7
+ it 'includes known languages' do
8
+ known_languages = ["en", "ru", "uk"]
9
+ (client.available_languages.keys & known_languages).sort.should eq(known_languages)
10
+ end
11
+ end
12
+ describe '#base_categories' do
13
+ it 'lists base categories for a language' do
14
+ client.base_categories("uk").should be_kind_of(Array)
15
+ end
16
+ end
17
+ end