itunes_transporter_generator 0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,169 @@
1
+ # itunes_transporter_generator
2
+ **CLI for generating and packaging app store assets for Game Center and In-App Purchases**
3
+
4
+ Apple recently released their Transporter app (http://bit.ly/UcEhAh) which is a handy way to manage your App Store Packages (.itmsp) instead of having to input achievements, leaderboards, and in-app purchases through iTunes Connect. Unfortunately, there isn't an easy way to generate these packages. Why write XML by hand and deal with the hassle of calculating MD5 and file sizes? Why not define your Game Center and In-App Purchases in a simple format and have your App Store Package generated for you?
5
+
6
+ ## Installation
7
+ ```sh
8
+ $ gem install itunes_transporter_generator
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Get Familiar With The Spec
14
+ First, you'll need to be familiar with the app metadata specification (download from [here](http://bit.ly/TtHMF6)), which outlines all the possible information describing an achievement, leaderboard, or in-app purchase.
15
+
16
+ ### Describe your application metadata
17
+ Next, you'll need to create a YAML file describing your company information and achievement, leaderboard, and/or in-app purchase details.
18
+
19
+ ### Generate the .itmsp
20
+ This is as simple as running the following command in the folder containing your YAML config file and all referenced images.
21
+
22
+ ```sh
23
+ $ itmsp package -i <configuration file>
24
+ ```
25
+
26
+ ### That's It!
27
+ You can now upload your .itmsp package to iTunes Connect using the Transporter tool. Alternatively, there is another great open-source tool which wraps some of the complexities of running Transporter directly (https://github.com/sshaw/itunes_store_transporter)
28
+
29
+ ## Sample Config file
30
+ Below is a sample configuration file describing an achievement, leaderboard, and in-app purchase. The specific metadata required for each item type is fully described in the [App Metadata Specification guide](http://bit.ly/TtHMF6)
31
+
32
+ ```yaml
33
+ provider: SampleCompany # optional if team_id is supplied
34
+ team_id: ABCDE12345 # optional if provider is supplied
35
+ vendor_id: sample sku # the application's SKU as definied in iTunes Connect
36
+ id_prefix: com.samplecompany.applicationname. # if supplied, this will be prefixed to achievement, leaderboard, and in-app purchase IDs
37
+ achievements: # the order in which achievements are defined will be the order in which they appear in Game Center
38
+ - id: first_achievement
39
+ name: First Achievement
40
+ points: 10
41
+ locales:
42
+ - name: en
43
+ title: First Achievement
44
+ before_earned_description: 'Complete a task'
45
+ after_earned_description: 'Completed a task'
46
+ after_earned_image: achievement.jpg
47
+
48
+ leaderboards: # the order in which leaderboards are defined will be the order in which they appear in Game Center
49
+ - default: true # only one leaderboard can be set as default.
50
+ id: top_scores
51
+ name: Top Scores
52
+ locales:
53
+ - name: en
54
+ title: Top Scores
55
+ formatter_suffix: ' Points' # note the space. This must be provided if you want a space between the value and suffix
56
+ formatter_suffix_singular: ' Point'
57
+ formatter_type: INTEGER_COMMA_SEPARATOR
58
+ leaderboard_image: leaderboard.jpg
59
+
60
+ purchases:
61
+ - product_id: one_hundred_dollars
62
+ reference_name: '100 dollars'
63
+ type: consumable
64
+ review_screenshot_image: product1.jpg
65
+ products:
66
+ - cleared_for_sale: true
67
+ wholesale_price_tier: 1 # pricing tier matrix is available in Exhibit C of the iOS Paid Applications contract in the Contracts, Tax, and Banking section of iTunes Connect
68
+ locales:
69
+ - name: en
70
+ title: '$100'
71
+ description: 'An extra $100 to help you out'
72
+ ```
73
+
74
+ This configuration will generate the following metadata.xml:
75
+ ```xml
76
+ <?xml version="1.0" encoding="UTF-8"?>
77
+ <package xmlns="http://apple.com/itunes/importer" version="software5.0">
78
+ <provider>SampleCompany</provider>
79
+ <team_id>ABCDE12345</team_id>
80
+ <software>
81
+ <vendor_id>sample sku</vendor_id>
82
+ <software_metadata>
83
+ <game_center>
84
+ <achievements>
85
+ <achievement position="1">
86
+ <achievement_id>com.samplecompany.applicationname.first_achievement</achievement_id>
87
+ <reference_name>First Achievement</reference_name>
88
+ <points>10</points>
89
+ <hidden>false</hidden>
90
+ <reusable>false</reusable>
91
+ <locales>
92
+ <locale name="en">
93
+ <title>First Achievement</title>
94
+ <before_earned_description>Complete a task</before_earned_description>
95
+ <after_earned_description>Completed a task</after_earned_description>
96
+ <after_earned_image>
97
+ <file_name>test.jpg</file_name>
98
+ <size>20092</size>
99
+ <checksum type="md5">ff5bd97a5f40bb75a84884589ecbfc42</checksum>
100
+ </after_earned_image>
101
+ </locale>
102
+ </locales>
103
+ </achievement>
104
+ </achievements>
105
+ <leaderboards>
106
+ <leaderboard default="true" position="1">
107
+ <leaderboard_id/>
108
+ <reference_name>Top Scores</reference_name>
109
+ <sort_ascending>false</sort_ascending>
110
+ <locales>
111
+ <locale name="en">
112
+ <title>Top Scores</title>
113
+ <formatter_suffix> Points</formatter_suffix>
114
+ <formatter_suffix_singular> Point</formatter_suffix_singular>
115
+ <formatter_type>INTEGER_COMMA_SEPARATOR</formatter_type>
116
+ <leaderboard_image>
117
+ <file_name>test.jpg</file_name>
118
+ <size>20092</size>
119
+ <checksum type="md5">ff5bd97a5f40bb75a84884589ecbfc42</checksum>
120
+ </leaderboard_image>
121
+ </locale>
122
+ </locales>
123
+ </leaderboard>
124
+ </leaderboards>
125
+ <in_app_purchases>
126
+ <in_app_purchase>
127
+ <product_id>com.samplecompany.applicationname.one_hundred_dollars</product_id>
128
+ <reference_name>100 dollars</reference_name>
129
+ <type>consumable</type>
130
+ <products>
131
+ <product>
132
+ <cleared_for_sale>true</cleared_for_sale>
133
+ <wholesale_price_tier>1</wholesale_price_tier>
134
+ </product>
135
+ </products>
136
+ <locales>
137
+ <locale name="en">
138
+ <title>$100</title>
139
+ <description>An extra $100 to help you out</description>
140
+ </locale>
141
+ </locales>
142
+ <review_screenshot>
143
+ <file_name>test.jpg</file_name>
144
+ <size>20092</size>
145
+ <checksum type="md5">ff5bd97a5f40bb75a84884589ecbfc42</checksum>
146
+ </review_screenshot>
147
+ </in_app_purchase>
148
+ </in_app_purchases>
149
+ </game_center>
150
+ </software_metadata>
151
+ </software>
152
+ </package>
153
+ ```
154
+
155
+ ## Todo
156
+ * TESTS. High on my list
157
+ * Metadata validation. There are lots of rules depending on what values you provide. You should know when you generate the package if there are any issues instead of having Apple tell you when you upload
158
+ * Anything else! Pull requests are welcome! This is my first Ruby project so I'm sure there is are a lot of improvements that can be made
159
+
160
+ ## Contact
161
+
162
+ Colin Humber
163
+
164
+ - http://github.com/colinhumber
165
+ - http://twitter.com/colinhumber
166
+
167
+ ## License
168
+
169
+ itmsp is available under the MIT license. See the LICENSE file for more info.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/itmsp ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+ require 'commander/import'
5
+ require 'itunes'
6
+ require 'itunes/transporter/commands'
7
+
8
+ Signal.trap("INT") {} # Suppress backtrace when exiting command
9
+
10
+ program :version, Itunes::VERSION
11
+ program :description, 'Generate iTunes Store Transporter package (.itmsp) from Achievements, Leaderboards, and/or In-App Purchases'
12
+ program :help, 'Author', 'Colin Humber'
13
+
14
+ program :help_formatter, :compact
15
+
16
+ default_command :help
@@ -0,0 +1,11 @@
1
+ require './achievement'
2
+
3
+ def get_achievements
4
+ achievement1 = Achievement.new('achievement1', 'First Achievement', 10)
5
+ achievement1.add_locale(AchievementLocale.new('en', 'First Achievement', 'Unlock achievement 1', 'Unlock achievement 1', 'test.jpg'))
6
+
7
+ achievement2 = Achievement.new('achievement2', 'Second Achievement', 10)
8
+ achievement2.add_locale(AchievementLocale.new('en', 'Second Achievement', 'Unlock achievement 2', 'Unlock achievement 2', 'test.jpg'))
9
+
10
+ return [achievement1, achievement2]
11
+ end
@@ -0,0 +1,4 @@
1
+ id_prefix: 'com.company.product.'
2
+ provider: 'Company Name'
3
+ team_id: 'Team ID'
4
+ vendor_id: 'Vendor ID'
@@ -0,0 +1,9 @@
1
+ require './in_app_purchase'
2
+
3
+ def get_in_app_purchases
4
+ purchase1 = InAppPurchase.new('purchase1', 'First Purchase', CONSUMABLE, 'test.jpg')
5
+ purchase1.add_product(Product.new(true, 1))
6
+ purchase1.add_locale(ProductLocale.new('en', 'First Purchase', 'Some cools stuff.'))
7
+
8
+ return [purchase1]
9
+ end
@@ -0,0 +1,12 @@
1
+ require './leaderboard'
2
+
3
+ def get_leaderboards
4
+ default = Leaderboard.new('leaderboard', 'Top Scores')
5
+ locale = LeaderboardLocale.new('en', 'Top Scores', INTEGER_COMMA_SEPARATOR, 'test.jpg')
6
+ locale.formatter_suffix = ' Points'
7
+ locale.formatter_suffix_singular = ' Points'
8
+
9
+ default.add_locale(locale)
10
+
11
+ return [default]
12
+ end
data/example/test.jpg ADDED
Binary file
data/example/test.rb ADDED
@@ -0,0 +1,5 @@
1
+ require './itunes_transporter_generator'
2
+
3
+ generator = ItunesTransporterGenerator::Generator.new
4
+ generator.generate_metadata
5
+ generator.generate_itmsp
data/itmsp.gemspec ADDED
@@ -0,0 +1,16 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'itunes_transporter_generator'
3
+ s.version = '0.2'
4
+ s.date = '2012-11-28'
5
+ s.summary = "iTunes Transporter App Store Package Generator"
6
+ s.description = "A command-line tool for generating and packaging app store assets for Game Center and In-App Purchases"
7
+ s.authors = ["Colin Humber"]
8
+ s.email = 'colinhumber@gmail.com'
9
+ s.homepage = 'https://github.com/colinhumber/itunes_transporter_generator'
10
+
11
+ s.add_dependency 'builder', '~>3.0.0'
12
+
13
+ s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|log|pkg|script|spec|test|vendor)/ }
14
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
15
+ s.require_paths = ['lib']
16
+ end
data/lib/itunes.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Itunes
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,9 @@
1
+ module Itunes
2
+ module Transporter
3
+ class Achievement < Struct.new(:id, :name, :points, :hidden, :reusable, :should_remove, :locales)
4
+ end
5
+
6
+ class AchievementLocale < Struct.new(:name, :title, :before_earned_description, :after_earned_description, :after_earned_image, :should_remove)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,2 @@
1
+ require 'itunes/transporter/commands/metadata'
2
+ require 'itunes/transporter/commands/package'
@@ -0,0 +1,13 @@
1
+ require 'itunes/transporter/generator'
2
+
3
+ command :package do |c|
4
+ c.syntax = 'itmsp package [options]'
5
+ c.summary = ''
6
+ c.description = 'Generates iTunes Store Package metadata.xml from provided achievement, leaderboard, and/or in-app purchases provided'
7
+ c.example 'description', 'command example'
8
+ c.option '-i FILENAME', '--input FILENAME', String, 'YAML file containing app/team values, achievement, leaderboard, and/or in-app purchase descriptions'
9
+
10
+ c.action do |args, options|
11
+ Itunes::Transporter::Generator.new(options).generate_metadata
12
+ end
13
+ end
@@ -0,0 +1,196 @@
1
+ require 'builder'
2
+ require 'digest'
3
+ require 'itunes/transporter/helpers'
4
+
5
+ module Itunes
6
+ module Transporter
7
+ class Generator
8
+ include Itunes::Transporter::Helpers
9
+
10
+ attr_reader :files_to_process
11
+ attr_accessor :id_prefix
12
+ attr_accessor :provider
13
+ attr_accessor :team_id
14
+ attr_accessor :vendor_id
15
+ attr_accessor :achievements
16
+ attr_accessor :leaderboards
17
+ attr_accessor :purchases
18
+
19
+ def initialize(options)
20
+ @files_to_process = ['metadata.xml']
21
+
22
+ config_file = options.i || options.input
23
+
24
+ metadata = metadata_from_yaml(config_file)
25
+
26
+ @id_prefix = metadata[:id_prefix]
27
+ @provider = metadata[:provider]
28
+ @team_id = metadata[:team_id]
29
+ @vendor_id = metadata[:vendor_id]
30
+ @achievements = metadata[:achievements]
31
+ @leaderboards = metadata[:leaderboards]
32
+ @purchases = metadata[:purchases]
33
+ end
34
+
35
+ def create_achievement_xml(doc, achievement, position)
36
+ doc.achievement('position' => position) do
37
+ doc.achievement_id(@id_prefix + achievement.id)
38
+ doc.reference_name(achievement.name)
39
+ doc.points(achievement.points)
40
+ doc.hidden(achievement.hidden)
41
+ doc.reusable(achievement.reusable)
42
+ doc.locales() do
43
+ achievement.locales.each do |locale|
44
+ doc.locale('name' => locale.name) do
45
+ doc.title(locale.title)
46
+ doc.before_earned_description(locale.before_earned_description)
47
+ doc.after_earned_description(locale.after_earned_description)
48
+ doc.after_earned_image() do
49
+ image_path = Dir.pwd + "/#{locale.after_earned_image}"
50
+ @files_to_process << image_path
51
+
52
+ doc.file_name(locale.after_earned_image)
53
+ doc.size(File.size?(image_path))
54
+ doc.checksum(Digest::MD5.file(image_path).hexdigest, 'type' => 'md5')
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+
62
+ def create_leaderboard_xml(doc, leaderboard, position)
63
+ doc.leaderboard('default' => leaderboard.default, 'position' => position) do
64
+ doc.leaderboard_id(leaderboard.id)
65
+ doc.reference_name(leaderboard.name)
66
+
67
+ if leaderboard.aggregate_parent_leaderboard
68
+ doc.aggregate_parent_leaderboard(leaderboard.aggregate_parent_leaderboard)
69
+ end
70
+
71
+ doc.sort_ascending(leaderboard.sort_ascending)
72
+
73
+ if (doc.score_range_min != doc.score_range_max)
74
+ doc.score_range_min(leaderboard.score_range_min)
75
+ doc.score_range_max(leaderboard.score_range_max)
76
+ end
77
+
78
+ doc.locales() do
79
+ leaderboard.locales.each do |locale|
80
+ doc.locale('name' => locale.name) do
81
+ doc.title(locale.title)
82
+
83
+ if (locale.formatter_suffix)
84
+ doc.formatter_suffix(locale.formatter_suffix)
85
+ end
86
+
87
+ if (locale.formatter_suffix_singular)
88
+ doc.formatter_suffix_singular(locale.formatter_suffix_singular)
89
+ end
90
+
91
+ doc.formatter_type(locale.formatter_type)
92
+ doc.leaderboard_image() do
93
+ image_path = Dir.pwd + "/#{locale.leaderboard_image}"
94
+ @files_to_process << image_path
95
+
96
+ doc.file_name(locale.leaderboard_image)
97
+ doc.size(File.size?(image_path))
98
+ doc.checksum(Digest::MD5.file(image_path).hexdigest, 'type' => 'md5')
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ def create_purchase_xml(doc, purchase)
107
+ doc.in_app_purchase() do
108
+ doc.product_id(@id_prefix + purchase.product_id)
109
+ doc.reference_name(purchase.reference_name)
110
+ doc.type(purchase.type)
111
+
112
+ doc.products() do
113
+ purchase.products.each do |product|
114
+ doc.product() do
115
+ doc.cleared_for_sale(product.cleared_for_sale)
116
+ doc.wholesale_price_tier(product.wholesale_price_tier)
117
+ end
118
+ end
119
+ end
120
+
121
+ doc.locales() do
122
+ purchase.locales.each do |locale|
123
+ doc.locale('name' => locale.name) do
124
+ doc.title(locale.title)
125
+ doc.description(locale.description)
126
+ end
127
+ end
128
+ end
129
+
130
+ doc.review_screenshot() do
131
+ image_path = Dir.pwd + "/#{purchase.review_screenshot_image}"
132
+ @files_to_process << image_path
133
+
134
+ doc.file_name(purchase.review_screenshot_image)
135
+ doc.size(File.size?(image_path))
136
+ doc.checksum(Digest::MD5.file(image_path).hexdigest, 'type' => 'md5')
137
+ end
138
+ end
139
+ end
140
+
141
+ def generate_metadata
142
+ metadata_file = File.new(Dir.pwd + '/metadata.xml', 'w')
143
+
144
+ doc = Builder::XmlMarkup.new(:target => metadata_file, :indent => 2)
145
+ doc.instruct!(:xml, :version => '1.0', :encoding => 'UTF-8')
146
+ doc.package('xmlns' => 'http://apple.com/itunes/importer', 'version' => 'software5.0') do
147
+ doc.provider(@provider)
148
+ doc.team_id(@team_id)
149
+ doc.software() do
150
+ doc.vendor_id(@vendor_id)
151
+ doc.software_metadata() do
152
+ doc.game_center() do
153
+ if (@achievements.count > 0)
154
+ doc.achievements() do
155
+ @achievements.each_with_index do |val, index|
156
+ create_achievement_xml(doc, val, index + 1)
157
+ end
158
+ end
159
+ end
160
+
161
+ if (@leaderboards.count > 0)
162
+ doc.leaderboards() do
163
+ @leaderboards.each_with_index do |val, index|
164
+ create_leaderboard_xml(doc, val, index + 1)
165
+ end
166
+ end
167
+ end
168
+
169
+ if (@purchases.count > 0)
170
+ doc.in_app_purchases() do
171
+ @purchases.each do |val|
172
+ create_purchase_xml(doc, val)
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
179
+ end
180
+
181
+ metadata_file.close()
182
+
183
+ generate_itmsp
184
+ end
185
+
186
+ def generate_itmsp
187
+ itmsp_dir = @vendor_id + '.itmsp'
188
+ Dir.mkdir(itmsp_dir)
189
+
190
+ @files_to_process.each do |file|
191
+ FileUtils.cp(file, itmsp_dir)
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,143 @@
1
+ require 'yaml'
2
+ require 'itunes/transporter/achievement'
3
+ require 'itunes/transporter/leaderboard'
4
+ require 'itunes/transporter/in_app_purchase'
5
+
6
+ module Itunes
7
+ module Transporter
8
+ module Helpers
9
+ def metadata_from_yaml(yaml_file)
10
+ objs = YAML.load_file(Dir.pwd + "/#{yaml_file}")
11
+
12
+ metadata = {
13
+ :provider => objs['provider'],
14
+ :team_id => objs['team_id'],
15
+ :vendor_id => objs['vendor_id'],
16
+ :id_prefix => objs['id_prefix'] || '',
17
+ :achievements => parse_achievements(objs),
18
+ :leaderboards => parse_leaderboards(objs),
19
+ :purchases => parse_purchases(objs)
20
+ }
21
+ end
22
+
23
+ def parse_achievements(objs)
24
+ achievements = []
25
+
26
+ objs['achievements'].each do |dict|
27
+ achievement = Achievement.new
28
+ achievement.id = dict['id']
29
+ achievement.name = dict['name']
30
+ achievement.points = dict['points']
31
+ achievement.hidden = dict.has_key?('hidden') ? dict['has_key'] : false
32
+ achievement.reusable = dict.has_key?('reusable') ? dict['reusable'] : false
33
+ achievement.should_remove = dict.has_key?('should_remove') ? dict['should_remove'] : false
34
+ achievement.locales = []
35
+
36
+ dict['locales'].each do |loc|
37
+ locale = AchievementLocale.new
38
+ locale.name = loc['name']
39
+ locale.title = loc['title']
40
+ locale.before_earned_description = loc['before_earned_description']
41
+ locale.after_earned_description = loc['after_earned_description']
42
+ locale.after_earned_image = loc['after_earned_image']
43
+ locale.should_remove = loc.has_key?('should_remove') ? loc['should_remove'] : false
44
+
45
+ achievement.locales << locale
46
+ end
47
+
48
+ achievements << achievement
49
+ end
50
+
51
+ achievements
52
+ end
53
+
54
+ def parse_leaderboards(objs)
55
+ leaderboards = []
56
+
57
+ objs['leaderboards'].each do |dict|
58
+ leaderboard = Leaderboard.new
59
+ leaderboard.default = dict['default']
60
+ leaderboard.name = dict['name']
61
+ leaderboard.aggregate_parent_leaderboard = dict['aggregate_parent_leaderboard']
62
+ leaderboard.sort_ascending = dict.has_key?('sort_ascending') ? dict['sort_ascending'] : false
63
+ leaderboard.score_range_min = dict['score_range_min']
64
+ leaderboard.score_range_max = dict['score_range_max']
65
+ leaderboard.locales = []
66
+
67
+ dict['locales'].each do |loc|
68
+ locale = LeaderboardLocale.new
69
+ locale.name = loc['name']
70
+ locale.title = loc['title']
71
+ locale.formatter_suffix = loc['formatter_suffix']
72
+ locale.formatter_suffix_singular = loc['formatter_suffix_singular']
73
+ locale.formatter_type = loc['formatter_type']
74
+ locale.leaderboard_image = loc['leaderboard_image']
75
+ locale.should_remove = loc.has_key?('should_remove') ? loc['should_remove'] : false
76
+
77
+ leaderboard.locales << locale
78
+ end
79
+
80
+ leaderboards << leaderboard
81
+ end
82
+
83
+ leaderboards
84
+ end
85
+
86
+ def parse_purchases(objs)
87
+ purchases = []
88
+
89
+ objs['purchases'].each do |dict|
90
+ purchase = InAppPurchase.new
91
+ purchase.product_id = dict['product_id']
92
+ purchase.reference_name = dict['reference_name']
93
+ purchase.type = dict['type']
94
+ purchase.duration = dict['duration']
95
+ purchase.free_trial_duration = dict['free_trial_duration']
96
+ purchase.bonus_duration = dict['bonus_duration']
97
+ purchase.review_screenshot_image = dict['review_screenshot_image']
98
+ purchase.review_notes = dict['review_notes']
99
+ purchase.should_remove = dict.has_key?('should_remove') ? dict['should_remove'] : false
100
+ purchase.locales = []
101
+ purchase.products = []
102
+
103
+ dict['products'].each do |p|
104
+ product = Product.new
105
+ product.cleared_for_sale = p['cleared_for_sale']
106
+ product.wholesale_price_tier = p['wholesale_price_tier']
107
+ product.should_remove = dict.has_key?('should_remove') ? dict['should_remove'] : false
108
+ product.intervals = []
109
+
110
+ intervals = p['intervals']
111
+ if intervals
112
+ p['intervals'].each do |i|
113
+ interval = Interval.new
114
+ interval.start_date = i['start_date']
115
+ interval.end_date = i['end_date']
116
+ interval.wholesale_price_tier = i['wholesale_price_tier']
117
+
118
+ product.intervals << interval
119
+ end
120
+ end
121
+
122
+ purchase.products << product
123
+ end
124
+
125
+ dict['locales'].each do |loc|
126
+ locale = PurchaseLocale.new
127
+ locale.name = loc['name']
128
+ locale.title = loc['title']
129
+ locale.description = loc['description']
130
+ locale.publication_name = loc['publication_name']
131
+
132
+ purchase.locales << locale
133
+ end
134
+
135
+ purchases << purchase
136
+ end
137
+
138
+ purchases
139
+ end
140
+
141
+ end
142
+ end
143
+ end
@@ -0,0 +1,28 @@
1
+ module Itunes
2
+ module Transporter
3
+
4
+ CONSUMABLE = 'consumable'
5
+ NON_CONSUMABLE = 'non-consumable'
6
+ SUBSCRIPTION = 'subscription'
7
+ FREE_SUBSCRIPTION = 'free-subscription'
8
+
9
+ DURATION_7_DAYS = '7 Days'
10
+ DURATION_1_MONTH = '1 Month'
11
+ DURATION_2_MONTHS = '2 Months'
12
+ DURATION_3_MONTHS = '3 Months'
13
+ DURATION_6_MONTH = '6 Months'
14
+ DURATION_1_YEAR = '1 Year'
15
+
16
+ class InAppPurchase < Struct.new(:product_id, :reference_name, :type, :duration, :free_trial_duration, :bonus_duration, :products, :locales, :review_screenshot_image, :review_notes, :should_remove)
17
+ end
18
+
19
+ class Product < Struct.new(:cleared_for_sale, :intervals, :should_remove, :wholesale_price_tier)
20
+ end
21
+
22
+ class Interval < Struct.new(:start_date, :end_date, :wholesale_price_tier)
23
+ end
24
+
25
+ class PurchaseLocale < Struct.new(:name, :title, :description, :publication_name)
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,36 @@
1
+ require 'itunes/transporter/locale'
2
+
3
+ module Itunes
4
+ module Transporter
5
+ class Leaderboard < Struct.new(:default, :id, :name, :aggregate_parent_leaderboard, :sort_ascending, :score_range_min, :score_range_max, :locales)
6
+ end
7
+
8
+ class LeaderboardLocale < Struct.new(:name, :title, :formatter_suffix, :formatter_suffix_singular, :formatter_type, :leaderboard_image, :should_remove)
9
+ end
10
+
11
+ INTEGER_COMMA_SEPARATOR = 'INTEGER_COMMA_SEPARATOR'
12
+ INTEGER_DECIMAL_SEPARATOR = 'INTEGER_DECIMAL_SEPARATOR'
13
+ FIXED_POINT_1_PLACE_WITH_COMMA_SEPARATOR = 'FIXED_POINT_1_PLACE_WITH_COMMA_SEPARATOR'
14
+ FIXED_POINT_1_PLACE_WITH_DECIMAL_SEPARATOR = 'FIXED_POINT_1_PLACE_WITH_DECIMAL_SEPARATOR'
15
+ FIXED_POINT_2_PLACE_WITH_COMMA_SEPARATOR = 'FIXED_POINT_2_PLACE_WITH_COMMA_SEPARATOR'
16
+ FIXED_POINT_2_PLACE_WITH_DECIMAL_SEPARATOR = 'FIXED_POINT_2_PLACE_WITH_DECIMAL_SEPARATOR'
17
+ FIXED_POINT_3_PLACE_WITH_COMMA_SEPARATOR = 'FIXED_POINT_3_PLACE_WITH_COMMA_SEPARATOR'
18
+ FIXED_POINT_3_PLACE_WITH_DECIMAL_SEPARATOR = 'FIXED_POINT_3_PLACE_WITH_DECIMAL_SEPARATOR'
19
+ ELAPSED_TIME_TO_MINUTE = 'ELAPSED_TIME_TO_MINUTE'
20
+ ELAPSED_TIME_TO_SECOND = 'ELAPSED_TIME_TO_SECOND'
21
+ ELAPSED_TIME_TO_HUNDREDTH_OF_SECOND = 'ELAPSED_TIME_TO_HUNDREDTH_OF_SECOND'
22
+ MONEY_DOLLAR_WHOLE_WITH_COMMA_SEPARATOR = 'MONEY_DOLLAR_WHOLE_WITH_COMMA_SEPARATOR'
23
+ MONEY_EURO_WHOLE_WITH_DECIMAL_SEPARATOR = 'MONEY_EURO_WHOLE_WITH_DECIMAL_SEPARATOR'
24
+ MONEY_EURO_WHOLE_WITH_SPACE_SEPARATOR = 'MONEY_EURO_WHOLE_WITH_SPACE_SEPARATOR'
25
+ MONEY_POUND_WHOLE_WITH_COMMA_SEPARATOR = 'MONEY_POUND_WHOLE_WITH_COMMA_SEPARATOR'
26
+ MONEY_KR_WHOLE_WITH_COMMA_SEPARATOR = 'MONEY_KR_WHOLE_WITH_COMMA_SEPARATOR'
27
+ MONEY_FR_WHOLE_WITH_SPACE_SEPARATOR = 'MONEY_FR_WHOLE_WITH_SPACE_SEPARATOR'
28
+ MONEY_YEN_WHOLE_WITH_COMMA_SEPARATOR= 'MONEY_YEN_WHOLE_WITH_COMMA_SEPARATOR'
29
+ MONEY_DOLLAR_2DECIMALS_WITH_COMMA_SEPARATOR = 'MONEY_DOLLAR_2DECIMALS_WITH_COMMA_SEPARATOR'
30
+ MONEY_EURO_2DECIMALS_WITH_DECIMAL_SEPARATOR= 'MONEY_EURO_2DECIMALS_WITH_DECIMAL_SEPARATOR'
31
+ MONEY_EURO_2DECIMALSE_WITH_SPACE_SEPARATOR = 'MONEY_EURO_2DECIMALSE_WITH_SPACE_SEPARATOR'
32
+ MONEY_POUND_2DECIMALS_WITH_COMMA_SEPARATOR = 'MONEY_POUND_2DECIMALS_WITH_COMMA_SEPARATOR'
33
+ MONEY_KR_2DECIMALS_WITH_COMMA_SEPARATOR = 'MONEY_KR_2DECIMALS_WITH_COMMA_SEPARATOR'
34
+ MONEY_FR_2DECIMALS_WITH_SPACE_SEPARATOR = 'MONEY_FR_2DECIMALS_WITH_SPACE_SEPARATOR'
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ module Itunes
2
+ module Transporter
3
+ class Locale
4
+ attr_accessor :language
5
+ attr_accessor :title
6
+
7
+ def initialize(language, title)
8
+ @language = language
9
+ @title = title
10
+ end
11
+ end
12
+ end
13
+ end
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: itunes_transporter_generator
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.2'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Colin Humber
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-11-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: builder
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.0.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 3.0.0
30
+ description: A command-line tool for generating and packaging app store assets for
31
+ Game Center and In-App Purchases
32
+ email: colinhumber@gmail.com
33
+ executables:
34
+ - itmsp
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - ./example/achievements.rb
39
+ - ./example/config.yaml
40
+ - ./example/in_app_purchases.rb
41
+ - ./example/leaderboards.rb
42
+ - ./example/test.jpg
43
+ - ./example/test.rb
44
+ - ./itmsp.gemspec
45
+ - ./lib/itunes/transporter/achievement.rb
46
+ - ./lib/itunes/transporter/commands/package.rb
47
+ - ./lib/itunes/transporter/commands.rb
48
+ - ./lib/itunes/transporter/generator.rb
49
+ - ./lib/itunes/transporter/helpers.rb
50
+ - ./lib/itunes/transporter/in_app_purchase.rb
51
+ - ./lib/itunes/transporter/leaderboard.rb
52
+ - ./lib/itunes/transporter/locale.rb
53
+ - ./lib/itunes.rb
54
+ - ./Rakefile
55
+ - ./README.md
56
+ - bin/itmsp
57
+ homepage: https://github.com/colinhumber/itunes_transporter_generator
58
+ licenses: []
59
+ post_install_message:
60
+ rdoc_options: []
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 1.8.24
78
+ signing_key:
79
+ specification_version: 3
80
+ summary: iTunes Transporter App Store Package Generator
81
+ test_files: []