apple_epf 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.md +90 -0
  3. data/Rakefile +35 -0
  4. data/lib/apple_epf.rb +43 -0
  5. data/lib/apple_epf/downloader.rb +164 -0
  6. data/lib/apple_epf/errors.rb +8 -0
  7. data/lib/apple_epf/extractor.rb +43 -0
  8. data/lib/apple_epf/logging.rb +32 -0
  9. data/lib/apple_epf/main.rb +113 -0
  10. data/lib/apple_epf/parser.rb +95 -0
  11. data/lib/apple_epf/version.rb +3 -0
  12. data/lib/core_ext/array.rb +30 -0
  13. data/lib/core_ext/module.rb +63 -0
  14. data/lib/tasks/apple_epf_tasks.rake +4 -0
  15. data/spec/lib/apple_epf/downloader_spec.rb +220 -0
  16. data/spec/lib/apple_epf/exctractor_spec.rb +72 -0
  17. data/spec/lib/apple_epf/main_spec.rb +185 -0
  18. data/spec/lib/apple_epf/parser_spec.rb +66 -0
  19. data/spec/spec_helper.rb +40 -0
  20. data/spec/support/fixture_helper.rb +13 -0
  21. data/spec/support/fixtures/itunes/epf/current_full_list.html +20 -0
  22. data/spec/support/fixtures/itunes/epf/current_inc_list.html +19 -0
  23. data/spec/support/fixtures/itunes/epf/incremental/itunes20130111.tbz +0 -0
  24. data/spec/support/fixtures/itunes/epf/incremental/itunes20130111/application +21 -0
  25. data/spec/support/fixtures/itunes/epf/incremental/itunes20130111/application_with_nil +7 -0
  26. data/spec/support/fixtures/itunes/epf/incremental/itunes20130111/test_file.txt +0 -0
  27. data/spec/support/fixtures/itunes/epf/incremental/popularity20130111.tbz +0 -0
  28. data/spec/support/fixtures/itunes/epf/incremental/popularity20130111/popularity1 +0 -0
  29. data/spec/support/fixtures/itunes/epf/incremental/popularity20130111/popularity2 +0 -0
  30. metadata +255 -0
@@ -0,0 +1,185 @@
1
+ # encoding: UTF-8
2
+ require File.expand_path('../../../spec_helper', __FILE__)
3
+
4
+ describe AppleEpf::Main do
5
+ let(:filedate) { Date.parse('17-01-2013') }
6
+ let(:file_entry_double) { double('FileEntry', tbz_file: 'tbz_file') }
7
+ let(:file_basename) { 'itunes20130111.tbz' }
8
+
9
+ before do
10
+ @tmp_dir = [Dir.tmpdir, 'epm_files'].join('/')
11
+ FileUtils.mkpath @tmp_dir
12
+
13
+ AppleEpf.configure do |config|
14
+ config.apple_id = 'test'
15
+ config.apple_password = 'test'
16
+ config.extract_dir = @tmp_dir
17
+ config.files_matrix = {popularity: ['application_popularity_per_genre']}.freeze
18
+ end
19
+ end
20
+
21
+ describe "initialize" do
22
+ it "should set attributes" do
23
+ custom_dir = [Dir.tmpdir, 'epm_files_custom'].join('/')
24
+ manager = AppleEpf::Incremental.new(filedate, nil, custom_dir)
25
+
26
+ manager.store_dir.should == custom_dir
27
+ manager.filedate.to_s.should == Date.parse('17-01-2013').to_s
28
+ manager.store_dir.should == custom_dir
29
+ manager.files_matrix.should == {popularity: ['application_popularity_per_genre']}
30
+
31
+ manager = AppleEpf::Incremental.new(filedate, {test: ['itworks']})
32
+ manager.files_matrix.should == {test: ['itworks']}
33
+
34
+ end
35
+ end
36
+
37
+ describe "#download_all_files" do
38
+ before do
39
+ files_matrix = {one: ['test1', 'test2'], two: ['test3', 'test4']}
40
+ @manager = AppleEpf::Incremental.new(filedate, files_matrix)
41
+
42
+ @downloder_double1 = double('Downloader', download: true, download_to: 'somepath')
43
+ @downloder_double2 = double('Downloader', download: true, download_to: 'somepath2')
44
+
45
+ AppleEpf::Downloader.should_receive(:new).with('incremental', 'one', filedate).and_return(@downloder_double1)
46
+ AppleEpf::Downloader.should_receive(:new).with('incremental', 'two', filedate).and_return(@downloder_double2)
47
+ end
48
+
49
+ it "should download all files and return array with donwloaded files" do
50
+ @manager.download_all_files.should == [@downloder_double1, @downloder_double2]
51
+ end
52
+
53
+ it "should send to block if block given" do
54
+ expect { |b|
55
+ @manager.download_all_files(&b)
56
+ }.to yield_successive_args(*[@downloder_double1, @downloder_double2])
57
+ end
58
+ end
59
+
60
+ describe "#download_and_extract_all_files" do
61
+ before do
62
+ @itunes_download_to = "#{@tmp_dir}/itunes20130111.tbz"
63
+ FileUtils.copy_file(apple_epf_inc_filename('itunes20130111.tbz'), @itunes_download_to)
64
+
65
+ @popularity_download_to = "#{@tmp_dir}/popularity20130111.tbz"
66
+ FileUtils.copy_file(apple_epf_inc_filename('popularity20130111.tbz'), @popularity_download_to)
67
+
68
+ itunes_downloder_double = double('Downloader', download: true, download_to: @itunes_download_to)
69
+ popularity_downloder_double = double('Downloader', download: true, download_to: @popularity_download_to)
70
+
71
+ @file_matrix = {
72
+ itunes: ['application', 'test_file.txt'],
73
+ popularity: ['popularity1', 'popularity2'],
74
+ }
75
+
76
+ @manager = AppleEpf::Incremental.new(filedate, @file_matrix)
77
+
78
+ AppleEpf::Downloader.should_receive(:new)
79
+ .with('incremental', 'itunes', filedate).and_return(itunes_downloder_double)
80
+
81
+ AppleEpf::Downloader.should_receive(:new)
82
+ .with('incremental', 'popularity', filedate).and_return(popularity_downloder_double)
83
+
84
+ @itunes_expected_extracted = ['application', 'test_file.txt'].map do |f|
85
+ File.join(@tmp_dir, 'itunes20130111', f)
86
+ end
87
+
88
+ @popularity_expected_extracted = ['popularity1', 'popularity2'].map do |f|
89
+ File.join(@tmp_dir, 'popularity20130111', f)
90
+ end
91
+ end
92
+
93
+ it "should download all files and return array with donwloaded files" do
94
+ result = @manager.download_and_extract_all_files
95
+ result.map(&:extracted_files).should == [
96
+ Hash[['application', 'test_file.txt'].zip(@itunes_expected_extracted)],
97
+ Hash[['popularity1', 'popularity2'].zip(@popularity_expected_extracted)]
98
+ ]
99
+ end
100
+
101
+ it "should send to block if block given" do
102
+ expect { |b|
103
+ @manager.download_and_extract_all_files(&b)
104
+ }.to yield_successive_args(AppleEpf::Extractor::FileEntry, AppleEpf::Extractor::FileEntry)
105
+ end
106
+ end
107
+
108
+ describe "#download_and_extract" do
109
+ it "should return extracted files" do
110
+ @download_to = "#{@tmp_dir}/#{file_basename}"
111
+ FileUtils.copy_file(apple_epf_inc_filename(file_basename), @download_to)
112
+
113
+ downloder_double = double('Downloader', download: true, download_to: @download_to)
114
+
115
+ manager = AppleEpf::Incremental.new(filedate)
116
+ AppleEpf::Downloader.should_receive(:new).and_return(downloder_double)
117
+
118
+ result = manager.download_and_extract('itunes', ['application', 'test_file.txt'])
119
+ expected_extracted = ['application', 'test_file.txt'].map do |f|
120
+ File.join(@tmp_dir, 'itunes20130111', f)
121
+ end
122
+
123
+ result.extracted_files.should == Hash[['application', 'test_file.txt'].zip(expected_extracted)]
124
+ end
125
+ end
126
+
127
+ describe "#download" do
128
+ it "should download file and return path to downloaded file" do
129
+ manager = AppleEpf::Incremental.new(filedate)
130
+
131
+ downloder_double1 = double('Downloader', download: true, download_to: 'somepath')
132
+
133
+ AppleEpf::Downloader.should_receive(:new).with('incremental', 'one', filedate).and_return(downloder_double1)
134
+
135
+ manager.download('one').download_to.should == 'somepath'
136
+ end
137
+
138
+ end
139
+
140
+ describe "#extract" do
141
+ it "should extract and return file entry" do
142
+ file = Tempfile.new('foo.tbz')
143
+ extractor_double = double('Ectractor', file_entry: file_entry_double).as_null_object
144
+
145
+ manager = AppleEpf::Incremental.new(filedate)
146
+ AppleEpf::Extractor.should_receive(:new).with(file, ['extractable1']).and_return(extractor_double)
147
+
148
+ manager.extract(file, ['extractable1']).should == file_entry_double
149
+
150
+ end
151
+ end
152
+
153
+
154
+ describe ".get_current_list" do
155
+ context 'Full' do
156
+ let(:filename) { apple_epf_filename('current_full_list.html') }
157
+
158
+ it "should return hash of avaliable files" do
159
+ stub_request(:get, "http://test:test@feeds.itunes.apple.com/feeds/epf/v3/full/current").
160
+ to_return(:status => 200, :body => File.read(filename), :headers => {})
161
+
162
+ list = {
163
+ 'itunes' => '20130130',
164
+ 'match' => '20130130',
165
+ 'popularity' => '20130130',
166
+ 'pricing' => '20130130'
167
+ }
168
+ AppleEpf::Full.get_current_list.should == list
169
+ end
170
+
171
+ end
172
+
173
+ context "Incremental" do
174
+ let(:filename) { apple_epf_filename('current_inc_list.html') }
175
+
176
+ it "should return hash of avaliable files" do
177
+ stub_request(:get, "http://test:test@feeds.itunes.apple.com/feeds/epf/v3/full/current/incremental/current").
178
+ to_return(:status => 200, :body => File.read(filename), :headers => {})
179
+
180
+ list = {"itunes"=>"20130205", "match"=>"20130205", "popularity"=>"20130205", "pricing"=>"20130205"}
181
+ AppleEpf::Incremental.get_current_list.should == list
182
+ end
183
+ end
184
+ end
185
+ end
@@ -0,0 +1,66 @@
1
+ # encoding: UTF-8
2
+ require File.expand_path('../../../spec_helper', __FILE__)
3
+
4
+ describe AppleEpf::Parser do
5
+ let(:header_block) {Proc.new{|b|}}
6
+ let(:row_block) {Proc.new{|b|}}
7
+ let(:filename) { apple_epf_inc_filename('itunes20130111/application') }
8
+
9
+ let(:parser) {AppleEpf::Parser.new(filename)}
10
+
11
+ describe "perform" do
12
+
13
+ describe "#parse_metadata" do
14
+
15
+ it "should properly parse header" do
16
+ _header_info = {:file=> "application",
17
+ :columns=>["export_date", "application_id", "title",
18
+ "recommended_age", "artist_name", "seller_name",
19
+ "company_url", "support_url", "view_url",
20
+ "artwork_url_large", "artwork_url_small",
21
+ "itunes_release_date", "copyright",
22
+ "description", "version", "itunes_version",
23
+ "download_size"],
24
+ :primary_keys=>["application_id"],
25
+ :db_types=>["BIGINT", "INTEGER", "VARCHAR(1000)", "VARCHAR(20)",
26
+ "VARCHAR(1000)", "VARCHAR(1000)", "VARCHAR(1000)",
27
+ "VARCHAR(1000)", "VARCHAR(1000)", "VARCHAR(1000)",
28
+ "VARCHAR(1000)", "DATETIME", "VARCHAR(4000)",
29
+ "LONGTEXT", "VARCHAR(100)", "VARCHAR(100)", "BIGINT"],
30
+ :export_type=>["INCREMENTAL"]}
31
+
32
+ _footer_info = {:records=>"2"}
33
+
34
+ parser.parse_metadata.should eq(_header_info.merge(_footer_info))
35
+ end
36
+
37
+ it "should properly parse footer" do
38
+ _footer_info = {:records=>"2"}
39
+ parser.parse_metadata
40
+ parser.footer_info.should eq(_footer_info)
41
+ end
42
+ end
43
+
44
+ describe "#process_rows" do
45
+ it "should properly parse body" do
46
+ first_entry = ["1111111111", "1111111111", "1111111111", "4+", "1111111111", "1111111111", "", "http://static.f1111111111.com/support", "http://itunes.apple.cdcdcd/app/1111111111/id1111111111uo=5", "http://a3.mzstatic.com/us/r1000/112/Purple/v4/cdcdcd/e0/e8/1111111111-2398-c014-2aae-8aefc7cd0f1c/mzl.hbggcdah.100x100-75.jpg", "http://a3.dccdcd.com/us/r1000/116/Purple/v4/66/ea/39/1111111111-c19f-4f01-475e-71fbd2d864a1/Icdcdcdon.png", "2012 03 06", "© Freedomeat, Inc.", "1111111111", "2.1.0", "11111111110", "1111111111"]
47
+ second_entry = ["1111111111", "41111111111", "Sp1111111111free", "4+", "L1111111111a", "L1111111111va", "http://www.s1111111111q.pl", "http://www.1111111111.pl", "http://itunes.apple.com/app/1111111111-1111111111-free/id1111111111?uo=5", "http://a2.mzstatic.com/us/r1000/071/Purple/v4/d4/68/01/d1111111111f9ba-ba6c-43c306364299/temp..bsoykdqd.100x100-75.jpg", "http://a3.mzstatic.com/us/r1000/1111111111e3/0f/71e30f60-142f-5f03-3558-1c8a0c383e42/Icon.png", "2011 03 14", "© Linnova", "Sprawdź 1111111111\nRazem - ponad 650 słów i fraz tj. ponad 1000 profesjonalnych nagrań dźwi1111111111\n1111111111\n\n*More on www1111111111us", "2.1.3", "1273444446", "21444440"]
48
+ third_entry = ["134444270", "5411111111111", "Wh1111111111iz", "4+", "App1111111111td", "App1111111111d", "", "http://appe1111111111t.com", "http://itunes.apple.com/app/what1111111111id5111111111131?uo=5", "http://a5.mzstatic.com/us/r1000/101/Purple/v4/bd/39/44/bd39449d11111111111e8-4de4083899e0/mzm.kuywoxgn.100x100-75.jpg", "http://a1.mzstatic.com/us1111111111/v4/95/2c/75/952c7576-6196-11a7-42be-9f3822e9d084/icon.png", "2011111111119", "© Apperleft Ltd", "\n- Original exciting themes and levels\n- Test your knowledge\n- Use Bombs to narrow the letters selection\n- Challenging Themes and Levels\n\n- Compatible with all devices iPod/iPhone/iPad/New iPad\n- Free update keep coming\n!", "1.4", "14111111111139", "1411111111115"]
49
+
50
+ expect { |b|
51
+ parser.process_rows(&b)
52
+ }.to yield_successive_args(*[first_entry, second_entry, third_entry])
53
+ end
54
+
55
+ it "should return nil for blank data" do
56
+ first_entry = ["1111111111", "1111111111", "1111111111", "4+", "1111111111", "1111111111", "", "http://static.f1111111111.com/support", "http://itunes.apple.cdcdcd/app/1111111111/id1111111111uo=5", "http://a3.mzstatic.com/us/r1000/112/Purple/v4/cdcdcd/e0/e8/1111111111-2398-c014-2aae-8aefc7cd0f1c/mzl.hbggcdah.100x100-75.jpg", "http://a3.dccdcd.com/us/r1000/116/Purple/v4/66/ea/39/1111111111-c19f-4f01-475e-71fbd2d864a1/Icdcdcdon.png", "2012 03 06", "© Freedomeat, Inc.", "1111111111", "2.1.0", "11111111110", '']
57
+ parser = AppleEpf::Parser.new(apple_epf_inc_filename('itunes20130111/application_with_nil'))
58
+ expect { |b|
59
+ parser.process_rows(&b)
60
+ }.to yield_successive_args(*[first_entry])
61
+ end
62
+ end
63
+
64
+
65
+ end
66
+ end
@@ -0,0 +1,40 @@
1
+ $LOAD_PATH << "." unless $LOAD_PATH.include?(".")
2
+ require 'logger'
3
+ require 'tempfile'
4
+
5
+ begin
6
+ require "rubygems"
7
+ require "bundler"
8
+
9
+ if Gem::Version.new(Bundler::VERSION) <= Gem::Version.new("0.9.5")
10
+ raise RuntimeError, "Your bundler version is too old." +
11
+ "Run `gem install bundler` to upgrade."
12
+ end
13
+
14
+ # Set up load paths for all bundled gems
15
+ Bundler.setup
16
+ rescue Bundler::GemNotFound
17
+ raise RuntimeError, "Bundler couldn't find some gems." +
18
+ "Did you run \`bundle install\`?"
19
+ end
20
+
21
+ Bundler.require
22
+
23
+ require 'webmock/rspec'
24
+ require 'timecop'
25
+
26
+ RSpec.configure do |config|
27
+ config.before(:each) do
28
+ AppleEpf.configure do |c|
29
+ c.log_to_console = true
30
+ end
31
+
32
+ WebMock.disable_net_connect!
33
+ end
34
+ config.filter_run :wip => true
35
+ config.run_all_when_everything_filtered = true
36
+ config.treat_symbols_as_metadata_keys_with_true_values = true
37
+ end
38
+
39
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
40
+
@@ -0,0 +1,13 @@
1
+ module FixtureHelper
2
+ def apple_epf_inc_filename(filename)
3
+ File.expand_path("../../support/fixtures/itunes/epf/incremental/#{filename}", __FILE__)
4
+ end
5
+
6
+ def apple_epf_filename(filename)
7
+ File.expand_path("../../support/fixtures/itunes/epf/#{filename}", __FILE__)
8
+ end
9
+ end
10
+
11
+ RSpec.configure do |config|
12
+ config.include FixtureHelper
13
+ end
@@ -0,0 +1,20 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
2
+ <html>
3
+ <head>
4
+ <title>Index of /feeds/epf/v3/full/current</title>
5
+ </head>
6
+ <body>
7
+ <h1>Index of /feeds/epf/v3/full/current</h1>
8
+ <table><tr><th><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr><tr><th colspan="5"><hr></th></tr>
9
+ <tr><td valign="top"><img src="/icons/folder.gif" alt="[DIR]"></td><td><a href="incremental/">incremental/</a> </td><td align="right">05-Feb-2013 07:39 </td><td align="right"> - </td><td>&nbsp;</td></tr>
10
+ <tr><td valign="top"><img src="/icons/compressed.gif" alt="[ ]"></td><td><a href="itunes20130130.tbz">itunes20130130.tbz</a> </td><td align="right">31-Jan-2013 12:08 </td><td align="right">4.5G</td><td>&nbsp;</td></tr>
11
+ <tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="itunes20130130.tbz.md5">itunes20130130.tbz.md5</a> </td><td align="right">31-Jan-2013 12:09 </td><td align="right"> 60 </td><td>&nbsp;</td></tr>
12
+ <tr><td valign="top"><img src="/icons/compressed.gif" alt="[ ]"></td><td><a href="match20130130.tbz">match20130130.tbz</a> </td><td align="right">31-Jan-2013 12:13 </td><td align="right">296M</td><td>&nbsp;</td></tr>
13
+ <tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="match20130130.tbz.md5">match20130130.tbz.md5</a> </td><td align="right">31-Jan-2013 12:13 </td><td align="right"> 59 </td><td>&nbsp;</td></tr>
14
+ <tr><td valign="top"><img src="/icons/compressed.gif" alt="[ ]"></td><td><a href="popularity20130130.tbz">popularity20130130.tbz</a> </td><td align="right">31-Jan-2013 12:14 </td><td align="right"> 41M</td><td>&nbsp;</td></tr>
15
+ <tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="popularity20130130.tbz.md5">popularity20130130.t..&gt;</a></td><td align="right">31-Jan-2013 12:14 </td><td align="right"> 64 </td><td>&nbsp;</td></tr>
16
+ <tr><td valign="top"><img src="/icons/compressed.gif" alt="[ ]"></td><td><a href="pricing20130130.tbz">pricing20130130.tbz</a> </td><td align="right">31-Jan-2013 11:03 </td><td align="right"> 10G</td><td>&nbsp;</td></tr>
17
+ <tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="pricing20130130.tbz.md5">pricing20130130.tbz.md5</a></td><td align="right">31-Jan-2013 11:04 </td><td align="right"> 61 </td><td>&nbsp;</td></tr>
18
+ <tr><th colspan="5"><hr></th></tr>
19
+ </table>
20
+ </body></html>
@@ -0,0 +1,19 @@
1
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
2
+ <html>
3
+ <head>
4
+ <title>Index of /feeds/epf/v3/full/current/incremental/current</title>
5
+ </head>
6
+ <body>
7
+ <h1>Index of /feeds/epf/v3/full/current/incremental/current</h1>
8
+ <table><tr><th><img src="/icons/blank.gif" alt="[ICO]"></th><th><a href="?C=N;O=D">Name</a></th><th><a href="?C=M;O=A">Last modified</a></th><th><a href="?C=S;O=A">Size</a></th><th><a href="?C=D;O=A">Description</a></th></tr><tr><th colspan="5"><hr></th></tr>
9
+ <tr><td valign="top"><img src="/icons/compressed.gif" alt="[ ]"></td><td><a href="itunes20130205.tbz">itunes20130205.tbz</a> </td><td align="right">05-Feb-2013 07:39 </td><td align="right">1.3G</td><td>&nbsp;</td></tr>
10
+ <tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="itunes20130205.tbz.md5">itunes20130205.tbz.md5</a> </td><td align="right">05-Feb-2013 07:39 </td><td align="right"> 60 </td><td>&nbsp;</td></tr>
11
+ <tr><td valign="top"><img src="/icons/compressed.gif" alt="[ ]"></td><td><a href="match20130205.tbz">match20130205.tbz</a> </td><td align="right">05-Feb-2013 05:47 </td><td align="right"> 65M</td><td>&nbsp;</td></tr>
12
+ <tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="match20130205.tbz.md5">match20130205.tbz.md5</a> </td><td align="right">05-Feb-2013 05:47 </td><td align="right"> 59 </td><td>&nbsp;</td></tr>
13
+ <tr><td valign="top"><img src="/icons/compressed.gif" alt="[ ]"></td><td><a href="popularity20130205.tbz">popularity20130205.tbz</a> </td><td align="right">05-Feb-2013 07:23 </td><td align="right"> 41M</td><td>&nbsp;</td></tr>
14
+ <tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="popularity20130205.tbz.md5">popularity20130205.t..&gt;</a></td><td align="right">05-Feb-2013 07:23 </td><td align="right"> 64 </td><td>&nbsp;</td></tr>
15
+ <tr><td valign="top"><img src="/icons/compressed.gif" alt="[ ]"></td><td><a href="pricing20130205.tbz">pricing20130205.tbz</a> </td><td align="right">05-Feb-2013 07:22 </td><td align="right">1.6G</td><td>&nbsp;</td></tr>
16
+ <tr><td valign="top"><img src="/icons/unknown.gif" alt="[ ]"></td><td><a href="pricing20130205.tbz.md5">pricing20130205.tbz.md5</a></td><td align="right">05-Feb-2013 07:22 </td><td align="right"> 61 </td><td>&nbsp;</td></tr>
17
+ <tr><th colspan="5"><hr></th></tr>
18
+ </table>
19
+ </body></html>
@@ -0,0 +1,21 @@
1
+ #export_dateapplication_idtitlerecommended_ageartist_nameseller_namecompany_urlsupport_urlview_urlartwork_url_largeartwork_url_smallitunes_release_datecopyrightdescriptionversionitunes_versiondownload_size
2
+ #primaryKey:application_id
3
+ #dbTypes:BIGINTINTEGERVARCHAR(1000)VARCHAR(20)VARCHAR(1000)VARCHAR(1000)VARCHAR(1000)VARCHAR(1000)VARCHAR(1000)VARCHAR(1000)VARCHAR(1000)DATETIMEVARCHAR(4000)LONGTEXTVARCHAR(100)VARCHAR(100)BIGINT
4
+ #exportMode:INCREMENTAL
5
+ ##legal: Legal Info
6
+ 1111111111111111111111111111114+11111111111111111111http://static.f1111111111.com/supporthttp://itunes.apple.cdcdcd/app/1111111111/id1111111111uo=5http://a3.mzstatic.com/us/r1000/112/Purple/v4/cdcdcd/e0/e8/1111111111-2398-c014-2aae-8aefc7cd0f1c/mzl.hbggcdah.100x100-75.jpghttp://a3.dccdcd.com/us/r1000/116/Purple/v4/66/ea/39/1111111111-c19f-4f01-475e-71fbd2d864a1/Icdcdcdon.png2012 03 06© Freedomeat, Inc.11111111112.1.0111111111101111111111
7
+ 111111111141111111111Sp1111111111free4+L1111111111aL1111111111vahttp://www.s1111111111q.plhttp://www.1111111111.plhttp://itunes.apple.com/app/1111111111-1111111111-free/id1111111111?uo=5http://a2.mzstatic.com/us/r1000/071/Purple/v4/d4/68/01/d1111111111f9ba-ba6c-43c306364299/temp..bsoykdqd.100x100-75.jpghttp://a3.mzstatic.com/us/r1000/1111111111e3/0f/71e30f60-142f-5f03-3558-1c8a0c383e42/Icon.png2011 03 14© LinnovaSprawdź 1111111111
8
+ Razem - ponad 650 słów i fraz tj. ponad 1000 profesjonalnych nagrań dźwi1111111111
9
+ 1111111111
10
+
11
+ *More on www1111111111us2.1.3127344444621444440
12
+ 1344442705411111111111Wh1111111111iz4+App1111111111tdApp1111111111dhttp://appe1111111111t.comhttp://itunes.apple.com/app/what1111111111id5111111111131?uo=5http://a5.mzstatic.com/us/r1000/101/Purple/v4/bd/39/44/bd39449d11111111111e8-4de4083899e0/mzm.kuywoxgn.100x100-75.jpghttp://a1.mzstatic.com/us1111111111/v4/95/2c/75/952c7576-6196-11a7-42be-9f3822e9d084/icon.png2011111111119© Apperleft Ltd
13
+ - Original exciting themes and levels
14
+ - Test your knowledge
15
+ - Use Bombs to narrow the letters selection
16
+ - Challenging Themes and Levels
17
+
18
+ - Compatible with all devices iPod/iPhone/iPad/New iPad
19
+ - Free update keep coming
20
+ !1.4141111111111391411111111115
21
+ #recordsWritten:2
@@ -0,0 +1,7 @@
1
+ #export_dateapplication_idtitlerecommended_ageartist_nameseller_namecompany_urlsupport_urlview_urlartwork_url_largeartwork_url_smallitunes_release_datecopyrightdescriptionversionitunes_versiondownload_size
2
+ #primaryKey:application_id
3
+ #dbTypes:BIGINTINTEGERVARCHAR(1000)VARCHAR(20)VARCHAR(1000)VARCHAR(1000)VARCHAR(1000)VARCHAR(1000)VARCHAR(1000)VARCHAR(1000)VARCHAR(1000)DATETIMEVARCHAR(4000)LONGTEXTVARCHAR(100)VARCHAR(100)BIGINT
4
+ #exportMode:INCREMENTAL
5
+ ##legal: Legal Info
6
+ 1111111111111111111111111111114+11111111111111111111http://static.f1111111111.com/supporthttp://itunes.apple.cdcdcd/app/1111111111/id1111111111uo=5http://a3.mzstatic.com/us/r1000/112/Purple/v4/cdcdcd/e0/e8/1111111111-2398-c014-2aae-8aefc7cd0f1c/mzl.hbggcdah.100x100-75.jpghttp://a3.dccdcd.com/us/r1000/116/Purple/v4/66/ea/39/1111111111-c19f-4f01-475e-71fbd2d864a1/Icdcdcdon.png2012 03 06© Freedomeat, Inc.11111111112.1.011111111110
7
+ #recordsWritten:1
metadata ADDED
@@ -0,0 +1,255 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: apple_epf
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Artem Kramarenko
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-02-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.12'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '2.12'
30
+ - !ruby/object:Gem::Dependency
31
+ name: rails
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 3.2.3
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 3.2.3
46
+ - !ruby/object:Gem::Dependency
47
+ name: guard
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: guard-rspec
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: rb-fsevent
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 0.9.1
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 0.9.1
94
+ - !ruby/object:Gem::Dependency
95
+ name: webmock
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: timecop
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: curb
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :runtime
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: chronic
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ~>
148
+ - !ruby/object:Gem::Version
149
+ version: 0.9.0
150
+ type: :runtime
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ~>
156
+ - !ruby/object:Gem::Version
157
+ version: 0.9.0
158
+ - !ruby/object:Gem::Dependency
159
+ name: nokogiri
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ~>
164
+ - !ruby/object:Gem::Version
165
+ version: 1.5.6
166
+ type: :runtime
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ~>
172
+ - !ruby/object:Gem::Version
173
+ version: 1.5.6
174
+ description: Downloader, Extractor and Parser for Apple Epf Affiliate files
175
+ email:
176
+ - me@artemk.name
177
+ executables: []
178
+ extensions: []
179
+ extra_rdoc_files: []
180
+ files:
181
+ - lib/apple_epf/downloader.rb
182
+ - lib/apple_epf/errors.rb
183
+ - lib/apple_epf/extractor.rb
184
+ - lib/apple_epf/logging.rb
185
+ - lib/apple_epf/main.rb
186
+ - lib/apple_epf/parser.rb
187
+ - lib/apple_epf/version.rb
188
+ - lib/apple_epf.rb
189
+ - lib/core_ext/array.rb
190
+ - lib/core_ext/module.rb
191
+ - lib/tasks/apple_epf_tasks.rake
192
+ - MIT-LICENSE
193
+ - Rakefile
194
+ - README.md
195
+ - spec/lib/apple_epf/downloader_spec.rb
196
+ - spec/lib/apple_epf/exctractor_spec.rb
197
+ - spec/lib/apple_epf/main_spec.rb
198
+ - spec/lib/apple_epf/parser_spec.rb
199
+ - spec/spec_helper.rb
200
+ - spec/support/fixture_helper.rb
201
+ - spec/support/fixtures/itunes/epf/current_full_list.html
202
+ - spec/support/fixtures/itunes/epf/current_inc_list.html
203
+ - spec/support/fixtures/itunes/epf/incremental/itunes20130111.tbz
204
+ - spec/support/fixtures/itunes/epf/incremental/itunes20130111/application
205
+ - spec/support/fixtures/itunes/epf/incremental/itunes20130111/application_with_nil
206
+ - spec/support/fixtures/itunes/epf/incremental/itunes20130111/test_file.txt
207
+ - spec/support/fixtures/itunes/epf/incremental/popularity20130111.tbz
208
+ - spec/support/fixtures/itunes/epf/incremental/popularity20130111/popularity1
209
+ - spec/support/fixtures/itunes/epf/incremental/popularity20130111/popularity2
210
+ homepage:
211
+ licenses: []
212
+ post_install_message:
213
+ rdoc_options: []
214
+ require_paths:
215
+ - lib
216
+ required_ruby_version: !ruby/object:Gem::Requirement
217
+ none: false
218
+ requirements:
219
+ - - ! '>='
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ segments:
223
+ - 0
224
+ hash: 742301200685018392
225
+ required_rubygems_version: !ruby/object:Gem::Requirement
226
+ none: false
227
+ requirements:
228
+ - - ! '>='
229
+ - !ruby/object:Gem::Version
230
+ version: '0'
231
+ segments:
232
+ - 0
233
+ hash: 742301200685018392
234
+ requirements: []
235
+ rubyforge_project:
236
+ rubygems_version: 1.8.23
237
+ signing_key:
238
+ specification_version: 3
239
+ summary: Downloader, Extractor and Parser for Apple Epf Affiliate files
240
+ test_files:
241
+ - spec/lib/apple_epf/downloader_spec.rb
242
+ - spec/lib/apple_epf/exctractor_spec.rb
243
+ - spec/lib/apple_epf/main_spec.rb
244
+ - spec/lib/apple_epf/parser_spec.rb
245
+ - spec/spec_helper.rb
246
+ - spec/support/fixture_helper.rb
247
+ - spec/support/fixtures/itunes/epf/current_full_list.html
248
+ - spec/support/fixtures/itunes/epf/current_inc_list.html
249
+ - spec/support/fixtures/itunes/epf/incremental/itunes20130111.tbz
250
+ - spec/support/fixtures/itunes/epf/incremental/itunes20130111/application
251
+ - spec/support/fixtures/itunes/epf/incremental/itunes20130111/application_with_nil
252
+ - spec/support/fixtures/itunes/epf/incremental/itunes20130111/test_file.txt
253
+ - spec/support/fixtures/itunes/epf/incremental/popularity20130111.tbz
254
+ - spec/support/fixtures/itunes/epf/incremental/popularity20130111/popularity1
255
+ - spec/support/fixtures/itunes/epf/incremental/popularity20130111/popularity2