ex_ua 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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