itunes_transporter_generator 0.2 → 0.4.2

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