1// Copyright 2018-present 650 Industries. All rights reserved.
2
3#import "EXScopedNotificationsUtils.h"
4
5@implementation EXScopedNotificationsUtils
6
7+ (BOOL)shouldNotificationRequest:(UNNotificationRequest *)request beHandledByExperience:(NSString *)scopeKey
8{
9  NSString *notificationScopeKey = request.content.userInfo[@"experienceId"];
10  if (!notificationScopeKey) {
11    return true;
12  }
13  return [notificationScopeKey isEqual:scopeKey];
14}
15
16+ (BOOL)shouldNotification:(UNNotification *)notification beHandledByExperience:(NSString *)scopeKey
17{
18  return [EXScopedNotificationsUtils shouldNotificationRequest:notification.request beHandledByExperience:scopeKey];
19}
20
21+ (NSString *)scopedIdentifierFromId:(NSString *)unscopedId forExperience:(NSString *)scopeKey
22{
23  NSString *scope = [EXScopedNotificationsUtils escapedString:scopeKey];
24  NSString *escapedCategoryId = [EXScopedNotificationsUtils escapedString:unscopedId];
25  return [NSString stringWithFormat:@"%@/%@", scope, escapedCategoryId];
26}
27
28+ (BOOL)isId:(NSString *)identifier scopedByExperience:(NSString *)scopeKey
29{
30  NSString *scopeFromCategoryId = [EXScopedNotificationsUtils getScopeAndIdentifierFromScopedIdentifier:identifier].scopeKey;
31  return [scopeFromCategoryId isEqualToString:scopeKey];
32}
33
34+ (ScopedIdentifierComponents)getScopeAndIdentifierFromScopedIdentifier:(NSString *)scopedIdentifier
35{
36  NSString *scope = @"";
37  NSString *identifier = @"";
38  NSString *pattern = @"^"
39                       "((?:[^/\\\\]|\\\\[/\\\\])*)" // escaped scope key
40                       "/"                           // delimiter
41                       "((?:[^/\\\\]|\\\\[/\\\\])*)" // escaped original category identifier
42                       "$";
43  NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern
44                                                                         options:0
45                                                                           error:nil];
46  NSTextCheckingResult *match = [regex firstMatchInString:scopedIdentifier
47                                                  options:0
48                                                    range:NSMakeRange(0, scopedIdentifier.length)];
49  if (!match) {
50    // No delimiter found, so no scope associated with this identifier
51    identifier = scopedIdentifier;
52  } else {
53    scope = [scopedIdentifier substringWithRange:[match rangeAtIndex:1]];
54    identifier = [scopedIdentifier substringWithRange:[match rangeAtIndex:2]];
55  }
56  ScopedIdentifierComponents components;
57  components.scopeKey = [EXScopedNotificationsUtils unescapedString:scope];
58  components.identifier = [EXScopedNotificationsUtils unescapedString:identifier];
59  return components;
60}
61
62+ (NSString *)escapedString:(NSString*)string
63{
64  return [[string stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"]
65    stringByReplacingOccurrencesOfString:@"/" withString:@"\\/"];
66}
67
68+ (NSString *)unescapedString:(NSString*)string
69{
70  return [[string stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"]
71          stringByReplacingOccurrencesOfString:@"\\\\" withString:@"\\"];
72}
73
74# pragma mark Legacy notification category scoping
75
76+ (BOOL)isLegacyCategoryId:(NSString *)scopedCategoryId scopedByScopeKey:(NSString *)scopeKey
77{
78  NSString* legacyScopingPrefix = [NSString stringWithFormat:@"%@-", scopeKey];
79  return [scopedCategoryId hasPrefix:legacyScopingPrefix];
80}
81
82// legacy categories were stored under an unescaped experienceId
83+ (NSString *)unscopedLegacyCategoryIdentifierWithId:(NSString *)scopedCategoryId
84                         forScopeKey:(NSString *)scopeKey
85{
86  NSString* legacyScopingPrefix = [NSString stringWithFormat:@"%@-", scopeKey];
87  return [scopedCategoryId stringByReplacingOccurrencesOfString:legacyScopingPrefix
88                                                     withString:@""
89                                                        options:NSAnchoredSearch
90                                                          range:NSMakeRange(0, [scopedCategoryId length])];
91}
92
93@end
94