mmine 0.5.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2800c10a54597154aa688b4b33c10777331fef21d30c2241a1ec30eb44649242
4
+ data.tar.gz: eece39c70436d2b8c790a8e6aadc68733959542a162403f48dc63bfd63f68797
5
+ SHA512:
6
+ metadata.gz: 10cebf9df3bcc9e60c453f349afb2d9293eef2fdf860b927aa19202b9799cf46331f5336d0b396648e34bc248a6d2dca1e84daa16a3274bd11f5b216d58b7419
7
+ data.tar.gz: 41b64be07b953ee6741133263a9db4cf74230dad4e19baf71777d3a30a0b8e8a6880aacea11c1028a6350e6e8dd24820624fa1f1bab81a3af91be437b8438708
data/bin/mmine ADDED
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optionparser'
4
+ require 'mmine'
5
+
6
+ first_arg, *the_rest = ARGV
7
+
8
+ options = {}
9
+ integrate_parse = OptionParser.new do |opts|
10
+ opts.banner = "Usage: mmine [command] [parameters]"
11
+ opts.on("-p", "--project XCODE_PROJECT", "Path for your Xcode project file (.xcodeproj)") do |project|
12
+ options[:project] = project
13
+ end
14
+ opts.on("-g", "--app-group APP_GROUP_ID", "App Group Id for your shared location. You generate it here firs: https://developer.apple.com/account/ios/identifier/applicationGroup. For more inforamtion see https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW19") do |app_group|
15
+ options[:"app-group"] = app_group
16
+ end
17
+ opts.on("-t", "--target MAIN_TARGET", "Name of main Xcode project target") do |target|
18
+ options[:target] = target
19
+ end
20
+ opts.on("-v", "--verbose", "Make verbose logs visible") do |verbose|
21
+ options[:verbose] = verbose
22
+ end
23
+ opts.on("--cordova", "--cordova", "Provide Cordova project specific settings.") do |verbose|
24
+ options[:cordova] = verbose
25
+ end
26
+ opts.on("--swift-version", "--swift-version SWIFT_VER", "Provide Swift Language version for notification extension (by default 4.2)") do |ver|
27
+ options[:"swift-version"] = ver
28
+ end
29
+ opts.on("-h", "--help", "Prints this help") do
30
+ puts opts
31
+ exit
32
+ end
33
+ end
34
+
35
+ case first_arg
36
+ when "integrate"
37
+ begin
38
+ integrate_parse.parse!
39
+ mandatory = [:"project", :"app-group", :"target"]
40
+ missing = mandatory.select{ |param| options[param].nil? }
41
+ unless missing.empty?
42
+ raise OptionParser::MissingArgument.new(missing.join(', '))
43
+ end
44
+ integrator = NotificationExtensionIntegrator.new(options[:project], options[:"app-group"], options[:target], options[:cordova] || false, options[:"swift-version"] || "4.2")
45
+ integrator.logger = Logger.new(STDOUT)
46
+ integrator.logger.formatter = proc do |severity, datetime, progname, msg|
47
+ "#{severity}: #{msg}\n"
48
+ end
49
+ if options[:verbose]
50
+ integrator.logger.level = Logger::DEBUG
51
+ else
52
+ integrator.logger.level = Logger::WARN
53
+ end
54
+ integrator.setupNotificationExtension()
55
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument
56
+ puts $!.to_s
57
+ puts integrate_parse
58
+ exit
59
+ end
60
+ else
61
+ if first_arg == nil
62
+ puts "Please specify a command. For example 'mmine integrate'"
63
+ else
64
+ puts "Unknown command: #{first_arg}"
65
+ end
66
+ end
67
+
data/lib/mmine.rb ADDED
@@ -0,0 +1 @@
1
+ require 'mmine/notification_extension_integrator'
@@ -0,0 +1,443 @@
1
+ require 'xcodeproj'
2
+ require 'fileutils'
3
+ require 'pathname'
4
+ require 'nokogiri'
5
+ require 'logger'
6
+ require 'json'
7
+
8
+ module Mmine
9
+ def self.root
10
+ File.expand_path '../..', File.dirname(__FILE__)
11
+ end
12
+ end
13
+
14
+ class NotificationExtensionIntegrator
15
+ def initialize(project_file_path, app_group, main_target_name, cordova = false, swift_ver)
16
+ @project_file_path = project_file_path
17
+ @app_group = app_group
18
+ @main_target_name = main_target_name
19
+ @logger = nil
20
+ @cordova = cordova
21
+ @swift_version = swift_ver
22
+
23
+ @project_dir = Pathname.new(@project_file_path).parent.to_s
24
+ @project = Xcodeproj::Project.open(@project_file_path)
25
+ @ne_target_name = 'MobileMessagingNotificationExtension'
26
+ @extension_source_name_filepath = File.join(Mmine.root, 'resources','NotificationService.swift')
27
+ @extension_dir_name = 'NotificationExtension'
28
+ @extension_destination_dir = File.join(@project_dir, @extension_dir_name)
29
+ @extension_code_destination_filepath = File.join(@extension_destination_dir, 'NotificationService.swift')
30
+ @extension_group_name = 'NotificationExtensionGroup'
31
+
32
+ @plist_name = 'MobileMessagingNotificationServiceExtension.plist'
33
+ @plist_source_filepath = File.join(Mmine.root, 'resources', @plist_name)
34
+ @extension_info_plist_path = File.join(@project_dir, @extension_dir_name, @plist_name)
35
+
36
+ @main_target = @project.native_targets().select { |target| target.name == @main_target_name }.first
37
+ @main_target_build_settings_debug = @main_target.build_configurations.select { |config| config.type == :debug }.first.build_settings
38
+ @main_target_build_settings_release = @main_target.build_configurations.select { |config| config.type == :release }.first.build_settings
39
+ @main_target_debug_plist = resolveAbsolutePath(@main_target_build_settings_debug["INFOPLIST_FILE"])
40
+ @main_target_release_plist = resolveAbsolutePath(@main_target_build_settings_release["INFOPLIST_FILE"])
41
+ end
42
+
43
+ def logger=(_logger)
44
+ @logger = _logger
45
+ end
46
+ def logger
47
+ return @logger
48
+ end
49
+
50
+ def setupNotificationExtension
51
+
52
+ createNotificationExtensionTarget()
53
+ createNotificationExtensionDir()
54
+ addNotificationExtensionSourceCode()
55
+ setupDevelopmentTeam()
56
+ setupDeploymentTarget()
57
+ setupNotificationExtensionInfoPlist()
58
+ setupNotificationExtensionBundleId()
59
+ setupNotificationExtensionEntitlements()
60
+ setupMainTargetEntitlements()
61
+ setupAppGroupPlistValue()
62
+ setupBackgroundModesPlistValue()
63
+ setupExtensionTargetCapabilities()
64
+ setupMainTargetCapabilities()
65
+ setupEmbedExtensionAction()
66
+ setupMainTargetDependency()
67
+ setupSwiftVersion()
68
+ setupProductName()
69
+
70
+ if @cordova
71
+ setupFrameworkSearchPaths()
72
+ setupRunpathSearchPaths()
73
+ setupLibCordovaLink()
74
+ setupCopyFrameworkScript()
75
+ end
76
+
77
+ @project.save()
78
+ puts "🏁 Integration has been finished successfully!"
79
+ end
80
+
81
+ def createNotificationExtensionTarget
82
+ @ne_target = @project.native_targets().select { |target| target.name == @ne_target_name }.first
83
+ if @ne_target == nil
84
+ @logger.info("Creating notification extension target with name #{@ne_target_name}")
85
+ @ne_target = @project.new_target(:app_extension, @ne_target_name, ':ios')
86
+ else
87
+ @logger.info("Notification extension target already exists, reusing...")
88
+ end
89
+
90
+ @extension_build_settings_debug = @ne_target.build_configurations.select { |config| config.name == 'Debug' }.first.build_settings
91
+ @extension_build_settings_release = @ne_target.build_configurations.select { |config| config.name == 'Release' }.first.build_settings
92
+
93
+ @ne_target.frameworks_build_phase.files_references.each { |ref|
94
+ @ne_target.frameworks_build_phase.remove_file_reference(ref)
95
+ }
96
+
97
+ @logger.info("Notification extension target debug build settings:\n#{JSON.pretty_generate(@extension_build_settings_debug)}")
98
+ @logger.info("Notification extension target release build settings:\n#{JSON.pretty_generate(@extension_build_settings_release)}")
99
+ end
100
+
101
+ def createNotificationExtensionDir
102
+ unless File.directory?(@extension_destination_dir)
103
+ @logger.info("Creating directory: #{@extension_destination_dir}")
104
+ FileUtils.mkdir_p(@extension_destination_dir)
105
+ else
106
+ @logger.info("Notification extension directory already exists: #{@extension_destination_dir}")
107
+ end
108
+ end
109
+
110
+ def addNotificationExtensionSourceCode
111
+ unless File.exist?(@extension_code_destination_filepath)
112
+ @logger.info("Copying notification extension source code to path: #{@extension_code_destination_filepath}")
113
+ FileUtils.cp(@extension_source_name_filepath, @extension_code_destination_filepath)
114
+ filereference = getNotificationExtensionGroupReference().new_reference(@extension_code_destination_filepath)
115
+ @ne_target.add_file_references([filereference])
116
+ else
117
+ @logger.info("Notification extension source code already exists on path: #{@extension_code_destination_filepath}")
118
+ end
119
+ end
120
+
121
+ def setupDevelopmentTeam
122
+ setNotificationExtensionBuildSettings('DEVELOPMENT_TEAM', @main_target_build_settings_debug['DEVELOPMENT_TEAM'], @main_target_build_settings_release['DEVELOPMENT_TEAM'])
123
+ end
124
+
125
+ def setupDeploymentTarget
126
+ setNotificationExtensionBuildSettings('IPHONEOS_DEPLOYMENT_TARGET', "10.0")
127
+ end
128
+
129
+ def setupNotificationExtensionInfoPlist
130
+ unless File.exist?(@extension_info_plist_path)
131
+ @logger.info("Copying extension plist file to path: #{@extension_info_plist_path}")
132
+ FileUtils.cp(@plist_source_filepath, @extension_info_plist_path)
133
+ getNotificationExtensionGroupReference().new_reference(@extension_info_plist_path) #check if additional plist manipulations needed (target membership?)
134
+ else
135
+ @logger.info("Notification extension info plist already exists on path: #{@extension_info_plist_path}")
136
+ end
137
+ setNotificationExtensionBuildSettings('INFOPLIST_FILE', resolveXcodePath(@extension_info_plist_path))
138
+ end
139
+
140
+ def setupNotificationExtensionBundleId
141
+ suffix = "notification-extension"
142
+ debug_id = @main_target_build_settings_debug['PRODUCT_BUNDLE_IDENTIFIER']
143
+ release_id = @main_target_build_settings_release['PRODUCT_BUNDLE_IDENTIFIER']
144
+ setNotificationExtensionBuildSettings('PRODUCT_BUNDLE_IDENTIFIER', "#{debug_id}.#{suffix}", "#{release_id}.#{suffix}")
145
+ end
146
+
147
+ def setupMainTargetEntitlements
148
+ @logger.info("Setting up main target entitlements...")
149
+ setupEntitlements(@main_target_build_settings_debug, @main_target_build_settings_release, @main_target_name)
150
+
151
+ entitlements_path_debug = @main_target_build_settings_debug['CODE_SIGN_ENTITLEMENTS']
152
+ entitlements_path_release = @main_target_build_settings_release['CODE_SIGN_ENTITLEMENTS']
153
+ if entitlements_path_debug = entitlements_path_release
154
+ putStringValueIntoXML("aps-environment", "development", entitlements_path_debug)
155
+ else
156
+ putStringValueIntoXML("aps-environment", "development", entitlements_path_debug)
157
+ putStringValueIntoXML("aps-environment", "production", entitlements_path_release)
158
+ end
159
+ end
160
+
161
+ def setupNotificationExtensionEntitlements
162
+ @logger.info("Setting up extension entitlements...")
163
+ setupEntitlements(@extension_build_settings_debug, @extension_build_settings_release, @ne_target_name)
164
+ end
165
+
166
+ def setupAppGroupPlistValue
167
+ putStringValueIntoXML("com.mobilemessaging.app_group", @app_group, @main_target_debug_plist)
168
+ putStringValueIntoXML("com.mobilemessaging.app_group", @app_group, @main_target_release_plist)
169
+ end
170
+
171
+ def setupBackgroundModesPlistValue
172
+ putKeyArrayElement("UIBackgroundModes", "remote-notification", @main_target_debug_plist)
173
+ putKeyArrayElement("UIBackgroundModes", "remote-notification", @main_target_release_plist)
174
+ end
175
+
176
+ def setupEmbedExtensionAction
177
+ phase_name = 'Embed App Extensions'
178
+ unless @main_target.copy_files_build_phases.select { |phase| phase.name == phase_name }.first
179
+ @logger.info("Adding copy files build phase: #{phase_name}")
180
+ new_phase = @main_target.new_copy_files_build_phase(phase_name)
181
+ new_phase.dst_subfolder_spec = '13'
182
+ new_phase.add_file_reference(@ne_target.product_reference)
183
+ end
184
+ end
185
+
186
+ def setupMainTargetDependency
187
+ unless @main_target.dependency_for_target(@ne_target)
188
+ @logger.info("Adding extension target dependency for main target")
189
+ @main_target.add_dependency(@ne_target)
190
+ end
191
+ end
192
+
193
+ def setupFrameworkSearchPaths
194
+ setNotificationExtensionBuildSettings('FRAMEWORK_SEARCH_PATHS', '$SRCROOT/$PROJECT/Plugins/com-infobip-plugins-mobilemessaging')
195
+ end
196
+
197
+ def setupRunpathSearchPaths
198
+ setNotificationExtensionBuildSettings('LD_RUNPATH_SEARCH_PATHS', '@executable_path/../../Frameworks')
199
+ end
200
+
201
+ def setupSwiftVersion
202
+ setNotificationExtensionBuildSettings('SWIFT_VERSION', @swift_version)
203
+ end
204
+
205
+ def setupProductName
206
+ setNotificationExtensionBuildSettings('PRODUCT_NAME', @ne_target_name)
207
+ end
208
+
209
+ def setupLibCordovaLink
210
+ lib_cordova_name = 'libCordova.a'
211
+ unless @ne_target.frameworks_build_phase.files_references.select { |ref| ref.path == lib_cordova_name }.first
212
+ @logger.info("Adding libCordova.a to Notification Extension target...")
213
+ ref = @main_target.frameworks_build_phase.files_references.select { |ref| ref.path == lib_cordova_name }.first
214
+ if ref
215
+ @ne_target.frameworks_build_phase.add_file_reference(ref)
216
+ else
217
+ @logger.error("Main target has no libCordova.a as a linked library. Unable to add libCordova.a to Notification Extension target!")
218
+ end
219
+ else
220
+ @logger.info("Notification Extension target already has libCordova.a linked.")
221
+ end
222
+ end
223
+
224
+ def setupCopyFrameworkScript
225
+ phase_name = "Copy Frameworks"
226
+ shell_script = "/usr/local/bin/carthage copy-frameworks"
227
+ unless @main_target.shell_script_build_phases.select { |phase| phase.shell_script == shell_script }.first
228
+ @logger.info("Setting up #{phase_name} shell script for main target")
229
+ phase = @main_target.new_shell_script_build_phase(phase_name)
230
+ phase.shell_path = "/bin/sh"
231
+ phase.shell_script = shell_script
232
+ phase.input_paths << "$SRCROOT/$PROJECT/Plugins/com-infobip-plugins-mobilemessaging/MobileMessaging.framework"
233
+ phase.output_paths << "$(BUILT_PRODUCTS_DIR)/$(FRAMEWORKS_FOLDER_PATH)/MobileMessaging.framework"
234
+ else
235
+ @logger.info("Main target already has #{phase_name} shell script set up")
236
+ end
237
+ end
238
+
239
+ def setupEntitlements(_build_settings_debug, _build_settings_release, target_name)
240
+ entitlements_debug_filepath = _build_settings_debug['CODE_SIGN_ENTITLEMENTS'] != nil ? resolveAbsolutePath(_build_settings_debug['CODE_SIGN_ENTITLEMENTS']) : nil
241
+ entitlements_release_filepath = _build_settings_release['CODE_SIGN_ENTITLEMENTS'] != nil ? resolveAbsolutePath(_build_settings_release['CODE_SIGN_ENTITLEMENTS']) : nil
242
+ key = 'CODE_SIGN_ENTITLEMENTS'
243
+ if entitlements_debug_filepath == nil and entitlements_release_filepath == nil
244
+ @logger.info("\tEntitlements are not set for both release and debug schemes, setting up...")
245
+ entitlements_destination_filepath = createAppGroupEntitlements("#{target_name}.entitlements")
246
+ entitlements_destination_filepath = resolveXcodePath(entitlements_destination_filepath)
247
+
248
+ @logger.info("\tSetting build settings:\n\t\tdebug: \t#{key}\t#{entitlements_destination_filepath}\n\t\trelease:\t#{key}\t#{entitlements_destination_filepath}")
249
+
250
+ _build_settings_debug[key] = entitlements_destination_filepath
251
+ _build_settings_release[key] = entitlements_destination_filepath
252
+ else
253
+ if entitlements_debug_filepath == entitlements_release_filepath
254
+ @logger.info("\tEntitlements settings are equal for debug and release schemes.")
255
+ putAppGroupEntitlement(entitlements_debug_filepath)
256
+ else
257
+ if entitlements_debug_filepath != nil
258
+ @logger.info("\tEntitlements debug settings already set, updating settings...")
259
+ putAppGroupEntitlement(entitlements_debug_filepath)
260
+ else
261
+ @logger.info("\tEntitlements debug settings are not set, setting up...")
262
+ entitlements_destination_filepath = createAppGroupEntitlements("#{target_name}_debug.entitlements")
263
+ entitlements_destination_filepath = resolveXcodePath(entitlements_destination_filepath)
264
+
265
+ @logger.info("\tSetting build settings:\n\tdebug:\t#{key}\t#{entitlements_destination_filepath}")
266
+ _build_settings_debug[key] = entitlements_destination_filepath
267
+ end
268
+
269
+ if entitlements_release_filepath != nil
270
+ @logger.info("\tEntitlements release settings already set, updating settings...")
271
+ putAppGroupEntitlement(entitlements_release_filepath)
272
+ else
273
+ @logger.info("\tEntitlements release settings are not set, setting up...")
274
+ entitlements_destination_filepath = createAppGroupEntitlements("#{target_name}_release.entitlements")
275
+ entitlements_destination_filepath = resolveXcodePath(entitlements_destination_filepath)
276
+
277
+ @logger.info("\tSetting build settings:\n\trelease:\t#{key}\t#{entitlements_destination_filepath}")
278
+ _build_settings_release[key] = entitlements_destination_filepath
279
+ end
280
+ end
281
+ end
282
+ end
283
+
284
+ def setupExtensionTargetCapabilities
285
+ exitsting_capabilities = @project.root_object.attributes["TargetAttributes"][@ne_target.uuid]
286
+ mobilemessaging_capabilities = { "SystemCapabilities" =>
287
+ {
288
+ "com.apple.ApplicationGroups.iOS" => { "enabled" => 1 }
289
+ }
290
+ }
291
+ if exitsting_capabilities == nil
292
+ @project.root_object.attributes["TargetAttributes"][@ne_target.uuid] = mobilemessaging_capabilities
293
+ else
294
+ @project.root_object.attributes["TargetAttributes"][@ne_target.uuid] = exitsting_capabilities.merge(mobilemessaging_capabilities)
295
+ end
296
+ end
297
+
298
+ def setupMainTargetCapabilities
299
+ exitsting_capabilities = @project.root_object.attributes["TargetAttributes"][@main_target.uuid]
300
+ mobilemessaging_capabilities = { "SystemCapabilities" =>
301
+ {
302
+ "com.apple.ApplicationGroups.iOS" => { "enabled" => 1 },
303
+ "com.apple.Push" => { "enabled" => 1 },
304
+ "com.apple.BackgroundModes" => { "enabled" => 1 }
305
+ }
306
+ }
307
+ if exitsting_capabilities == nil
308
+ @project.root_object.attributes["TargetAttributes"][@main_target.uuid] = mobilemessaging_capabilities
309
+ else
310
+ @project.root_object.attributes["TargetAttributes"][@main_target.uuid] = exitsting_capabilities.merge(mobilemessaging_capabilities)
311
+ end
312
+ end
313
+
314
+ def resolveXcodePath(path)
315
+ return path.sub(@project_dir, '$(PROJECT_DIR)')
316
+ end
317
+
318
+ def setNotificationExtensionBuildSettings(key, debug_value, release_value=nil)
319
+ release_value = release_value != nil ? release_value : debug_value
320
+ @logger.info("\tSetting extension build settings:\n\t\tdebug: \t#{key}\t#{debug_value}\n\t\trelease:\t#{key}\t#{release_value}")
321
+ @extension_build_settings_debug[key] = debug_value
322
+ @extension_build_settings_release[key] = release_value
323
+ end
324
+
325
+ def getNotificationExtensionGroupReference
326
+ group_reference = @project.groups().select { |group| group.name == @extension_group_name }.first
327
+ if group_reference == nil
328
+ group_reference = @project.new_group(@extension_group_name, @extension_destination_dir)
329
+ end
330
+ return group_reference
331
+ end
332
+
333
+ def createAppGroupEntitlements(_entitlements_name)
334
+ entitlements_destination_filepath = File.join(@project_dir, _entitlements_name)
335
+ entitlements_source_filepath = File.join(Mmine.root, 'resources', "MobileMessagingNotificationExtension.entitlements")
336
+ unless File.exist?(entitlements_destination_filepath)
337
+ @logger.info("\tCopying entitlemenst file to path: #{entitlements_destination_filepath}")
338
+ FileUtils.cp(entitlements_source_filepath, entitlements_destination_filepath)
339
+ ref = @project.main_group.new_reference(entitlements_destination_filepath)
340
+ ref.last_known_file_type = "text.xml"
341
+ else
342
+ @logger.info("\tEntitlements file already exists on path: #{entitlements_destination_filepath}")
343
+ end
344
+ putAppGroupEntitlement(entitlements_destination_filepath)
345
+ return entitlements_destination_filepath
346
+ end
347
+
348
+ def resolveAbsolutePath(path)
349
+ ret = path
350
+ ["$(PROJECT_DIR)", "$PROJECT_DIR"].each do |proj_dir|
351
+ ret = ret.sub(proj_dir, @project_dir)
352
+ end
353
+
354
+ if ret.include?("$")
355
+ puts "Could not resolve absolute path for #{path}. The only supported variable are $(PROJECT_DIR) and $PROJECT_DIR. Make sure you don't misuse Xcode paths variables, consider using $(PROJECT_DIR) instead or contact Infobip Mobile Messaging support via email Push.Support@infobip.com"
356
+ exit
357
+ end
358
+
359
+ if ret == path && !ret.include?("$") # no aliases found/replaced, no aliases left in path
360
+ if path.start_with? "/"
361
+ return path # it's already an absolute path
362
+ else
363
+ return File.join(@project_dir, path) # it's a relative project path
364
+ end
365
+ end
366
+ return ret
367
+ end
368
+
369
+ def putStringValueIntoXML(key, value, plist_path)
370
+ plist_path = resolveAbsolutePath(plist_path)
371
+ @logger.info("\tConfiguring plist on path: #{plist_path}")
372
+ doc = Nokogiri::XML(IO.read(plist_path))
373
+ key_node = doc.search("//dict//key[text() = '#{key}']").first
374
+ string_value_node = Nokogiri::XML::Node.new("string",doc)
375
+ string_value_node.content = value
376
+ if key_node == nil
377
+ @logger.info("\tAdding 'key' node with content #{key}")
378
+ key_node = Nokogiri::XML::Node.new("key",doc)
379
+ key_node.content = key
380
+ doc.xpath("//dict").first.add_child(key_node)
381
+ @logger.info("\tAdding next string sibling with content #{string_value_node}")
382
+ key_node.add_next_sibling(string_value_node)
383
+ else
384
+ @logger.info("\t'Key' node with content #{key} already extists.")
385
+ existing_string_value_node = key_node.xpath("following-sibling::*").first
386
+ if existing_string_value_node.name == 'string'
387
+ @logger.info("\tUpdating following string sibling value with #{value}")
388
+ existing_string_value_node.content = value
389
+ else
390
+ @logger.info("\tAdding next string sibling with content #{string_value_node}")
391
+ key_node.add_next_sibling(string_value_node)
392
+ end
393
+ end
394
+
395
+ file = File.open(plist_path,'w')
396
+ @logger.info("\tWriting changes to plist: #{plist_path}")
397
+ file.puts Nokogiri::XML(doc.to_xml) { |x| x.noblanks }
398
+ file.close
399
+ end
400
+
401
+ def putKeyArrayElement(key, value, filepath) # check if it appends to existing array
402
+ doc = Nokogiri::XML(IO.read(filepath))
403
+ key_node = doc.search("//dict//key[text() = '#{key}']").first
404
+ string_app_group_value = Nokogiri::XML::Node.new("string",doc)
405
+ string_app_group_value.content = value
406
+ if key_node == nil
407
+ @logger.info("\tAdding 'key' node with content #{key}")
408
+ key_node = Nokogiri::XML::Node.new("key",doc)
409
+ key_node.content = key
410
+ array_node = Nokogiri::XML::Node.new("array",doc)
411
+ array_node.add_child(string_app_group_value)
412
+
413
+ doc.xpath("//dict").first.add_child(key_node)
414
+ key_node.add_next_sibling(array_node)
415
+ else
416
+ @logger.info("\t'Key' node with content #{key} already extists.")
417
+ array_node = key_node.xpath("following-sibling::*").first
418
+ if array_node.name == 'array'
419
+ @logger.info("\tFollowing array sibling already exists")
420
+ unless array_node.xpath("//string[text() = '#{value}']").first
421
+ @logger.info("\tAdding child string element with content #{value}")
422
+ array_node.add_child(string_app_group_value)
423
+ else
424
+ @logger.info("\tArray string element with content #{value} already exists")
425
+ end
426
+ else
427
+ @logger.info("\tFollowing array sibling is missing. Adding array node containing a string element.")
428
+ array_node = Nokogiri::XML::Node.new("array",doc)
429
+ array_node.add_child(string_app_group_value)
430
+ key_node.add_next_sibling(array_node)
431
+ end
432
+ end
433
+
434
+ file = File.open(filepath,'w')
435
+ @logger.info("\tWriting changes to entitlements: #{filepath}")
436
+ file.puts Nokogiri::XML(doc.to_xml) { |x| x.noblanks }
437
+ file.close
438
+ end
439
+
440
+ def putAppGroupEntitlement(filepath)
441
+ putKeyArrayElement("com.apple.security.application-groups", @app_group, filepath)
442
+ end
443
+ end
@@ -0,0 +1,3 @@
1
+ module Mmine
2
+ VERSION = "0.5.2"
3
+ end
@@ -0,0 +1,9 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>com.apple.security.application-groups</key>
6
+ <array>
7
+ </array>
8
+ </dict>
9
+ </plist>
@@ -0,0 +1,31 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3
+ <plist version="1.0">
4
+ <dict>
5
+ <key>CFBundleDevelopmentRegion</key>
6
+ <string>$(DEVELOPMENT_LANGUAGE)</string>
7
+ <key>CFBundleDisplayName</key>
8
+ <string>MobileMessagingNotificationExtension</string>
9
+ <key>CFBundleExecutable</key>
10
+ <string>$(EXECUTABLE_NAME)</string>
11
+ <key>CFBundleIdentifier</key>
12
+ <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
13
+ <key>CFBundleInfoDictionaryVersion</key>
14
+ <string>6.0</string>
15
+ <key>CFBundleName</key>
16
+ <string>$(PRODUCT_NAME)</string>
17
+ <key>CFBundlePackageType</key>
18
+ <string>XPC!</string>
19
+ <key>CFBundleShortVersionString</key>
20
+ <string>1.0</string>
21
+ <key>CFBundleVersion</key>
22
+ <string>1</string>
23
+ <key>NSExtension</key>
24
+ <dict>
25
+ <key>NSExtensionPointIdentifier</key>
26
+ <string>com.apple.usernotifications.service</string>
27
+ <key>NSExtensionPrincipalClass</key>
28
+ <string>$(PRODUCT_MODULE_NAME).NotificationService</string>
29
+ </dict>
30
+ </dict>
31
+ </plist>
@@ -0,0 +1,25 @@
1
+ // NotificationService.swift
2
+
3
+ import UserNotifications
4
+ import MobileMessaging
5
+
6
+ @available(iOS 10.0, *)
7
+ class NotificationService: UNNotificationServiceExtension {
8
+
9
+ var contentHandler: ((UNNotificationContent) -> Void)?
10
+ var originalContent: UNNotificationContent?
11
+
12
+ override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
13
+ self.contentHandler = contentHandler
14
+ self.originalContent = request.content
15
+ MobileMessagingNotificationServiceExtension.startWithApplicationCode(<# put your Application Code here #>)
16
+ MobileMessagingNotificationServiceExtension.didReceive(request, withContentHandler: contentHandler)
17
+ }
18
+
19
+ override func serviceExtensionTimeWillExpire() {
20
+ MobileMessagingNotificationServiceExtension.serviceExtensionTimeWillExpire()
21
+ if let originalContent = originalContent {
22
+ contentHandler?(originalContent)
23
+ }
24
+ }
25
+ }
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mmine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.2
5
+ platform: ruby
6
+ authors:
7
+ - Andrey Kadochnikov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-10-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: xcodeproj
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '='
18
+ - !ruby/object:Gem::Version
19
+ version: 1.6.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '='
25
+ - !ruby/object:Gem::Version
26
+ version: 1.6.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: nokogiri
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '='
32
+ - !ruby/object:Gem::Version
33
+ version: 1.8.5
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '='
39
+ - !ruby/object:Gem::Version
40
+ version: 1.8.5
41
+ description: Use this tool to automatically integrate your Xcode project with Infobips
42
+ (https://www.infobip.com) Notification Service Extension
43
+ email: andrey.kadochnikov@infobip.com
44
+ executables:
45
+ - mmine
46
+ extensions: []
47
+ extra_rdoc_files: []
48
+ files:
49
+ - bin/mmine
50
+ - lib/mmine.rb
51
+ - lib/mmine/notification_extension_integrator.rb
52
+ - lib/mmine/version.rb
53
+ - resources/MobileMessagingNotificationExtension.entitlements
54
+ - resources/MobileMessagingNotificationServiceExtension.plist
55
+ - resources/NotificationService.swift
56
+ homepage: https://github.com/infobip/mobile-messaging-mmine
57
+ licenses:
58
+ - MIT
59
+ metadata:
60
+ source_code_url: https://github.com/infobip/mobile-messaging-mmine
61
+ post_install_message:
62
+ rdoc_options: []
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ requirements:
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ requirements: []
76
+ rubyforge_project:
77
+ rubygems_version: 2.7.7
78
+ signing_key:
79
+ specification_version: 4
80
+ summary: Mobile Messaging iOS Notification Extension Integration Tool made at Infobip
81
+ (https://www.infobip.com)!!!
82
+ test_files: []