itunes_transporter_generator 0.2 → 0.4.2

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.
Files changed (80) hide show
  1. data/Gemfile +3 -0
  2. data/LICENSE +19 -0
  3. data/README.md +250 -52
  4. data/doc/Itunes.html +198 -0
  5. data/doc/Itunes/Transporter.html +380 -0
  6. data/doc/Itunes/Transporter/Achievement.html +165 -0
  7. data/doc/Itunes/Transporter/AchievementLocale.html +165 -0
  8. data/doc/Itunes/Transporter/Generator.html +700 -0
  9. data/doc/Itunes/Transporter/Helpers.html +427 -0
  10. data/doc/Itunes/Transporter/InAppPurchase.html +165 -0
  11. data/doc/Itunes/Transporter/Interval.html +165 -0
  12. data/doc/Itunes/Transporter/Leaderboard.html +165 -0
  13. data/doc/Itunes/Transporter/LeaderboardLocale.html +165 -0
  14. data/doc/Itunes/Transporter/Locale.html +256 -0
  15. data/doc/Itunes/Transporter/Product.html +165 -0
  16. data/doc/Itunes/Transporter/PurchaseLocale.html +165 -0
  17. data/doc/Object.html +307 -0
  18. data/doc/Rakefile.html +112 -0
  19. data/doc/bin/itmsp.html +60 -0
  20. data/doc/created.rid +16 -0
  21. data/doc/example/achievements_rb.html +54 -0
  22. data/doc/example/in_app_purchases_rb.html +54 -0
  23. data/doc/example/leaderboards_rb.html +54 -0
  24. data/doc/example/test_rb.html +54 -0
  25. data/doc/images/brick.png +0 -0
  26. data/doc/images/brick_link.png +0 -0
  27. data/doc/images/bug.png +0 -0
  28. data/doc/images/bullet_black.png +0 -0
  29. data/doc/images/bullet_toggle_minus.png +0 -0
  30. data/doc/images/bullet_toggle_plus.png +0 -0
  31. data/doc/images/date.png +0 -0
  32. data/doc/images/find.png +0 -0
  33. data/doc/images/loadingAnimation.gif +0 -0
  34. data/doc/images/macFFBgHack.png +0 -0
  35. data/doc/images/package.png +0 -0
  36. data/doc/images/page_green.png +0 -0
  37. data/doc/images/page_white_text.png +0 -0
  38. data/doc/images/page_white_width.png +0 -0
  39. data/doc/images/plugin.png +0 -0
  40. data/doc/images/ruby.png +0 -0
  41. data/doc/images/tag_green.png +0 -0
  42. data/doc/images/wrench.png +0 -0
  43. data/doc/images/wrench_orange.png +0 -0
  44. data/doc/images/zoom.png +0 -0
  45. data/doc/index.html +110 -0
  46. data/doc/js/darkfish.js +116 -0
  47. data/doc/js/jquery.js +32 -0
  48. data/doc/js/quicksearch.js +114 -0
  49. data/doc/js/thickbox-compressed.js +10 -0
  50. data/doc/lib/itunes/transporter/achievement_rb.html +52 -0
  51. data/doc/lib/itunes/transporter/commands/package_rb.html +54 -0
  52. data/doc/lib/itunes/transporter/commands_rb.html +56 -0
  53. data/doc/lib/itunes/transporter/generator_rb.html +58 -0
  54. data/doc/lib/itunes/transporter/helpers_rb.html +60 -0
  55. data/doc/lib/itunes/transporter/in_app_purchase_rb.html +52 -0
  56. data/doc/lib/itunes/transporter/leaderboard_rb.html +54 -0
  57. data/doc/lib/itunes/transporter/locale_rb.html +52 -0
  58. data/doc/lib/itunes_rb.html +52 -0
  59. data/doc/rdoc.css +763 -0
  60. data/example/config copy.yaml +75 -0
  61. data/example/config.yaml +109 -4
  62. data/example/metadata.xml +201 -0
  63. data/example/sample sku.itmsp/metadata.xml +201 -0
  64. data/example/sample sku.itmsp/test.jpg +0 -0
  65. data/itmsp.gemspec +8 -4
  66. data/lib/itunes.rb +2 -2
  67. data/lib/itunes/transporter.rb +75 -0
  68. data/lib/itunes/transporter/commands.rb +1 -1
  69. data/lib/itunes/transporter/commands/package.rb +12 -9
  70. data/lib/itunes/transporter/generator.rb +291 -191
  71. data/lib/itunes/transporter/helpers.rb +236 -139
  72. data/lib/itunes/transporter/in_app_purchase.rb +16 -23
  73. data/lib/itunes/transporter/leaderboard.rb +0 -36
  74. data/lib/itunes/transporter/locale.rb +11 -11
  75. metadata +81 -7
  76. data/example/achievements.rb +0 -11
  77. data/example/in_app_purchases.rb +0 -9
  78. data/example/leaderboards.rb +0 -12
  79. data/example/test.rb +0 -5
  80. data/lib/itunes/transporter/achievement.rb +0 -9
Binary file
data/itmsp.gemspec CHANGED
@@ -1,7 +1,10 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+ require "itunes"
3
+
1
4
  Gem::Specification.new do |s|
2
5
  s.name = 'itunes_transporter_generator'
3
- s.version = '0.2'
4
- s.date = '2012-11-28'
6
+ s.version = Itunes::VERSION
7
+ s.platform = Gem::Platform::RUBY
5
8
  s.summary = "iTunes Transporter App Store Package Generator"
6
9
  s.description = "A command-line tool for generating and packaging app store assets for Game Center and In-App Purchases"
7
10
  s.authors = ["Colin Humber"]
@@ -9,8 +12,9 @@ Gem::Specification.new do |s|
9
12
  s.homepage = 'https://github.com/colinhumber/itunes_transporter_generator'
10
13
 
11
14
  s.add_dependency 'builder', '~>3.0.0'
12
-
13
- s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|log|pkg|script|spec|test|vendor)/ }
15
+ s.add_dependency 'commander', '~> 4.1.3'
16
+
17
+ s.files = Dir["./**/*"].reject { |file| file =~ /\.\/(bin|log|pkg|script|spec|test|vendor)/ }
14
18
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
15
19
  s.require_paths = ['lib']
16
20
  end
data/lib/itunes.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Itunes
2
- VERSION = '0.0.1'
3
- end
2
+ VERSION = '0.4.2'
3
+ end
@@ -0,0 +1,75 @@
1
+ module Itunes
2
+ module Transporter
3
+ class Achievement < Struct.new(:id, :name, :points, :hidden, :reusable, :should_remove, :locales)
4
+ def to_s
5
+ "#{self.id} #{self.name}"
6
+ end
7
+ end
8
+
9
+ class AchievementLocale < Struct.new(:name, :title, :before_earned_description, :after_earned_description, :achievement_after_earned_image, :should_remove)
10
+ def to_s
11
+ "#{self.name} #{self.title}"
12
+ end
13
+ end
14
+
15
+ class Leaderboard < Struct.new(:default, :id, :name, :aggregate_parent_leaderboard, :sort_ascending, :score_range_min, :score_range_max, :locales)
16
+ def to_s
17
+ "#{self.name} #{self.title}"
18
+ end
19
+ end
20
+
21
+ class LeaderboardLocale < Struct.new(:name, :title, :formatter_suffix, :formatter_suffix_singular, :formatter_type, :leaderboard_image, :should_remove)
22
+ def to_s
23
+ "#{self.name} #{self.title}"
24
+ end
25
+ end
26
+
27
+ class InAppPurchase < Struct.new(:product_id, :reference_name, :type, :duration, :free_trial_duration, :bonus_duration, :products, :locales, :review_screenshot_image, :review_notes, :should_remove)
28
+ def to_s
29
+ "Product ID: #{self.product_id} Reference Name: #{self.reference_name}"
30
+ end
31
+ end
32
+
33
+ class Family < Struct.new(:name, :review_screenshot_image, :review_notes, :locales, :purchases)
34
+ def to_s
35
+ "Name: #{self.name} Purchases: #{self.purchases}"
36
+ end
37
+ end
38
+
39
+ class Product < Struct.new(:cleared_for_sale, :intervals, :should_remove, :wholesale_price_tier)
40
+ def to_s
41
+ "Cleared for sale: #{self.cleared_for_sale}, Tier: #{self.wholesale_price_tier}"
42
+ end
43
+ end
44
+
45
+ class Interval < Struct.new(:start_date, :end_date, :wholesale_price_tier)
46
+ def to_s
47
+ "Start date: #{self.start_date} End Date: #{self.end_date} Tier: #{self.wholesale_price_tier}"
48
+ end
49
+ end
50
+
51
+ class PurchaseLocale < Struct.new(:name, :title, :description, :publication_name)
52
+ def to_s
53
+ "Name: #{self.name} Title: #{self.title}"
54
+ end
55
+ end
56
+
57
+ class Version < Struct.new(:name, :locales)
58
+ def to_s
59
+ self.name
60
+ end
61
+ end
62
+
63
+ class VersionLocale < Struct.new(:name, :title, :description, :keywords, :version_whats_new, :software_url, :privacy_url, :support_url, :screenshots)
64
+ def to_s
65
+ "#{self.name} #{self.title}"
66
+ end
67
+ end
68
+
69
+ class VersionScreenshot < Struct.new(:display_target, :file_name)
70
+ def to_s
71
+ "#{self.display_target} - #{self.file_name}"
72
+ end
73
+ end
74
+ end
75
+ end
@@ -1,2 +1,2 @@
1
- require 'itunes/transporter/commands/metadata'
1
+ # require 'itunes/transporter/commands/metadata'
2
2
  require 'itunes/transporter/commands/package'
@@ -1,13 +1,16 @@
1
1
  require 'itunes/transporter/generator'
2
2
 
3
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
4
+ c.syntax = 'itmsp package [options]'
5
+ c.summary = ''
6
+ c.description = 'Generates iTunes Metadata Store Package (.itmsp) 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
+ output = Itunes::Transporter::Generator.new(options).generate_metadata
12
+
13
+ say_ok output[:messages].join("\n") if output[:messages].length > 0
14
+ say_error "Errors:\n #{output[:errors].join("\n")}" if output[:errors].length > 0
15
+ end
13
16
  end
@@ -1,196 +1,296 @@
1
1
  require 'builder'
2
2
  require 'digest'
3
+ require 'fileutils'
3
4
  require 'itunes/transporter/helpers'
4
5
 
5
6
  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
7
+ module Transporter
8
+ class Generator
9
+ include Itunes::Transporter::Helpers
10
+
11
+ attr_reader :files_to_process
12
+ attr_accessor :id_prefix
13
+ attr_accessor :provider
14
+ attr_accessor :team_id
15
+ attr_accessor :vendor_id
16
+ attr_accessor :achievements
17
+ attr_accessor :leaderboards
18
+ attr_accessor :purchases
19
+ attr_accessor :output
20
+ attr_accessor :versions
21
+
22
+ def initialize(options)
23
+ @files_to_process = ['metadata.xml']
24
+
25
+ config_file = options.i || options.input
26
+
27
+ metadata = metadata_from_yaml(config_file)
28
+
29
+ @id_prefix = metadata[:id_prefix]
30
+ @provider = metadata[:provider]
31
+ @team_id = metadata[:team_id]
32
+ @vendor_id = metadata[:vendor_id].to_s
33
+ @achievements = metadata[:achievements]
34
+ @leaderboards = metadata[:leaderboards]
35
+ @purchases = metadata[:purchases]
36
+ @default_achievement_image = metadata[:default_achievement_image]
37
+ @versions = metadata[:versions]
38
+ @output = { :messages => [], :errors => [] }
39
+ end
40
+
41
+ def create_version_xml(doc, version)
42
+ doc.version('string' => version.name) do
43
+ doc.locales() do
44
+
45
+ version.locales.each do |locale|
46
+ doc.locale('name' => locale.name) do
47
+ doc.title(locale.title)
48
+ doc.description(locale.description)
49
+
50
+ doc.keywords() do
51
+ locale.keywords.each do |keyword|
52
+ doc.keyword(keyword)
53
+ end
54
+ end
55
+
56
+ doc.version_whats_new(locale.version_whats_new)
57
+ doc.software_url(locale.software_url)
58
+ doc.privacy_url(locale.privacy_url)
59
+ doc.support_url(locale.support_url)
60
+
61
+ doc.software_screenshots() do
62
+ locale.screenshots.each_with_index do |screenshot, index|
63
+ doc.software_screenshot('display_target' => screenshot.display_target, 'position' => index + 1) do
64
+ create_screenshot_xml(doc, screenshot.file_name)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+
74
+ def create_achievement_xml(doc, achievement, position)
75
+ doc.achievement('position' => position) do
76
+ doc.achievement_id(@id_prefix + achievement.id)
77
+ doc.reference_name(achievement.name)
78
+ doc.points(achievement.points)
79
+ doc.hidden(achievement.hidden)
80
+ doc.reusable(achievement.reusable)
81
+ doc.locales() do
82
+ achievement.locales.each do |locale|
83
+ doc.locale('name' => locale.name) do
84
+ doc.title(locale.title)
85
+ doc.before_earned_description(locale.before_earned_description)
86
+ doc.after_earned_description(locale.after_earned_description)
87
+ doc.achievement_after_earned_image() do
88
+ create_screenshot_xml(doc, locale.achievement_after_earned_image || @default_achievement_image)
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ def create_leaderboard_xml(doc, leaderboard, position)
97
+ doc.leaderboard('default' => leaderboard.default, 'position' => position) do
98
+ doc.leaderboard_id(@id_prefix + leaderboard.id)
99
+ doc.reference_name(leaderboard.name)
100
+
101
+ if leaderboard.aggregate_parent_leaderboard
102
+ doc.aggregate_parent_leaderboard(leaderboard.aggregate_parent_leaderboard)
103
+ end
104
+
105
+ doc.sort_ascending(leaderboard.sort_ascending)
106
+
107
+ doc.score_range_min(leaderboard.score_range_min) if leaderboard.score_range_min
108
+ doc.score_range_max(leaderboard.score_range_max) if leaderboard.score_range_max
109
+
110
+ doc.locales() do
111
+ leaderboard.locales.each do |locale|
112
+ doc.locale('name' => locale.name) do
113
+ doc.title(locale.title)
114
+
115
+ doc.formatter_suffix(locale.formatter_suffix) if locale.formatter_suffix
116
+ doc.formatter_suffix_singular(locale.formatter_suffix_singular) if locale.formatter_suffix_singular
117
+
118
+ doc.formatter_type(locale.formatter_type)
119
+ doc.leaderboard_image() do
120
+ create_screenshot_xml(doc, locale.leaderboard_image)
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ def create_in_app_purchase_xml(doc, purchase)
129
+ doc.in_app_purchase() do
130
+ doc.product_id(@id_prefix + purchase.product_id)
131
+ doc.reference_name(purchase.reference_name) if purchase.reference_name
132
+ doc.duration(purchase.duration) if purchase.duration
133
+ doc.free_trial_duration(purchase.free_trial_duration) if purchase.free_trial_duration
134
+ doc.bonus_duration(purchase.bonus_duration) if purchase.bonus_duration
135
+
136
+ doc.type(purchase.type)
137
+
138
+ doc.products() do
139
+ purchase.products.each do |product|
140
+ doc.product() do
141
+ doc.cleared_for_sale(product.cleared_for_sale)
142
+ doc.wholesale_price_tier(product.wholesale_price_tier) if product.wholesale_price_tier
143
+
144
+ doc.intervals() do
145
+ product.intervals.each do |interval|
146
+ doc.interval() do
147
+ if (interval.start_date)
148
+ doc.start_date(interval.start_date) if interval.start_date
149
+ end
150
+
151
+ if (interval.end_date)
152
+ doc.end_date(interval.end_date) if interval.end_date
153
+ end
154
+
155
+ doc.wholesale_price_tier(interval.wholesale_price_tier)
156
+ end
157
+ end
158
+ end if product.intervals.count > 0
159
+ end
160
+ end
161
+ end
162
+
163
+ doc.locales() do
164
+ purchase.locales.each do |locale|
165
+ create_purchase_locale_xml(doc, locale)
166
+ end
167
+ end if purchase.locales.count > 0
168
+
169
+ doc.review_screenshot() do
170
+ create_screenshot_xml(doc, purchase.review_screenshot_image)
171
+ end if purchase.review_screenshot_image
172
+ end
173
+ end
174
+
175
+ def create_purchase_locale_xml(doc, locale)
176
+ doc.locale('name' => locale.name) do
177
+ doc.title(locale.title)
178
+ doc.description(locale.description)
179
+ doc.publication_name(locale.publication_name) if locale.publication_name
180
+ end
181
+ end
182
+
183
+ def create_purchase_family_xml(doc, family)
184
+ doc.family('name' => family.name) do
185
+ doc.locales() do
186
+ family.locales.each do |locale|
187
+ create_purchase_locale_xml(doc, locale)
188
+ end
189
+ end
190
+
191
+ doc.review_screenshot() do
192
+ create_screenshot_xml(doc, family.review_screenshot_image)
193
+ end
194
+
195
+ doc.review_notes(family.review_notes)
196
+
197
+ family.purchases.each do |purchase|
198
+ create_in_app_purchase_xml(doc, purchase)
199
+ end
200
+ end
201
+ end
202
+
203
+ def create_screenshot_xml(doc, file_name)
204
+ image_path = Dir.pwd + "/#{file_name}"
205
+ @files_to_process << image_path
206
+
207
+ doc.file_name(file_name)
208
+ doc.size(File.size?(image_path))
209
+ doc.checksum(Digest::MD5.file(image_path).hexdigest, 'type' => 'md5')
210
+ end
211
+
212
+ def create_other_purchases_xml(doc, purchases)
213
+ purchases.each do |purchase|
214
+ create_in_app_purchase_xml(doc, purchase)
215
+ end
216
+ end
217
+
218
+ def generate_metadata
219
+ metadata_file = File.new(Dir.pwd + '/metadata.xml', 'w')
220
+
221
+ doc = Builder::XmlMarkup.new(:target => metadata_file, :indent => 2)
222
+ doc.instruct!(:xml, :version => '1.0', :encoding => 'UTF-8')
223
+ doc.package('xmlns' => 'http://apple.com/itunes/importer', 'version' => 'software5.1') do
224
+ doc.provider(@provider) if @provider
225
+ doc.team_id(@team_id) if @team_id
226
+ doc.software() do
227
+ doc.vendor_id(@vendor_id)
228
+ doc.software_metadata() do
229
+ if @versions.count > 0
230
+ doc.versions() do
231
+ @versions.each do |version|
232
+ create_version_xml(doc, version)
233
+ end
234
+ end
235
+ end
236
+
237
+ doc.game_center() do
238
+ # generate XML for all achievements
239
+ if @achievements.count > 0
240
+ doc.achievements() do
241
+ @achievements.each_with_index do |val, index|
242
+ create_achievement_xml(doc, val, index + 1)
243
+ end
244
+ end
245
+ end
246
+
247
+ # generate XML for all leaderboards
248
+ if @leaderboards.count > 0
249
+ doc.leaderboards() do
250
+ @leaderboards.each_with_index do |val, index|
251
+ create_leaderboard_xml(doc, val, index + 1)
252
+ end
253
+ end
254
+ end
255
+ end
256
+
257
+ # generate XML for all auto-renewable subscriptions and other IAPs (consumable, non-consumable, subscription, free-subscription)
258
+ if @purchases.count > 0
259
+ auto_renewable_purchase_family = @purchases[:auto_renewable_purchase_family]
260
+ other_purchases = @purchases[:other_purchases]
261
+
262
+ doc.in_app_purchases() do
263
+ create_purchase_family_xml(doc, auto_renewable_purchase_family) if auto_renewable_purchase_family
264
+ create_other_purchases_xml(doc, other_purchases) if other_purchases
265
+ end
266
+ end
267
+ end
268
+ end
269
+ end
270
+
271
+ metadata_file.close()
272
+
273
+ generate_itmsp
274
+
275
+ output
276
+ end
277
+
278
+ def generate_itmsp
279
+ itmsp_dir = @vendor_id + '.itmsp'
280
+
281
+ begin
282
+ FileUtils.rm_rf(itmsp_dir) if Dir.exists?(itmsp_dir)
283
+ Dir.mkdir(itmsp_dir)
284
+
285
+ @files_to_process.each do |file|
286
+ FileUtils.cp(file, itmsp_dir)
287
+ end
288
+
289
+ output[:messages] << "Successfully created iTunes metadata package: #{itmsp_dir}"
290
+ rescue Exception => e
291
+ output[:errors] << e.message
292
+ end
293
+ end
294
+ end
295
+ end
296
+ end