apprank 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/LICENSE +19 -0
- data/README +0 -0
- data/lib/apprank/app.rb +56 -0
- data/lib/apprank/rank.rb +27 -0
- data/lib/apprank.rb +8 -0
- data/spec/app_spec.rb +30 -0
- data/spec/rank_spec.rb +17 -0
- data/spec/rcov.opts +1 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +137 -0
- metadata +77 -0
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (c) 2010 Hwan-Joon Choi
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README
ADDED
File without changes
|
data/lib/apprank/app.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
module Apprank
|
2
|
+
class App
|
3
|
+
|
4
|
+
attr_accessor :name, :icon_urls, :summary, :price, :rights, :display_name,
|
5
|
+
:preview, :link, :itunes_url, :developer, :category, :release_date
|
6
|
+
|
7
|
+
def initialize(hash)
|
8
|
+
@name = hash["im:name"]["label"]
|
9
|
+
@icon_urls = {}
|
10
|
+
hash["im:image"].each do |image|
|
11
|
+
height =
|
12
|
+
if image["attributes"]["height"] == '53'
|
13
|
+
:small
|
14
|
+
elsif image["attributes"]["height"] == '75'
|
15
|
+
:medium
|
16
|
+
else
|
17
|
+
:large
|
18
|
+
end
|
19
|
+
@icon_urls[height] = image["label"]
|
20
|
+
end
|
21
|
+
@summary = hash["summary"]["label"]
|
22
|
+
@price = {
|
23
|
+
:amount => hash["im:price"]["attributes"]["amount"].to_f,
|
24
|
+
:currency => hash["im:price"]["attributes"]["currency"]
|
25
|
+
}
|
26
|
+
@rights = hash["rights"]["label"]
|
27
|
+
@display_name = hash["title"]["label"]
|
28
|
+
hash["link"].each do |link|
|
29
|
+
if link["attributes"]["title"] == "Preview"
|
30
|
+
@preview = link["attributes"]["href"]
|
31
|
+
else
|
32
|
+
@link = link["attributes"]["href"]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
@itunes_url = hash["id"]["label"]
|
36
|
+
@developer = {
|
37
|
+
:name => hash["im:artist"]["label"],
|
38
|
+
:url => hash["im:artist"]["attributes"]["href"]
|
39
|
+
}
|
40
|
+
@category = {
|
41
|
+
:name => hash["category"]["attributes"]["term"],
|
42
|
+
:url => hash["category"]["attributes"]["scheme"]
|
43
|
+
}
|
44
|
+
@release_date = Time.parse(hash["im:releaseDate"]["label"])
|
45
|
+
end
|
46
|
+
|
47
|
+
def itunes_id
|
48
|
+
self.itunes_url.split(/\//).last.split(/\?/).first.gsub(/[^\d]/,'')
|
49
|
+
end
|
50
|
+
|
51
|
+
def is_free?
|
52
|
+
self.price[:amount].zero?
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
data/lib/apprank/rank.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'apprank/app'
|
2
|
+
|
3
|
+
module Apprank
|
4
|
+
class Rank
|
5
|
+
|
6
|
+
attr_accessor :apps, :link, :updated
|
7
|
+
|
8
|
+
def initialize(text)
|
9
|
+
begin
|
10
|
+
data = JSON.load(text)
|
11
|
+
apps_data = data["feed"]["entry"]
|
12
|
+
@link = data["feed"]["link"].last["attributes"]["href"]
|
13
|
+
@apps = apps_data.map do |app|
|
14
|
+
Apprank::App.new(app)
|
15
|
+
end
|
16
|
+
@updated = Time.parse(data["feed"]["updated"]["label"])
|
17
|
+
rescue
|
18
|
+
raise BadJsonData
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def country
|
23
|
+
self.link[/cc=(\w*)/][3..-1]
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
data/lib/apprank.rb
ADDED
data/spec/app_spec.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe App do
|
4
|
+
|
5
|
+
describe "when you load the data" do
|
6
|
+
it "should get data" do
|
7
|
+
|
8
|
+
app, expected, data = create_fake_app
|
9
|
+
|
10
|
+
app.name.should == expected[:name]
|
11
|
+
app.icon_urls.should == expected[:icon_urls]
|
12
|
+
app.summary.should == expected[:summary]
|
13
|
+
app.price.should == expected[:price]
|
14
|
+
app.rights.should == expected[:rights]
|
15
|
+
app.display_name.should == expected[:title]
|
16
|
+
app.link.should == expected[:link]
|
17
|
+
app.preview.should == expected[:preview]
|
18
|
+
app.itunes_url.should == expected[:itunes_url]
|
19
|
+
app.developer.should == expected[:developer]
|
20
|
+
app.category.should == expected[:category]
|
21
|
+
|
22
|
+
date_diff = app.release_date - expected[:release_date]
|
23
|
+
date_diff.abs.should <= 1
|
24
|
+
|
25
|
+
app.itunes_id.should == expected[:itunes_id]
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
data/spec/rank_spec.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Rank do
|
4
|
+
|
5
|
+
describe "when you load the data" do
|
6
|
+
it "should get data" do
|
7
|
+
|
8
|
+
feed = create_fake_feed(100)
|
9
|
+
rank = Rank.new({ :feed => feed }.to_json)
|
10
|
+
rank.apps.length.should == 100
|
11
|
+
rank.link.should == feed[:id][:href]
|
12
|
+
(rank.updated - Time.now).abs.should < 10
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/spec/rcov.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--exclude "spec/*"
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
require 'lib/apprank'
|
2
|
+
require 'faker'
|
3
|
+
|
4
|
+
include Apprank
|
5
|
+
|
6
|
+
def create_fake_app
|
7
|
+
itunes_id = rand(100000).to_s
|
8
|
+
expected = {
|
9
|
+
:name => Faker::Company.bs,
|
10
|
+
:icon_urls => {
|
11
|
+
:small => Faker::Internet.domain_name,
|
12
|
+
:medium => Faker::Internet.domain_name,
|
13
|
+
:large => Faker::Internet.domain_name
|
14
|
+
},
|
15
|
+
:summary => Faker::Company.catch_phrase,
|
16
|
+
:price => {
|
17
|
+
:amount => rand(1000),
|
18
|
+
:currency => Faker::Address.us_state_abbr,
|
19
|
+
},
|
20
|
+
:rights => Faker::Company.name,
|
21
|
+
:title => Faker::Company.bs + Faker::Company.name,
|
22
|
+
:link => Faker::Internet.domain_name,
|
23
|
+
:preview => Faker::Internet.domain_name,
|
24
|
+
:itunes_id => itunes_id,
|
25
|
+
:itunes_url => Faker::Internet.domain_name + '/id' + itunes_id + '?foo=bar',
|
26
|
+
:developer => {
|
27
|
+
:name => Faker::Company.name,
|
28
|
+
:url => Faker::Internet.domain_name
|
29
|
+
},
|
30
|
+
:category => {
|
31
|
+
:name => Faker::Name.last_name,
|
32
|
+
:url => Faker::Internet.domain_name
|
33
|
+
},
|
34
|
+
:release_date => Time.now
|
35
|
+
}
|
36
|
+
|
37
|
+
data = {
|
38
|
+
"im:name" => { "label" => expected[:name] },
|
39
|
+
"im:image" => [
|
40
|
+
{
|
41
|
+
"label" => expected[:icon_urls][:small],
|
42
|
+
"attributes" => { "height" => "53" }
|
43
|
+
},
|
44
|
+
{
|
45
|
+
"label" => expected[:icon_urls][:medium],
|
46
|
+
"attributes" => { "height" => "75" }
|
47
|
+
},
|
48
|
+
{
|
49
|
+
"label" => expected[:icon_urls][:large],
|
50
|
+
"attributes" => { "height" => "100" }
|
51
|
+
}
|
52
|
+
],
|
53
|
+
"summary" => { "label" => expected[:summary] },
|
54
|
+
"im:price" => {
|
55
|
+
"label" => "Free",
|
56
|
+
"attributes" => {
|
57
|
+
"amount" => expected[:price][:amount],
|
58
|
+
"currency" => expected[:price][:currency]
|
59
|
+
}
|
60
|
+
},
|
61
|
+
"im:contentType" => {
|
62
|
+
"attributes" => {
|
63
|
+
"term" => "Application",
|
64
|
+
"label" => "Application"
|
65
|
+
}
|
66
|
+
},
|
67
|
+
"rights" => { "label" => expected[:rights] },
|
68
|
+
"title" => { "label" => expected[:title] },
|
69
|
+
"link" => [
|
70
|
+
{
|
71
|
+
"attributes" => {
|
72
|
+
"rel" => "alternate",
|
73
|
+
"type" => "text/html",
|
74
|
+
"href" => expected[:link]
|
75
|
+
}
|
76
|
+
},
|
77
|
+
{
|
78
|
+
"im:duration" => { "label" => "0" },
|
79
|
+
"attributes" => {
|
80
|
+
"title" => "Preview",
|
81
|
+
"rel" => "enclosure",
|
82
|
+
"type" => "image/jpeg",
|
83
|
+
"href" => expected[:preview],
|
84
|
+
"im:assetType" => "preview"
|
85
|
+
}
|
86
|
+
}
|
87
|
+
],
|
88
|
+
"id" => { "label" => expected[:itunes_url] },
|
89
|
+
"im:artist" => {
|
90
|
+
"label" => expected[:developer][:name],
|
91
|
+
"attributes" => { "href" => expected[:developer][:url] }
|
92
|
+
},
|
93
|
+
"category" => {
|
94
|
+
"attributes" => {
|
95
|
+
"term" => expected[:category][:name],
|
96
|
+
"scheme" => expected[:category][:url],
|
97
|
+
"label" => expected[:category][:name]
|
98
|
+
}
|
99
|
+
},
|
100
|
+
"im:releaseDate" => {
|
101
|
+
"label" => expected[:release_date].strftime("%Y-%m-%dT%H:%M:%S%z"),
|
102
|
+
"attributes" => { "label" => "November 04, 2010" }
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
[App.new(data), expected, data]
|
107
|
+
end
|
108
|
+
|
109
|
+
def create_fake_feed(length=100)
|
110
|
+
{
|
111
|
+
:author => {
|
112
|
+
:name => { :label => Faker::Company.name },
|
113
|
+
:uri => { :label => Faker::Internet.domain_name }
|
114
|
+
},
|
115
|
+
:entry => length.times.map{ create_fake_app[2] },
|
116
|
+
:updated => { :label => Time.now },
|
117
|
+
:rights => { :label => Faker::Company.catch_phrase },
|
118
|
+
:title => { :label => Faker::Company.bs },
|
119
|
+
:icon => { :label => Faker::Internet.domain_name },
|
120
|
+
:link => [
|
121
|
+
{
|
122
|
+
:attributes => {
|
123
|
+
:rel => "alternate",
|
124
|
+
:type => "text/html",
|
125
|
+
:href => Faker::Internet.domain_name
|
126
|
+
}
|
127
|
+
},
|
128
|
+
{
|
129
|
+
:attributes => {
|
130
|
+
:rel => "self",
|
131
|
+
:href => Faker::Internet.domain_name + "?cc=us"
|
132
|
+
}
|
133
|
+
}
|
134
|
+
],
|
135
|
+
:id => { :label => Faker::Internet.domain_name + "?cc=us" }
|
136
|
+
}
|
137
|
+
end
|
metadata
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: apprank
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- hc5duke
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2010-12-25 00:00:00 -08:00
|
19
|
+
default_executable:
|
20
|
+
dependencies: []
|
21
|
+
|
22
|
+
description: Apprank parses iOS app rank data from Apple.
|
23
|
+
email: hc5duke@gmail.com
|
24
|
+
executables: []
|
25
|
+
|
26
|
+
extensions: []
|
27
|
+
|
28
|
+
extra_rdoc_files: []
|
29
|
+
|
30
|
+
files:
|
31
|
+
- Gemfile
|
32
|
+
- LICENSE
|
33
|
+
- README
|
34
|
+
- lib/apprank.rb
|
35
|
+
- lib/apprank/app.rb
|
36
|
+
- lib/apprank/rank.rb
|
37
|
+
- spec/app_spec.rb
|
38
|
+
- spec/rank_spec.rb
|
39
|
+
- spec/rcov.opts
|
40
|
+
- spec/spec.opts
|
41
|
+
- spec/spec_helper.rb
|
42
|
+
has_rdoc: true
|
43
|
+
homepage: https://www.github.com/hc5duke/apprank
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
hash: 3
|
66
|
+
segments:
|
67
|
+
- 0
|
68
|
+
version: "0"
|
69
|
+
requirements: []
|
70
|
+
|
71
|
+
rubyforge_project:
|
72
|
+
rubygems_version: 1.3.7
|
73
|
+
signing_key:
|
74
|
+
specification_version: 3
|
75
|
+
summary: Take app rank data from Apple and rubyfy it
|
76
|
+
test_files: []
|
77
|
+
|