adding pods method of package managing
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBAEMAdvertiserRuleMatching.h"
|
||||
#import "FBAEMAdvertiserRuleOperator.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AEMAdvertiserMultiEntryRule)
|
||||
@interface FBAEMAdvertiserMultiEntryRule : NSObject<FBAEMAdvertiserRuleMatching, NSCopying, NSSecureCoding>
|
||||
|
||||
@property (nonatomic, readonly, assign) FBAEMAdvertiserRuleOperator operator;
|
||||
|
||||
@property (nonatomic, readonly) NSArray<id<FBAEMAdvertiserRuleMatching>> *rules;
|
||||
|
||||
- (instancetype)initWithOperator:(FBAEMAdvertiserRuleOperator)op
|
||||
rules:(NSArray<id<FBAEMAdvertiserRuleMatching>> *)rules;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,101 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBAEMAdvertiserMultiEntryRule.h"
|
||||
|
||||
#import "FBAEMAdvertiserSingleEntryRule.h"
|
||||
|
||||
static NSString *const OPERATOR_KEY = @"operator";
|
||||
static NSString *const RULES_KEY = @"rules";
|
||||
|
||||
@implementation FBAEMAdvertiserMultiEntryRule
|
||||
|
||||
- (instancetype)initWithOperator:(FBAEMAdvertiserRuleOperator)op
|
||||
rules:(NSArray<id<FBAEMAdvertiserRuleMatching>> *)rules
|
||||
{
|
||||
if (self = [super init]) {
|
||||
_operator = op;
|
||||
_rules = rules;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - FBAEMAdvertiserRuleMatching
|
||||
|
||||
- (BOOL)isMatchedEventParameters:(nullable NSDictionary<NSString *, id> *)eventParams
|
||||
{
|
||||
@try {
|
||||
BOOL isMatched = _operator == FBAEMAdvertiserRuleOperatorOr ? NO : YES;
|
||||
for (id<FBAEMAdvertiserRuleMatching> rule in _rules) {
|
||||
BOOL doesSubruleMatch = [rule isMatchedEventParameters:eventParams];
|
||||
if (_operator == FBAEMAdvertiserRuleOperatorAnd) {
|
||||
isMatched = isMatched & doesSubruleMatch;
|
||||
}
|
||||
if (_operator == FBAEMAdvertiserRuleOperatorOr) {
|
||||
isMatched = isMatched | doesSubruleMatch;
|
||||
}
|
||||
if (_operator == FBAEMAdvertiserRuleOperatorNot) {
|
||||
isMatched = isMatched & !doesSubruleMatch;
|
||||
}
|
||||
}
|
||||
return isMatched;
|
||||
} @catch (NSException *exception) {
|
||||
#if DEBUG
|
||||
#if FBTEST
|
||||
@throw exception;
|
||||
#endif
|
||||
#endif
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - NSCoding
|
||||
|
||||
+ (BOOL)supportsSecureCoding
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder
|
||||
{
|
||||
FBAEMAdvertiserRuleOperator op = [decoder decodeIntegerForKey:OPERATOR_KEY];
|
||||
NSSet *classes = [NSSet setWithArray:@[NSArray.class, FBAEMAdvertiserMultiEntryRule.class, FBAEMAdvertiserSingleEntryRule.class]];
|
||||
NSArray<id<FBAEMAdvertiserRuleMatching>> *rules = [decoder decodeObjectOfClasses:classes forKey:RULES_KEY];
|
||||
return [self initWithOperator:op rules:rules];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)encoder
|
||||
{
|
||||
[encoder encodeInteger:_operator forKey:OPERATOR_KEY];
|
||||
[encoder encodeObject:_rules forKey:RULES_KEY];
|
||||
}
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBAEMAdvertiserRuleMatching.h"
|
||||
#import "FBAEMAdvertiserRuleProviding.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AEMAdvertiserRuleFactory)
|
||||
@interface FBAEMAdvertiserRuleFactory : NSObject<FBAEMAdvertiserRuleProviding>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,184 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBAEMAdvertiserRuleFactory.h"
|
||||
|
||||
#import "FBAEMAdvertiserMultiEntryRule.h"
|
||||
#import "FBAEMAdvertiserSingleEntryRule.h"
|
||||
#import "FBCoreKitBasicsImportForAEMKit.h"
|
||||
|
||||
@implementation FBAEMAdvertiserRuleFactory
|
||||
|
||||
- (nullable id<FBAEMAdvertiserRuleMatching>)createRuleWithJson:(nullable NSString *)json
|
||||
{
|
||||
@try {
|
||||
json = [FBSDKTypeUtility stringValueOrNil:json];
|
||||
if (!json) {
|
||||
return nil;
|
||||
}
|
||||
NSDictionary<NSString *, id> *rule = [FBSDKBasicUtility objectForJSONString:json error:nil];
|
||||
return [self createRuleWithDict:rule];
|
||||
} @catch (NSException *exception) {
|
||||
NSLog(@"Fail to parse Advertiser Rules with JSON");
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (nullable id<FBAEMAdvertiserRuleMatching>)createRuleWithDict:(NSDictionary<NSString *, id> *)dict
|
||||
{
|
||||
@try {
|
||||
dict = [FBSDKTypeUtility dictionaryValue:dict];
|
||||
if (!dict) {
|
||||
return nil;
|
||||
}
|
||||
FBAEMAdvertiserRuleOperator op = [self getOperator:dict];
|
||||
if ([self isOperatorForMultiEntryRule:op]) {
|
||||
return [self createMultiEntryRuleWithDict:dict];
|
||||
} else {
|
||||
return [self createSingleEntryRuleWithDict:dict];
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
NSLog(@"Fail to parse Advertiser Rules with Dict");
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (nullable FBAEMAdvertiserMultiEntryRule *)createMultiEntryRuleWithDict:(NSDictionary<NSString *, id> *)dict
|
||||
{
|
||||
dict = [FBSDKTypeUtility dictionaryValue:dict];
|
||||
if (!dict) {
|
||||
return nil;
|
||||
}
|
||||
NSString *opString = [self primaryKeyForRule:dict];
|
||||
FBAEMAdvertiserRuleOperator operator = [self getOperator:dict];
|
||||
if (![self isOperatorForMultiEntryRule:operator]) {
|
||||
return nil;
|
||||
}
|
||||
NSArray<NSDictionary *> *subrules = [FBSDKTypeUtility dictionary:dict objectForKey:opString ofType:NSArray.class];
|
||||
NSMutableArray<id<FBAEMAdvertiserRuleMatching>> *rules = [NSMutableArray new];
|
||||
for (NSDictionary *subrule in subrules) {
|
||||
id<FBAEMAdvertiserRuleMatching> entryRule = [self createRuleWithDict:subrule];
|
||||
if (!entryRule) {
|
||||
return nil;
|
||||
}
|
||||
[FBSDKTypeUtility array:rules addObject:entryRule];
|
||||
}
|
||||
if (!rules.count) {
|
||||
return nil;
|
||||
}
|
||||
return [[FBAEMAdvertiserMultiEntryRule alloc] initWithOperator:operator rules:rules];
|
||||
}
|
||||
|
||||
- (nullable FBAEMAdvertiserSingleEntryRule *)createSingleEntryRuleWithDict:(NSDictionary<NSString *, id> *)dict
|
||||
{
|
||||
dict = [FBSDKTypeUtility dictionaryValue:dict];
|
||||
if (!dict) {
|
||||
return nil;
|
||||
}
|
||||
NSString *paramKey = [self primaryKeyForRule:dict];
|
||||
NSDictionary<NSString *, id> *rawRule = [FBSDKTypeUtility dictionary:dict objectForKey:paramKey ofType:NSDictionary.class];
|
||||
NSString *encodedOperator = [self primaryKeyForRule:rawRule];
|
||||
FBAEMAdvertiserRuleOperator operator = [self getOperator:rawRule];
|
||||
NSString *linguisticCondition = nil;
|
||||
NSNumber *numericalCondition = nil;
|
||||
NSArray *arrayCondition = nil;
|
||||
switch (operator) {
|
||||
case Unknown:
|
||||
default:
|
||||
return nil;
|
||||
case FBAEMAdvertiserRuleOperatorContains:
|
||||
case FBAEMAdvertiserRuleOperatorNotContains:
|
||||
case FBAEMAdvertiserRuleOperatorStartsWith:
|
||||
case FBAEMAdvertiserRuleOperatorI_Contains:
|
||||
case FBAEMAdvertiserRuleOperatorI_NotContains:
|
||||
case FBAEMAdvertiserRuleOperatorI_StartsWith:
|
||||
case FBAEMAdvertiserRuleOperatorRegexMatch:
|
||||
case FBAEMAdvertiserRuleOperatorEqual:
|
||||
case FBAEMAdvertiserRuleOperatorNotEqual:
|
||||
linguisticCondition = [FBSDKTypeUtility dictionary:rawRule objectForKey:encodedOperator ofType:NSString.class]; break;
|
||||
case FBAEMAdvertiserRuleOperatorLessThan:
|
||||
case FBAEMAdvertiserRuleOperatorLessThanOrEqual:
|
||||
case FBAEMAdvertiserRuleOperatorGreaterThan:
|
||||
case FBAEMAdvertiserRuleOperatorGreaterThanOrEqual:
|
||||
numericalCondition = [FBSDKTypeUtility dictionary:rawRule objectForKey:encodedOperator ofType:NSNumber.class]; break;
|
||||
case FBAEMAdvertiserRuleOperatorI_IsAny:
|
||||
case FBAEMAdvertiserRuleOperatorI_IsNotAny:
|
||||
case FBAEMAdvertiserRuleOperatorIsAny:
|
||||
case FBAEMAdvertiserRuleOperatorIsNotAny:
|
||||
arrayCondition = [FBSDKTypeUtility dictionary:rawRule objectForKey:encodedOperator ofType:NSArray.class]; break;
|
||||
}
|
||||
if (linguisticCondition || numericalCondition != nil || arrayCondition.count > 0) {
|
||||
return [[FBAEMAdvertiserSingleEntryRule alloc] initWithOperator:operator paramKey:paramKey linguisticCondition:linguisticCondition numericalCondition:numericalCondition arrayCondition:arrayCondition];
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (nullable NSString *)primaryKeyForRule:(NSDictionary<NSString *, id> *)rule
|
||||
{
|
||||
NSArray<NSString *> *keys = [rule allKeys];
|
||||
NSString *key = keys.firstObject;
|
||||
return [FBSDKTypeUtility stringValueOrNil:key];
|
||||
}
|
||||
|
||||
- (FBAEMAdvertiserRuleOperator)getOperator:(NSDictionary<NSString *, id> *)rule
|
||||
{
|
||||
NSString *key = [self primaryKeyForRule:rule];
|
||||
if (!key) {
|
||||
return Unknown;
|
||||
}
|
||||
NSArray<NSString *> *operatorKeys = @[
|
||||
@"unknown",
|
||||
@"and",
|
||||
@"or",
|
||||
@"not",
|
||||
@"contains",
|
||||
@"not_contains",
|
||||
@"starts_with",
|
||||
@"i_contains",
|
||||
@"i_not_contains",
|
||||
@"i_starts_with",
|
||||
@"regex_match",
|
||||
@"eq",
|
||||
@"neq",
|
||||
@"lt",
|
||||
@"lte",
|
||||
@"gt",
|
||||
@"gte",
|
||||
@"i_is_any",
|
||||
@"i_is_not_any",
|
||||
@"is_any",
|
||||
@"is_not_any"
|
||||
];
|
||||
NSInteger index = [operatorKeys indexOfObject:key.lowercaseString];
|
||||
return index == NSNotFound ? Unknown : index;
|
||||
}
|
||||
|
||||
- (BOOL)isOperatorForMultiEntryRule:(FBAEMAdvertiserRuleOperator)operator
|
||||
{
|
||||
return operator == FBAEMAdvertiserRuleOperatorAnd
|
||||
|| operator == FBAEMAdvertiserRuleOperatorOr
|
||||
|| operator == FBAEMAdvertiserRuleOperatorNot;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@protocol FBAEMAdvertiserRuleMatching <NSObject>
|
||||
|
||||
- (BOOL)isMatchedEventParameters:(nullable NSDictionary<NSString *, id> *)eventParams;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
typedef NS_CLOSED_ENUM(NSInteger, FBAEMAdvertiserRuleOperator)
|
||||
{
|
||||
Unknown = 0,
|
||||
// Multi Entry Rule Operator
|
||||
FBAEMAdvertiserRuleOperatorAnd,
|
||||
FBAEMAdvertiserRuleOperatorOr,
|
||||
FBAEMAdvertiserRuleOperatorNot,
|
||||
// Single Entry Rule Operator
|
||||
FBAEMAdvertiserRuleOperatorContains,
|
||||
FBAEMAdvertiserRuleOperatorNotContains,
|
||||
FBAEMAdvertiserRuleOperatorStartsWith,
|
||||
FBAEMAdvertiserRuleOperatorI_Contains,
|
||||
FBAEMAdvertiserRuleOperatorI_NotContains,
|
||||
FBAEMAdvertiserRuleOperatorI_StartsWith,
|
||||
FBAEMAdvertiserRuleOperatorRegexMatch,
|
||||
FBAEMAdvertiserRuleOperatorEqual,
|
||||
FBAEMAdvertiserRuleOperatorNotEqual,
|
||||
FBAEMAdvertiserRuleOperatorLessThan,
|
||||
FBAEMAdvertiserRuleOperatorLessThanOrEqual,
|
||||
FBAEMAdvertiserRuleOperatorGreaterThan,
|
||||
FBAEMAdvertiserRuleOperatorGreaterThanOrEqual,
|
||||
FBAEMAdvertiserRuleOperatorI_IsAny,
|
||||
FBAEMAdvertiserRuleOperatorI_IsNotAny,
|
||||
FBAEMAdvertiserRuleOperatorIsAny,
|
||||
FBAEMAdvertiserRuleOperatorIsNotAny
|
||||
} NS_SWIFT_NAME(AEMAdvertiserRuleOperator);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
/// Describes anything that can provide instances of `AEMAdvertiserRuleMatching`
|
||||
NS_SWIFT_NAME(AEMAdvertiserRuleProviding)
|
||||
@protocol FBAEMAdvertiserRuleProviding
|
||||
|
||||
- (nullable id<FBAEMAdvertiserRuleMatching>)createRuleWithJson:(nullable NSString *)json;
|
||||
|
||||
- (nullable id<FBAEMAdvertiserRuleMatching>)createRuleWithDict:(NSDictionary<NSString *, id> *)dict;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBAEMAdvertiserRuleMatching.h"
|
||||
#import "FBAEMAdvertiserRuleOperator.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AEMAdvertiserSingleEntryRule)
|
||||
@interface FBAEMAdvertiserSingleEntryRule : NSObject<FBAEMAdvertiserRuleMatching, NSCopying, NSSecureCoding>
|
||||
|
||||
@property (nonatomic, readonly, assign) FBAEMAdvertiserRuleOperator operator;
|
||||
|
||||
@property (nonatomic, readonly) NSString *paramKey;
|
||||
|
||||
@property (nullable, nonatomic, readonly) NSString *linguisticCondition;
|
||||
|
||||
@property (nullable, nonatomic, readonly) NSNumber *numericalCondition;
|
||||
|
||||
@property (nullable, nonatomic, readonly) NSArray *arrayCondition;
|
||||
|
||||
- (instancetype)initWithOperator:(FBAEMAdvertiserRuleOperator)op
|
||||
paramKey:(NSString *)paramKey
|
||||
linguisticCondition:(nullable NSString *)linguisticCondition
|
||||
numericalCondition:(nullable NSNumber *)numericalCondition
|
||||
arrayCondition:(nullable NSArray *)arrayCondition;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,267 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBAEMAdvertiserSingleEntryRule.h"
|
||||
|
||||
#import "FBCoreKitBasicsImportForAEMKit.h"
|
||||
|
||||
static NSString *const OPERATOR_KEY = @"operator";
|
||||
static NSString *const PARAMKEY_KEY = @"param_key";
|
||||
static NSString *const STRING_VALUE_KEY = @"string_value";
|
||||
static NSString *const NUMBER_VALUE_KEY = @"number_value";
|
||||
static NSString *const ARRAY_VALUE_KEY = @"array_value";
|
||||
static NSString *const PARAM_DELIMETER = @".";
|
||||
static NSString *const ASTERISK_DELIMETER = @"[*]";
|
||||
|
||||
@implementation FBAEMAdvertiserSingleEntryRule
|
||||
|
||||
- (instancetype)initWithOperator:(FBAEMAdvertiserRuleOperator)op
|
||||
paramKey:(NSString *)paramKey
|
||||
linguisticCondition:(nullable NSString *)linguisticCondition
|
||||
numericalCondition:(nullable NSNumber *)numericalCondition
|
||||
arrayCondition:(nullable NSArray *)arrayCondition
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_operator = op;
|
||||
_paramKey = paramKey;
|
||||
_linguisticCondition = linguisticCondition;
|
||||
_numericalCondition = numericalCondition;
|
||||
_arrayCondition = arrayCondition;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - FBAEMAdvertiserRuleMatching
|
||||
|
||||
- (BOOL)isMatchedEventParameters:(nullable NSDictionary<NSString *, id> *)eventParams
|
||||
{
|
||||
@try {
|
||||
NSArray<NSString *> *paramPath = [_paramKey componentsSeparatedByString:PARAM_DELIMETER];
|
||||
return [self isMatchedEventParameters:eventParams paramPath:paramPath];
|
||||
} @catch (NSException *exception) {
|
||||
#if DEBUG
|
||||
#if FBTEST
|
||||
@throw exception;
|
||||
#endif
|
||||
#endif
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isMatchedEventParameters:(nullable NSDictionary<NSString *, id> *)eventParams
|
||||
paramPath:(NSArray<NSString *> *)paramPath
|
||||
{
|
||||
eventParams = [FBSDKTypeUtility dictionaryValue:eventParams];
|
||||
if (!eventParams || !paramPath.count) {
|
||||
return NO;
|
||||
}
|
||||
NSString *param = [FBSDKTypeUtility stringValueOrNil:paramPath.firstObject];
|
||||
if ([param hasSuffix:ASTERISK_DELIMETER]) {
|
||||
return [self isMatchedWithAsteriskParam:param eventParameters:eventParams paramPath:paramPath];
|
||||
}
|
||||
// if data does not contain the key, we should return false directly.
|
||||
if (!param || ![[eventParams allKeys] containsObject:param]) {
|
||||
return NO;
|
||||
}
|
||||
// Apply operator rule if the last param is reached
|
||||
if (paramPath.count == 1) {
|
||||
NSString *stringValue = nil;
|
||||
NSNumber *numericalValue = nil;
|
||||
switch (_operator) {
|
||||
case FBAEMAdvertiserRuleOperatorContains:
|
||||
case FBAEMAdvertiserRuleOperatorNotContains:
|
||||
case FBAEMAdvertiserRuleOperatorStartsWith:
|
||||
case FBAEMAdvertiserRuleOperatorI_Contains:
|
||||
case FBAEMAdvertiserRuleOperatorI_NotContains:
|
||||
case FBAEMAdvertiserRuleOperatorI_StartsWith:
|
||||
case FBAEMAdvertiserRuleOperatorRegexMatch:
|
||||
case FBAEMAdvertiserRuleOperatorEqual:
|
||||
case FBAEMAdvertiserRuleOperatorNotEqual:
|
||||
case FBAEMAdvertiserRuleOperatorI_IsAny:
|
||||
case FBAEMAdvertiserRuleOperatorI_IsNotAny:
|
||||
case FBAEMAdvertiserRuleOperatorIsAny:
|
||||
case FBAEMAdvertiserRuleOperatorIsNotAny:
|
||||
stringValue = [FBSDKTypeUtility dictionary:eventParams objectForKey:param ofType:NSString.class]; break;
|
||||
case FBAEMAdvertiserRuleOperatorLessThan:
|
||||
case FBAEMAdvertiserRuleOperatorLessThanOrEqual:
|
||||
case FBAEMAdvertiserRuleOperatorGreaterThan:
|
||||
case FBAEMAdvertiserRuleOperatorGreaterThanOrEqual:
|
||||
numericalValue = [FBSDKTypeUtility dictionary:eventParams objectForKey:param ofType:NSNumber.class]; break;
|
||||
default: break;
|
||||
}
|
||||
return [self isMatchedWithStringValue:stringValue numericalValue:numericalValue];
|
||||
}
|
||||
NSDictionary<NSString *, id> *subParams = [FBSDKTypeUtility dictionary:eventParams objectForKey:param ofType:NSDictionary.class];
|
||||
NSRange range = NSMakeRange(1, paramPath.count - 1);
|
||||
NSArray *subParamPath = [paramPath subarrayWithRange:range];
|
||||
return [self isMatchedEventParameters:subParams paramPath:subParamPath];
|
||||
}
|
||||
|
||||
- (BOOL)isMatchedWithAsteriskParam:(NSString *)param
|
||||
eventParameters:(NSDictionary<NSString *, id> *)eventParams
|
||||
paramPath:(NSArray<NSString *> *)paramPath
|
||||
{
|
||||
param = [param substringToIndex:param.length - ASTERISK_DELIMETER.length];
|
||||
NSArray<NSDictionary *> *items = [FBSDKTypeUtility dictionary:eventParams objectForKey:param ofType:NSArray.class];
|
||||
if (!items.count || paramPath.count < 2) {
|
||||
return NO;
|
||||
}
|
||||
BOOL isMatched = NO;
|
||||
NSRange range = NSMakeRange(1, paramPath.count - 1);
|
||||
NSArray *subParamPath = [paramPath subarrayWithRange:range];
|
||||
for (NSDictionary *item in items) {
|
||||
isMatched |= [self isMatchedEventParameters:item paramPath:subParamPath];
|
||||
if (isMatched) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return isMatched;
|
||||
}
|
||||
|
||||
- (BOOL)isMatchedWithStringValue:(nullable NSString *)stringValue
|
||||
numericalValue:(nullable NSNumber *)numericalValue
|
||||
{
|
||||
BOOL isMatched = NO;
|
||||
switch (_operator) {
|
||||
case FBAEMAdvertiserRuleOperatorContains:
|
||||
isMatched = stringValue && [stringValue containsString:_linguisticCondition]; break;
|
||||
case FBAEMAdvertiserRuleOperatorNotContains:
|
||||
isMatched = !(stringValue && [stringValue containsString:_linguisticCondition]); break;
|
||||
case FBAEMAdvertiserRuleOperatorStartsWith:
|
||||
isMatched = stringValue && [stringValue hasPrefix:_linguisticCondition]; break;
|
||||
case FBAEMAdvertiserRuleOperatorI_Contains:
|
||||
isMatched = stringValue && [stringValue.lowercaseString containsString:_linguisticCondition.lowercaseString]; break;
|
||||
case FBAEMAdvertiserRuleOperatorI_NotContains:
|
||||
isMatched = !(stringValue && [stringValue.lowercaseString containsString:_linguisticCondition.lowercaseString]); break;
|
||||
case FBAEMAdvertiserRuleOperatorI_StartsWith:
|
||||
isMatched = stringValue && [stringValue.lowercaseString hasPrefix:_linguisticCondition.lowercaseString]; break;
|
||||
case FBAEMAdvertiserRuleOperatorRegexMatch:
|
||||
isMatched = stringValue && [self isRegexMatch:stringValue]; break;
|
||||
case FBAEMAdvertiserRuleOperatorEqual:
|
||||
isMatched = stringValue && [stringValue isEqualToString:_linguisticCondition]; break;
|
||||
case FBAEMAdvertiserRuleOperatorNotEqual:
|
||||
isMatched = !(stringValue && [stringValue isEqualToString:_linguisticCondition]); break;
|
||||
case FBAEMAdvertiserRuleOperatorI_IsAny:
|
||||
isMatched = stringValue && [self isAnyOf:_arrayCondition stringValue:stringValue ignoreCase:YES]; break;
|
||||
case FBAEMAdvertiserRuleOperatorI_IsNotAny:
|
||||
isMatched = !(stringValue && [self isAnyOf:_arrayCondition stringValue:stringValue ignoreCase:YES]); break;
|
||||
case FBAEMAdvertiserRuleOperatorIsAny:
|
||||
isMatched = stringValue && [self isAnyOf:_arrayCondition stringValue:stringValue ignoreCase:NO]; break;
|
||||
case FBAEMAdvertiserRuleOperatorIsNotAny:
|
||||
isMatched = !(stringValue && [self isAnyOf:_arrayCondition stringValue:stringValue ignoreCase:NO]); break;
|
||||
case FBAEMAdvertiserRuleOperatorLessThan:
|
||||
isMatched = (numericalValue != nil) && ([numericalValue compare:_numericalCondition] == NSOrderedAscending); break;
|
||||
case FBAEMAdvertiserRuleOperatorLessThanOrEqual:
|
||||
isMatched = (numericalValue != nil) && ([numericalValue compare:_numericalCondition] != NSOrderedDescending); break;
|
||||
case FBAEMAdvertiserRuleOperatorGreaterThan:
|
||||
isMatched = (numericalValue != nil) && ([numericalValue compare:_numericalCondition] == NSOrderedDescending); break;
|
||||
case FBAEMAdvertiserRuleOperatorGreaterThanOrEqual:
|
||||
isMatched = (numericalValue != nil) && ([numericalValue compare:_numericalCondition] != NSOrderedAscending); break;
|
||||
default: break;
|
||||
}
|
||||
return isMatched;
|
||||
}
|
||||
|
||||
- (BOOL)isRegexMatch:(NSString *)stringValue
|
||||
{
|
||||
if (!_linguisticCondition.length) {
|
||||
return NO;
|
||||
}
|
||||
NSError *error = nil;
|
||||
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:_linguisticCondition options:0 error:&error];
|
||||
if (!regex || error) {
|
||||
return NO;
|
||||
}
|
||||
NSRange searchedRange = NSMakeRange(0, stringValue.length);
|
||||
NSArray *matches = [regex matchesInString:stringValue options:0 range:searchedRange];
|
||||
return matches.count > 0;
|
||||
}
|
||||
|
||||
- (BOOL)isAnyOf:(NSArray<NSString *> *)arrayCondition
|
||||
stringValue:(NSString *)stringValue
|
||||
ignoreCase:(BOOL)ignoreCase
|
||||
{
|
||||
NSMutableSet<NSString *> *set = [NSMutableSet new];
|
||||
for (NSString *item in arrayCondition) {
|
||||
if (ignoreCase) {
|
||||
[set addObject:item.lowercaseString];
|
||||
} else {
|
||||
[set addObject:item];
|
||||
}
|
||||
}
|
||||
if (ignoreCase) {
|
||||
stringValue = stringValue.lowercaseString;
|
||||
}
|
||||
return [set containsObject:stringValue];
|
||||
}
|
||||
|
||||
#pragma mark - NSCoding
|
||||
|
||||
+ (BOOL)supportsSecureCoding
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder
|
||||
{
|
||||
FBAEMAdvertiserRuleOperator op = [decoder decodeIntegerForKey:OPERATOR_KEY];
|
||||
NSString *paramKey = [decoder decodeObjectOfClass:NSString.class forKey:PARAMKEY_KEY];
|
||||
NSString *linguisticCondition = [decoder decodeObjectOfClass:NSString.class forKey:STRING_VALUE_KEY];
|
||||
NSNumber *numericalCondition = [decoder decodeObjectOfClass:NSNumber.class forKey:NUMBER_VALUE_KEY];
|
||||
NSArray *arrayCondition = [decoder decodeObjectOfClass:NSArray.class forKey:ARRAY_VALUE_KEY];
|
||||
return [self initWithOperator:op
|
||||
paramKey:paramKey
|
||||
linguisticCondition:linguisticCondition
|
||||
numericalCondition:numericalCondition
|
||||
arrayCondition:arrayCondition];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)encoder
|
||||
{
|
||||
[encoder encodeInteger:_operator forKey:OPERATOR_KEY];
|
||||
[encoder encodeObject:_paramKey forKey:PARAMKEY_KEY];
|
||||
[encoder encodeObject:_linguisticCondition forKey:STRING_VALUE_KEY];
|
||||
[encoder encodeObject:_numericalCondition forKey:NUMBER_VALUE_KEY];
|
||||
[encoder encodeObject:_arrayCondition forKey:ARRAY_VALUE_KEY];
|
||||
}
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#if FBTEST
|
||||
|
||||
- (void)setOperator:(FBAEMAdvertiserRuleOperator)operator
|
||||
{
|
||||
_operator = operator;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBAEMRule.h"
|
||||
#import "FBAEMAdvertiserRuleMatching.h"
|
||||
#import "FBAEMAdvertiserRuleProviding.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AEMConfiguration)
|
||||
@interface FBAEMConfiguration : NSObject <NSCopying, NSSecureCoding>
|
||||
|
||||
@property (nonatomic, readonly, assign) NSInteger cutoffTime;
|
||||
|
||||
/** The UNIX timestamp of config's valid date and works as a unqiue identifier of the config */
|
||||
@property (nonatomic, readonly, assign) NSInteger validFrom;
|
||||
|
||||
@property (nonatomic, readonly, copy) NSString *defaultCurrency;
|
||||
|
||||
@property (nonatomic, readonly, copy) NSString *configMode;
|
||||
|
||||
@property (nullable, nonatomic, readonly, copy) NSString *businessID;
|
||||
|
||||
@property (nullable, nonatomic, readonly, copy) id<FBAEMAdvertiserRuleMatching> matchingRule;
|
||||
|
||||
@property (nonatomic, readonly) NSArray<FBAEMRule *> *conversionValueRules;
|
||||
|
||||
@property (nonatomic, readonly) NSSet<NSString *> *eventSet;
|
||||
|
||||
@property (nonatomic, readonly) NSSet<NSString *> *currencySet;
|
||||
|
||||
+ (void)configureWithRuleProvider:(id<FBAEMAdvertiserRuleProviding>)ruleProvider;
|
||||
|
||||
- (nullable instancetype)initWithJSON:(nullable NSDictionary<NSString *, id> *)dict;
|
||||
|
||||
- (BOOL)isSameValidFrom:(NSInteger)validFrom
|
||||
businessID:(nullable NSString *)businessID;
|
||||
|
||||
- (BOOL)isSameBusinessID:(nullable NSString *)businessID;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+231
@@ -0,0 +1,231 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBAEMConfiguration.h"
|
||||
|
||||
#import "FBAEMAdvertiserMultiEntryRule.h"
|
||||
#import "FBAEMAdvertiserSingleEntryRule.h"
|
||||
#import "FBCoreKitBasicsImportForAEMKit.h"
|
||||
|
||||
static NSString *const DEFAULT_CURRENCY_KEY = @"default_currency";
|
||||
static NSString *const CUTOFF_TIME_KEY = @"cutoff_time";
|
||||
static NSString *const CONVERSION_RULES_KEY = @"conversion_value_rules";
|
||||
static NSString *const VALID_FROM_KEY = @"valid_from";
|
||||
static NSString *const CONFIG_MODE_KEY = @"config_mode";
|
||||
static NSString *const CONFIG_BUSINESS_ID_KEY = @"advertiser_id";
|
||||
static NSString *const BUSINESS_ID_KEY = @"business_id";
|
||||
static NSString *const PARAM_RULE_KEY = @"param_rule";
|
||||
|
||||
static id<FBAEMAdvertiserRuleProviding> _ruleProvider;
|
||||
|
||||
@implementation FBAEMConfiguration
|
||||
|
||||
+ (void)configureWithRuleProvider:(id<FBAEMAdvertiserRuleProviding>)ruleProvider
|
||||
{
|
||||
if (self == [FBAEMConfiguration class]) {
|
||||
_ruleProvider = ruleProvider;
|
||||
}
|
||||
}
|
||||
|
||||
+ (id<FBAEMAdvertiserRuleProviding>)ruleProvider
|
||||
{
|
||||
return _ruleProvider;
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithJSON:(nullable NSDictionary<NSString *, id> *)dict
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
@try {
|
||||
dict = [FBSDKTypeUtility dictionaryValue:dict];
|
||||
if (!dict) {
|
||||
return nil;
|
||||
}
|
||||
NSString *defaultCurrency = [FBSDKTypeUtility dictionary:dict objectForKey:DEFAULT_CURRENCY_KEY ofType:NSString.class];
|
||||
NSNumber *cutoffTime = [FBSDKTypeUtility dictionary:dict objectForKey:CUTOFF_TIME_KEY ofType:NSNumber.class];
|
||||
NSNumber *validFrom = [FBSDKTypeUtility dictionary:dict objectForKey:VALID_FROM_KEY ofType:NSNumber.class];
|
||||
NSString *configMode = [FBSDKTypeUtility dictionary:dict objectForKey:CONFIG_MODE_KEY ofType:NSString.class];
|
||||
NSString *businessID = [FBSDKTypeUtility dictionary:dict objectForKey:CONFIG_BUSINESS_ID_KEY ofType:NSString.class];
|
||||
NSString *paramRuleJson = [FBSDKTypeUtility dictionary:dict objectForKey:PARAM_RULE_KEY ofType:NSString.class];
|
||||
id<FBAEMAdvertiserRuleMatching> matchingRule = [FBAEMConfiguration.ruleProvider createRuleWithJson:paramRuleJson];
|
||||
NSArray<FBAEMRule *> *rules = [FBAEMConfiguration parseRules:[FBSDKTypeUtility dictionary:dict objectForKey:CONVERSION_RULES_KEY ofType:NSArray.class]];
|
||||
if (!defaultCurrency || cutoffTime == nil || validFrom == nil || !configMode || 0 == rules.count) {
|
||||
return nil;
|
||||
}
|
||||
// Advertiser Config must have param rule
|
||||
if (businessID && !matchingRule) {
|
||||
return nil;
|
||||
}
|
||||
_defaultCurrency = defaultCurrency;
|
||||
_cutoffTime = cutoffTime.integerValue;
|
||||
_validFrom = validFrom.integerValue;
|
||||
_configMode = configMode;
|
||||
_businessID = businessID;
|
||||
_matchingRule = matchingRule;
|
||||
_conversionValueRules = rules;
|
||||
_eventSet = [FBAEMConfiguration getEventSetFromRules:_conversionValueRules];
|
||||
_currencySet = [FBAEMConfiguration getCurrencySetFromRules:_conversionValueRules];
|
||||
} @catch (NSException *exception) {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithDefaultCurrency:(NSString *)defaultCurrency
|
||||
cutoffTime:(NSInteger)cutoffTime
|
||||
validFrom:(NSInteger)validFrom
|
||||
configMode:(NSString *)configMode
|
||||
businessID:(nullable NSString *)businessID
|
||||
matchingRule:(id<FBAEMAdvertiserRuleMatching>)matchingRule
|
||||
conversionValueRules:(NSArray<FBAEMRule *> *)conversionValueRules
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_defaultCurrency = defaultCurrency;
|
||||
_cutoffTime = cutoffTime;
|
||||
_validFrom = validFrom;
|
||||
_configMode = configMode;
|
||||
_businessID = businessID;
|
||||
_matchingRule = matchingRule;
|
||||
_conversionValueRules = conversionValueRules;
|
||||
_eventSet = [FBAEMConfiguration getEventSetFromRules:_conversionValueRules];
|
||||
_currencySet = [FBAEMConfiguration getCurrencySetFromRules:_conversionValueRules];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (nullable NSArray<FBAEMRule *> *)parseRules:(nullable NSArray<NSDictionary<NSString *, id> *> *)rules
|
||||
{
|
||||
if (0 == rules.count) {
|
||||
return nil;
|
||||
}
|
||||
NSMutableArray<FBAEMRule *> *parsedRules = [NSMutableArray new];
|
||||
for (NSDictionary<NSString *, id> *ruleEntry in rules) {
|
||||
FBAEMRule *rule = [[FBAEMRule alloc] initWithJSON:ruleEntry];
|
||||
if (!rule) {
|
||||
return nil;
|
||||
}
|
||||
[FBSDKTypeUtility array:parsedRules addObject:rule];
|
||||
}
|
||||
// Sort the rules in descending priority order
|
||||
[parsedRules sortUsingComparator:^NSComparisonResult (FBAEMRule *obj1, FBAEMRule *obj2) {
|
||||
if (obj1.priority < obj2.priority) {
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
if (obj1.priority > obj2.priority) {
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
return NSOrderedSame;
|
||||
}];
|
||||
return [parsedRules copy];
|
||||
}
|
||||
|
||||
+ (NSSet<NSString *> *)getEventSetFromRules:(NSArray<FBAEMRule *> *)rules
|
||||
{
|
||||
NSMutableSet<NSString *> *eventSet = [NSMutableSet new];
|
||||
for (FBAEMRule *rule in rules) {
|
||||
if (!rule) {
|
||||
continue;
|
||||
}
|
||||
for (FBAEMEvent *event in rule.events) {
|
||||
if (event.eventName) {
|
||||
[eventSet addObject:event.eventName];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [eventSet copy];
|
||||
}
|
||||
|
||||
+ (NSSet<NSString *> *)getCurrencySetFromRules:(NSArray<FBAEMRule *> *)rules
|
||||
{
|
||||
NSMutableSet<NSString *> *currencySet = [NSMutableSet new];
|
||||
for (FBAEMRule *rule in rules) {
|
||||
if (!rule) {
|
||||
continue;
|
||||
}
|
||||
for (FBAEMEvent *event in rule.events) {
|
||||
for (NSString *currency in event.values) {
|
||||
[currencySet addObject:[currency uppercaseString]];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [currencySet copy];
|
||||
}
|
||||
|
||||
- (BOOL)isSameValidFrom:(NSInteger)validFrom
|
||||
businessID:(nullable NSString *)businessID
|
||||
{
|
||||
return (_validFrom == validFrom) && [self isSameBusinessID:businessID];
|
||||
}
|
||||
|
||||
- (BOOL)isSameBusinessID:(nullable NSString *)businessID
|
||||
{
|
||||
return (_businessID && [_businessID isEqualToString:businessID])
|
||||
|| (!_businessID && !businessID);
|
||||
}
|
||||
|
||||
#pragma mark - NSCoding
|
||||
|
||||
+ (BOOL)supportsSecureCoding
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder
|
||||
{
|
||||
NSString *defaultCurrency = [decoder decodeObjectOfClass:NSString.class forKey:DEFAULT_CURRENCY_KEY];
|
||||
NSInteger cutoffTime = [decoder decodeIntegerForKey:CUTOFF_TIME_KEY];
|
||||
NSInteger validFrom = [decoder decodeIntegerForKey:VALID_FROM_KEY];
|
||||
NSString *configMode = [decoder decodeObjectOfClass:NSString.class forKey:CONFIG_MODE_KEY];
|
||||
NSString *businessID = [decoder decodeObjectOfClass:NSString.class forKey:BUSINESS_ID_KEY];
|
||||
NSSet *matchingRuleClasses = [NSSet setWithArray:@[NSArray.class, FBAEMAdvertiserMultiEntryRule.class, FBAEMAdvertiserSingleEntryRule.class]];
|
||||
id<FBAEMAdvertiserRuleMatching> matchingRule = [decoder decodeObjectOfClasses:matchingRuleClasses forKey:PARAM_RULE_KEY];
|
||||
NSArray<FBAEMRule *> *rules = [decoder decodeObjectOfClasses:[NSSet setWithArray:@[NSArray.class, FBAEMRule.class, FBAEMEvent.class]] forKey:CONVERSION_RULES_KEY];
|
||||
return [self initWithDefaultCurrency:defaultCurrency
|
||||
cutoffTime:cutoffTime
|
||||
validFrom:validFrom
|
||||
configMode:configMode
|
||||
businessID:businessID
|
||||
matchingRule:matchingRule
|
||||
conversionValueRules:rules];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)encoder
|
||||
{
|
||||
[encoder encodeObject:_defaultCurrency forKey:DEFAULT_CURRENCY_KEY];
|
||||
[encoder encodeInteger:_cutoffTime forKey:CUTOFF_TIME_KEY];
|
||||
[encoder encodeInteger:_validFrom forKey:VALID_FROM_KEY];
|
||||
[encoder encodeObject:_configMode forKey:CONFIG_MODE_KEY];
|
||||
[encoder encodeObject:_businessID forKey:BUSINESS_ID_KEY];
|
||||
[encoder encodeObject:_matchingRule forKey:PARAM_RULE_KEY];
|
||||
[encoder encodeObject:_conversionValueRules forKey:CONVERSION_RULES_KEY];
|
||||
}
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBAEMEvent : NSObject <NSCopying, NSSecureCoding>
|
||||
|
||||
@property (nonatomic, readonly, copy) NSString *eventName;
|
||||
|
||||
@property (nullable, nonatomic, readonly, copy) NSDictionary<NSString *, NSNumber *> *values;
|
||||
|
||||
- (nullable instancetype)initWithJSON:(nullable NSDictionary<NSString *, id> *)dict;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBAEMEvent.h"
|
||||
|
||||
#import "FBCoreKitBasicsImportForAEMKit.h"
|
||||
|
||||
static NSString *const EVENT_NAME_KEY = @"event_name";
|
||||
static NSString *const VALUES_KEY = @"values";
|
||||
static NSString *const CURRENCY_KEY = @"currency";
|
||||
static NSString *const AMOUNT_KEY = @"amount";
|
||||
|
||||
@implementation FBAEMEvent
|
||||
|
||||
- (nullable instancetype)initWithJSON:(nullable NSDictionary<NSString *, id> *)dict
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
dict = [FBSDKTypeUtility dictionaryValue:dict];
|
||||
if (!dict) {
|
||||
return nil;
|
||||
}
|
||||
_eventName = [FBSDKTypeUtility dictionary:dict objectForKey:EVENT_NAME_KEY ofType:NSString.class];
|
||||
// Event name is a required field
|
||||
if (!_eventName) {
|
||||
return nil;
|
||||
}
|
||||
// Values is an optional field
|
||||
NSArray<NSDictionary<NSString *, id> *> *valueEntries = [FBSDKTypeUtility dictionary:dict objectForKey:VALUES_KEY ofType:NSArray.class];
|
||||
if (valueEntries.count > 0) {
|
||||
NSMutableDictionary<NSString *, NSNumber *> *valueDict = [NSMutableDictionary new];
|
||||
for (NSDictionary<NSString *, id> *valueEntry in valueEntries) {
|
||||
NSDictionary<NSString *, id> *value = [FBSDKTypeUtility dictionaryValue:valueEntry];
|
||||
NSString *currency = [FBSDKTypeUtility dictionary:value objectForKey:CURRENCY_KEY ofType:NSString.class];
|
||||
NSNumber *amount = [FBSDKTypeUtility dictionary:value objectForKey:AMOUNT_KEY ofType:NSNumber.class];
|
||||
if (!currency || amount == nil) {
|
||||
return nil;
|
||||
}
|
||||
[FBSDKTypeUtility dictionary:valueDict setObject:amount forKey:[currency uppercaseString]];
|
||||
}
|
||||
_values = [valueDict copy];
|
||||
}
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithEventName:(NSString *)eventName
|
||||
values:(NSDictionary<NSString *, NSNumber *> *)values
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_eventName = eventName;
|
||||
_values = values;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - NSCoding
|
||||
|
||||
+ (BOOL)supportsSecureCoding
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder
|
||||
{
|
||||
NSString *eventName = [decoder decodeObjectOfClass:NSString.class forKey:EVENT_NAME_KEY];
|
||||
NSDictionary<NSString *, NSNumber *> *values = [decoder decodeObjectOfClass:NSDictionary.class forKey:VALUES_KEY];
|
||||
return [self initWithEventName:eventName values:values];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)encoder
|
||||
{
|
||||
[encoder encodeObject:_eventName forKey:EVENT_NAME_KEY];
|
||||
if (_values) {
|
||||
[encoder encodeObject:_values forKey:VALUES_KEY];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBAEMConfiguration.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AEMInvocation)
|
||||
@interface FBAEMInvocation : NSObject <NSCopying, NSSecureCoding>
|
||||
|
||||
@property (nonatomic, readonly, copy) NSString *campaignID;
|
||||
|
||||
@property (nonatomic, readonly, copy) NSString *ACSToken;
|
||||
|
||||
@property (nullable, nonatomic, readonly, copy) NSString *ACSSharedSecret;
|
||||
|
||||
@property (nullable, nonatomic, readonly, copy) NSString *ACSConfigID;
|
||||
|
||||
@property (nullable, nonatomic, readonly, copy) NSString *businessID;
|
||||
|
||||
@property (nonatomic, readonly, assign) BOOL isTestMode;
|
||||
|
||||
@property (nonatomic, readonly, assign) BOOL hasSKAN;
|
||||
|
||||
@property (nonatomic, readonly, copy) NSDate *timestamp;
|
||||
|
||||
@property (nonatomic, readonly, copy) NSString *configMode;
|
||||
|
||||
/** The unique identifier of the config, it's the same as config's validFrom */
|
||||
@property (nonatomic, readonly, assign) NSInteger configID;
|
||||
|
||||
@property (nonatomic, readonly) NSMutableSet<NSString *> *recordedEvents;
|
||||
|
||||
@property (nonatomic, readonly) NSMutableDictionary<NSString *, NSMutableDictionary *> *recordedValues;
|
||||
|
||||
@property (nonatomic, readonly, assign) NSInteger conversionValue;
|
||||
|
||||
@property (nonatomic, readonly, assign) NSInteger priority;
|
||||
|
||||
@property (nullable, nonatomic, readonly) NSDate *conversionTimestamp;
|
||||
|
||||
@property (nonatomic, assign) BOOL isAggregated;
|
||||
|
||||
+ (nullable instancetype)invocationWithAppLinkData:(nullable NSDictionary<id, id> *)applinkData;
|
||||
|
||||
- (BOOL)attributeEvent:(NSString *)event
|
||||
currency:(nullable NSString *)currency
|
||||
value:(nullable NSNumber *)value
|
||||
parameters:(nullable NSDictionary *)parameters
|
||||
configs:(nullable NSDictionary<NSString *, NSArray<FBAEMConfiguration *> *> *)configs;
|
||||
|
||||
- (BOOL)updateConversionValueWithConfigs:(nullable NSDictionary<NSString *, NSArray<FBAEMConfiguration *> *> *)configs;
|
||||
|
||||
- (BOOL)isOutOfWindowWithConfigs:(nullable NSDictionary<NSString *, NSArray<FBAEMConfiguration *> *> *)configs;
|
||||
|
||||
- (nullable NSString *)getHMAC:(NSInteger)delay;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+477
@@ -0,0 +1,477 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBAEMInvocation.h"
|
||||
|
||||
#import <CommonCrypto/CommonHMAC.h>
|
||||
|
||||
#import "FBCoreKitBasicsImportForAEMKit.h"
|
||||
|
||||
#define SEC_IN_DAY 86400
|
||||
|
||||
static NSString *const CAMPAIGN_ID_KEY = @"campaign_ids";
|
||||
static NSString *const ACS_TOKEN_KEY = @"acs_token";
|
||||
static NSString *const ACS_SHARED_SECRET_KEY = @"shared_secret";
|
||||
static NSString *const ACS_CONFIG_ID_KEY = @"acs_config_id";
|
||||
static NSString *const BUSINESS_ID_KEY = @"advertiser_id";
|
||||
static NSString *const TEST_DEEPLINK_KEY = @"test_deeplink";
|
||||
static NSString *const TIMESTAMP_KEY = @"timestamp";
|
||||
static NSString *const CONFIG_MODE_KEY = @"config_mode";
|
||||
static NSString *const CONFIG_ID_KEY = @"config_id";
|
||||
static NSString *const RECORDED_EVENTS_KEY = @"recorded_events";
|
||||
static NSString *const RECORDED_VALUES_KEY = @"recorded_values";
|
||||
static NSString *const CONVERSION_VALUE_KEY = @"conversion_value";
|
||||
static NSString *const PRIORITY_KEY = @"priority";
|
||||
static NSString *const CONVERSION_TIMESTAMP_KEY = @"conversion_timestamp";
|
||||
static NSString *const IS_AGGREGATED_KEY = @"is_aggregated";
|
||||
static NSString *const HAS_SKAN_KEY = @"has_skan";
|
||||
|
||||
static NSString *const FB_CONTENT = @"fb_content";
|
||||
|
||||
typedef NSString *const FBAEMInvocationConfigMode;
|
||||
|
||||
FBAEMInvocationConfigMode FBAEMInvocationConfigDefaultMode = @"DEFAULT";
|
||||
FBAEMInvocationConfigMode FBAEMInvocationConfigBrandMode = @"BRAND";
|
||||
|
||||
@implementation FBAEMInvocation
|
||||
|
||||
+ (nullable instancetype)invocationWithAppLinkData:(nullable NSDictionary<id, id> *)applinkData
|
||||
{
|
||||
@try {
|
||||
applinkData = [FBSDKTypeUtility dictionaryValue:applinkData];
|
||||
if (!applinkData) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSString *campaignID = [FBSDKTypeUtility dictionary:applinkData objectForKey:CAMPAIGN_ID_KEY ofType:NSString.class];
|
||||
NSString *ACSToken = [FBSDKTypeUtility dictionary:applinkData objectForKey:ACS_TOKEN_KEY ofType:NSString.class];
|
||||
NSString *ACSSharedSecret = [FBSDKTypeUtility dictionary:applinkData objectForKey:ACS_SHARED_SECRET_KEY ofType:NSString.class];
|
||||
NSString *ACSConfigID = [FBSDKTypeUtility dictionary:applinkData objectForKey:CONFIG_ID_KEY ofType:NSString.class];
|
||||
NSString *businessID = [FBSDKTypeUtility dictionary:applinkData objectForKey:BUSINESS_ID_KEY ofType:NSString.class];
|
||||
NSNumber *isTestMode = [FBSDKTypeUtility dictionary:applinkData objectForKey:TEST_DEEPLINK_KEY ofType:NSNumber.class] ?: @NO;
|
||||
NSNumber *hasSKAN = [FBSDKTypeUtility dictionary:applinkData objectForKey:HAS_SKAN_KEY ofType:NSNumber.class] ?: @NO;
|
||||
if (campaignID == nil || ACSToken == nil) {
|
||||
return nil;
|
||||
}
|
||||
return [[FBAEMInvocation alloc] initWithCampaignID:campaignID
|
||||
ACSToken:ACSToken
|
||||
ACSSharedSecret:ACSSharedSecret
|
||||
ACSConfigID:ACSConfigID
|
||||
businessID:businessID
|
||||
isTestMode:isTestMode.boolValue
|
||||
hasSKAN:hasSKAN.boolValue];
|
||||
} @catch (NSException *exception) {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCampaignID:(NSString *)campaignID
|
||||
ACSToken:(NSString *)ACSToken
|
||||
ACSSharedSecret:(nullable NSString *)ACSSharedSecret
|
||||
ACSConfigID:(nullable NSString *)ACSConfigID
|
||||
businessID:(nullable NSString *)businessID
|
||||
isTestMode:(BOOL)isTestMode
|
||||
hasSKAN:(BOOL)hasSKAN
|
||||
{
|
||||
return [self initWithCampaignID:campaignID
|
||||
ACSToken:ACSToken
|
||||
ACSSharedSecret:ACSSharedSecret
|
||||
ACSConfigID:ACSConfigID
|
||||
businessID:businessID
|
||||
timestamp:nil
|
||||
configMode:@"DEFAULT"
|
||||
configID:-1
|
||||
recordedEvents:nil
|
||||
recordedValues:nil
|
||||
conversionValue:-1
|
||||
priority:-1
|
||||
conversionTimestamp:nil
|
||||
isAggregated:YES
|
||||
isTestMode:isTestMode
|
||||
hasSKAN:hasSKAN];
|
||||
}
|
||||
|
||||
- (nullable instancetype)initWithCampaignID:(NSString *)campaignID
|
||||
ACSToken:(NSString *)ACSToken
|
||||
ACSSharedSecret:(nullable NSString *)ACSSharedSecret
|
||||
ACSConfigID:(nullable NSString *)ACSConfigID
|
||||
businessID:(nullable NSString *)businessID
|
||||
timestamp:(nullable NSDate *)timestamp
|
||||
configMode:(NSString *)configMode
|
||||
configID:(NSInteger)configID
|
||||
recordedEvents:(nullable NSMutableSet<NSString *> *)recordedEvents
|
||||
recordedValues:(nullable NSMutableDictionary<NSString *, NSMutableDictionary *> *)recordedValues
|
||||
conversionValue:(NSInteger)conversionValue
|
||||
priority:(NSInteger)priority
|
||||
conversionTimestamp:(nullable NSDate *)conversionTimestamp
|
||||
isAggregated:(BOOL)isAggregated
|
||||
isTestMode:(BOOL)isTestMode
|
||||
hasSKAN:(BOOL)hasSKAN
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_campaignID = campaignID;
|
||||
_ACSToken = ACSToken;
|
||||
_ACSSharedSecret = ACSSharedSecret;
|
||||
_ACSConfigID = ACSConfigID;
|
||||
_businessID = businessID;
|
||||
if ([timestamp isKindOfClass:NSDate.class]) {
|
||||
_timestamp = timestamp;
|
||||
} else {
|
||||
_timestamp = [NSDate date];
|
||||
}
|
||||
_configMode = configMode;
|
||||
_configID = configID;
|
||||
if ([recordedEvents isKindOfClass:NSMutableSet.class]) {
|
||||
_recordedEvents = recordedEvents;
|
||||
} else {
|
||||
_recordedEvents = [NSMutableSet new];
|
||||
}
|
||||
if ([recordedValues isKindOfClass:NSMutableDictionary.class]) {
|
||||
_recordedValues = recordedValues;
|
||||
} else {
|
||||
_recordedValues = [NSMutableDictionary new];
|
||||
}
|
||||
_conversionValue = conversionValue;
|
||||
_priority = priority;
|
||||
_conversionTimestamp = conversionTimestamp;
|
||||
_isAggregated = isAggregated;
|
||||
_isTestMode = isTestMode;
|
||||
_hasSKAN = hasSKAN;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)attributeEvent:(NSString *)event
|
||||
currency:(nullable NSString *)currency
|
||||
value:(nullable NSNumber *)value
|
||||
parameters:(nullable NSDictionary *)parameters
|
||||
configs:(nullable NSDictionary<NSString *, NSArray<FBAEMConfiguration *> *> *)configs
|
||||
{
|
||||
FBAEMConfiguration *config = [self _findConfig:configs];
|
||||
if ([self _isOutOfWindowWithConfig:config] || ![config.eventSet containsObject:event]) {
|
||||
return NO;
|
||||
}
|
||||
// Check advertiser rule matching
|
||||
if (config.matchingRule && ![config.matchingRule isMatchedEventParameters:[self processedParameters:parameters]]) {
|
||||
return NO;
|
||||
}
|
||||
BOOL isAttributed = NO;
|
||||
if (![_recordedEvents containsObject:event]) {
|
||||
[_recordedEvents addObject:event];
|
||||
isAttributed = YES;
|
||||
}
|
||||
// Change currency to default currency if currency is not found in currencySet
|
||||
NSString *valueCurrency = [currency uppercaseString];
|
||||
if (![config.currencySet containsObject:valueCurrency]) {
|
||||
valueCurrency = config.defaultCurrency;
|
||||
}
|
||||
if (value != nil) {
|
||||
NSMutableDictionary *mapping = [[FBSDKTypeUtility dictionary:_recordedValues objectForKey:event ofType:NSDictionary.class] mutableCopy] ?: [NSMutableDictionary new];
|
||||
NSNumber *valueInMapping = [FBSDKTypeUtility dictionary:mapping objectForKey:valueCurrency ofType:NSNumber.class] ?: [NSNumber numberWithDouble:0];
|
||||
// Overwrite values when the incoming event's value is greater than the cached one
|
||||
if (value.doubleValue > valueInMapping.doubleValue) {
|
||||
[FBSDKTypeUtility dictionary:mapping setObject:[NSNumber numberWithDouble:value.doubleValue] forKey:valueCurrency];
|
||||
[FBSDKTypeUtility dictionary:_recordedValues setObject:mapping forKey:event];
|
||||
isAttributed = YES;
|
||||
}
|
||||
}
|
||||
return isAttributed;
|
||||
}
|
||||
|
||||
- (BOOL)updateConversionValueWithConfigs:(nullable NSDictionary<NSString *, NSArray<FBAEMConfiguration *> *> *)configs
|
||||
{
|
||||
FBAEMConfiguration *config = [self _findConfig:configs];
|
||||
if (!config) {
|
||||
return NO;
|
||||
}
|
||||
// Update conversion value if a rule is matched
|
||||
for (FBAEMRule *rule in config.conversionValueRules) {
|
||||
if (rule.priority <= _priority) {
|
||||
break;
|
||||
}
|
||||
if ([rule isMatchedWithRecordedEvents:_recordedEvents recordedValues:_recordedValues]) {
|
||||
_conversionValue = rule.conversionValue;
|
||||
_priority = rule.priority;
|
||||
_conversionTimestamp = [NSDate date];
|
||||
_isAggregated = NO;
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (BOOL)isOutOfWindowWithConfigs:(nullable NSDictionary<NSString *, NSArray<FBAEMConfiguration *> *> *)configs
|
||||
{
|
||||
FBAEMConfiguration *config = [self _findConfig:configs];
|
||||
return [self _isOutOfWindowWithConfig:config];
|
||||
}
|
||||
|
||||
- (nullable NSString *)getHMAC:(NSInteger)delay
|
||||
{
|
||||
if (!_ACSSharedSecret || !_ACSConfigID) {
|
||||
return nil;
|
||||
}
|
||||
@try {
|
||||
NSData *secretData = [self decodeBase64UrlSafeString:_ACSSharedSecret];
|
||||
if (!secretData) {
|
||||
return nil;
|
||||
}
|
||||
NSMutableData *hmac = [NSMutableData dataWithLength:CC_SHA512_DIGEST_LENGTH];
|
||||
NSString *text = [NSString stringWithFormat:@"%@|%@|%@|%@", _campaignID, @(_conversionValue), @(delay), @"server"];
|
||||
NSData *clearTextData = [text dataUsingEncoding:NSUTF8StringEncoding];
|
||||
CCHmac(kCCHmacAlgSHA512, [secretData bytes], [secretData length], [clearTextData bytes], [clearTextData length], hmac.mutableBytes);
|
||||
NSString *base64UrlSafeString = [hmac base64EncodedStringWithOptions:0];
|
||||
base64UrlSafeString = [base64UrlSafeString stringByReplacingOccurrencesOfString:@"/"
|
||||
withString:@"_"];
|
||||
base64UrlSafeString = [base64UrlSafeString stringByReplacingOccurrencesOfString:@"+"
|
||||
withString:@"-"];
|
||||
base64UrlSafeString = [base64UrlSafeString stringByReplacingOccurrencesOfString:@"="
|
||||
withString:@""];
|
||||
return base64UrlSafeString;
|
||||
} @catch (NSException *exception) {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable NSData *)decodeBase64UrlSafeString:(NSString *)base64UrlSafeString
|
||||
{
|
||||
if (!base64UrlSafeString.length) {
|
||||
return nil;
|
||||
}
|
||||
NSString *base64String = [base64UrlSafeString stringByReplacingOccurrencesOfString:@"-" withString:@"+"];
|
||||
base64String = [base64String stringByReplacingOccurrencesOfString:@"_" withString:@"/"];
|
||||
base64String = [base64String stringByReplacingOccurrencesOfString:@"-" withString:@"+"];
|
||||
NSString *padding = [@"" stringByPaddingToLength:(4 - base64String.length % 4) withString:@"=" startingAtIndex:0];
|
||||
base64String = [base64String stringByAppendingString:padding];
|
||||
NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:base64String options:0];
|
||||
return decodedData;
|
||||
}
|
||||
|
||||
- (nullable NSDictionary<NSString *, id> *)processedParameters:(nullable NSDictionary<NSString *, id> *)parameters
|
||||
{
|
||||
if (!parameters) {
|
||||
return parameters;
|
||||
}
|
||||
@try {
|
||||
NSMutableDictionary<NSString *, id> *result = [NSMutableDictionary dictionaryWithDictionary:parameters];
|
||||
NSString *content = [FBSDKTypeUtility dictionary:result objectForKey:FB_CONTENT ofType:NSString.class];
|
||||
if (content) {
|
||||
[FBSDKTypeUtility dictionary:result
|
||||
setObject:[FBSDKTypeUtility JSONObjectWithData:[content dataUsingEncoding:NSUTF8StringEncoding]
|
||||
options:0
|
||||
error:nil]
|
||||
forKey:FB_CONTENT];
|
||||
}
|
||||
return [result copy];
|
||||
} @catch (NSException *exception) {
|
||||
return parameters;
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)_isOutOfWindowWithConfig:(nullable FBAEMConfiguration *)config
|
||||
{
|
||||
if (!config) {
|
||||
return true;
|
||||
}
|
||||
BOOL isCutoff = [[NSDate date] timeIntervalSinceDate:_timestamp] > config.cutoffTime * SEC_IN_DAY;
|
||||
BOOL isOverLastConversionWindow = _conversionTimestamp && [[NSDate date] timeIntervalSinceDate:_conversionTimestamp] > SEC_IN_DAY;
|
||||
return isCutoff || isOverLastConversionWindow;
|
||||
}
|
||||
|
||||
- (nullable FBAEMConfiguration *)_findConfig:(nullable NSDictionary<NSString *, NSArray<FBAEMConfiguration *> *> *)configs
|
||||
{
|
||||
NSString *configMode = _businessID ? FBAEMInvocationConfigBrandMode : FBAEMInvocationConfigDefaultMode;
|
||||
NSArray<FBAEMConfiguration *> *configList = [FBSDKTypeUtility dictionary:configs objectForKey:configMode ofType:NSArray.class];
|
||||
if (0 == configList.count) {
|
||||
return nil;
|
||||
}
|
||||
if (_configID > 0) {
|
||||
for (FBAEMConfiguration *config in configList) {
|
||||
if ([config isSameValidFrom:_configID businessID:_businessID]) {
|
||||
return config;
|
||||
}
|
||||
}
|
||||
return nil;
|
||||
} else {
|
||||
FBAEMConfiguration *config = nil;
|
||||
for (FBAEMConfiguration *c in [configList reverseObjectEnumerator]) {
|
||||
if (c.validFrom <= _timestamp.timeIntervalSince1970 && [c isSameBusinessID:_businessID]) {
|
||||
config = c;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!config) {
|
||||
return nil;
|
||||
}
|
||||
[self _setConfig:config];
|
||||
return config;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_setConfig:(FBAEMConfiguration *)config
|
||||
{
|
||||
_configID = config.validFrom;
|
||||
_configMode = config.configMode;
|
||||
}
|
||||
|
||||
#pragma mark - NSCoding
|
||||
|
||||
+ (BOOL)supportsSecureCoding
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder
|
||||
{
|
||||
NSString *campaignID = [decoder decodeObjectOfClass:NSString.class forKey:CAMPAIGN_ID_KEY];
|
||||
NSString *ACSToken = [decoder decodeObjectOfClass:NSString.class forKey:ACS_TOKEN_KEY];
|
||||
NSString *ACSSharedSecret = [decoder decodeObjectOfClass:NSString.class forKey:ACS_SHARED_SECRET_KEY];
|
||||
NSString *ACSConfigID = [decoder decodeObjectOfClass:NSString.class forKey:ACS_CONFIG_ID_KEY];
|
||||
NSString *businessID = [decoder decodeObjectOfClass:NSString.class forKey:BUSINESS_ID_KEY];
|
||||
NSDate *timestamp = [decoder decodeObjectOfClass:NSDate.class forKey:TIMESTAMP_KEY];
|
||||
NSString *configMode = [decoder decodeObjectOfClass:NSString.class forKey:CONFIG_MODE_KEY];
|
||||
NSInteger configID = [decoder decodeIntegerForKey:CONFIG_ID_KEY];
|
||||
NSMutableSet<NSString *> *recordedEvents = [decoder decodeObjectOfClass:NSMutableSet.class forKey:RECORDED_EVENTS_KEY];
|
||||
NSMutableDictionary<NSString *, NSMutableDictionary *> *recordedValues = [decoder decodeObjectOfClass:NSMutableDictionary.class forKey:RECORDED_VALUES_KEY];
|
||||
NSInteger conversionValue = [decoder decodeIntegerForKey:CONVERSION_VALUE_KEY];
|
||||
NSInteger priority = [decoder decodeIntegerForKey:PRIORITY_KEY];
|
||||
NSDate *conversionTimestamp = [decoder decodeObjectOfClass:NSDate.class forKey:CONVERSION_TIMESTAMP_KEY];
|
||||
BOOL isAggregated = [decoder decodeBoolForKey:IS_AGGREGATED_KEY];
|
||||
BOOL hasSKAN = [decoder decodeBoolForKey:HAS_SKAN_KEY];
|
||||
return [self initWithCampaignID:campaignID
|
||||
ACSToken:ACSToken
|
||||
ACSSharedSecret:ACSSharedSecret
|
||||
ACSConfigID:ACSConfigID
|
||||
businessID:businessID
|
||||
timestamp:timestamp
|
||||
configMode:configMode
|
||||
configID:configID
|
||||
recordedEvents:recordedEvents
|
||||
recordedValues:recordedValues
|
||||
conversionValue:conversionValue
|
||||
priority:priority
|
||||
conversionTimestamp:conversionTimestamp
|
||||
isAggregated:isAggregated
|
||||
isTestMode:NO
|
||||
hasSKAN:hasSKAN];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)encoder
|
||||
{
|
||||
[encoder encodeObject:_campaignID forKey:CAMPAIGN_ID_KEY];
|
||||
[encoder encodeObject:_ACSToken forKey:ACS_TOKEN_KEY];
|
||||
[encoder encodeObject:_ACSSharedSecret forKey:ACS_SHARED_SECRET_KEY];
|
||||
[encoder encodeObject:_ACSConfigID forKey:ACS_CONFIG_ID_KEY];
|
||||
[encoder encodeObject:_businessID forKey:BUSINESS_ID_KEY];
|
||||
[encoder encodeObject:_timestamp forKey:TIMESTAMP_KEY];
|
||||
[encoder encodeObject:_configMode forKey:CONFIG_MODE_KEY];
|
||||
[encoder encodeInteger:_configID forKey:CONFIG_ID_KEY];
|
||||
[encoder encodeObject:_recordedEvents forKey:RECORDED_EVENTS_KEY];
|
||||
[encoder encodeObject:_recordedValues forKey:RECORDED_VALUES_KEY];
|
||||
[encoder encodeInteger:_conversionValue forKey:CONVERSION_VALUE_KEY];
|
||||
[encoder encodeInteger:_priority forKey:PRIORITY_KEY];
|
||||
[encoder encodeObject:_conversionTimestamp forKey:CONVERSION_TIMESTAMP_KEY];
|
||||
[encoder encodeBool:_isAggregated forKey:IS_AGGREGATED_KEY];
|
||||
[encoder encodeBool:_hasSKAN forKey:HAS_SKAN_KEY];
|
||||
}
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
#if FBTEST
|
||||
|
||||
- (void)setRecordedEvents:(NSMutableSet<NSString *> *)recordedEvents
|
||||
{
|
||||
_recordedEvents = recordedEvents;
|
||||
}
|
||||
|
||||
- (void)setRecordedValues:(NSMutableDictionary<NSString *, NSMutableDictionary *> *)recordedValues
|
||||
{
|
||||
_recordedValues = recordedValues;
|
||||
}
|
||||
|
||||
- (void)setPriority:(NSInteger)priority
|
||||
{
|
||||
_priority = priority;
|
||||
}
|
||||
|
||||
- (void)setConfigID:(NSInteger)configID
|
||||
{
|
||||
_configID = configID;
|
||||
}
|
||||
|
||||
- (void)setBusinessID:(NSString *_Nullable)businessID
|
||||
{
|
||||
_businessID = businessID;
|
||||
}
|
||||
|
||||
- (void)setConversionTimestamp:(NSDate *_Nonnull)conversionTimestamp
|
||||
{
|
||||
_conversionTimestamp = conversionTimestamp;
|
||||
}
|
||||
|
||||
- (void)setConversionValue:(NSInteger)conversionValue
|
||||
{
|
||||
_conversionValue = conversionValue;
|
||||
}
|
||||
|
||||
- (void)setCampaignID:(NSString *_Nonnull)campaignID
|
||||
{
|
||||
_campaignID = campaignID;
|
||||
}
|
||||
|
||||
- (void)setACSSharedSecret:(NSString *_Nullable)ACSSharedSecret
|
||||
{
|
||||
_ACSSharedSecret = ACSSharedSecret;
|
||||
}
|
||||
|
||||
- (void)setACSConfigID:(NSString *_Nullable)ACSConfigID
|
||||
{
|
||||
_ACSConfigID = ACSConfigID;
|
||||
}
|
||||
|
||||
- (void)reset
|
||||
{
|
||||
_timestamp = [NSDate date];
|
||||
_configMode = @"DEFAULT";
|
||||
_configID = -1;
|
||||
_businessID = nil;
|
||||
_recordedEvents = [NSMutableSet new];
|
||||
_recordedValues = [NSMutableDictionary new];
|
||||
_conversionValue = -1;
|
||||
_priority = -1;
|
||||
_conversionTimestamp = [NSDate date];
|
||||
_isAggregated = YES;
|
||||
_hasSKAN = NO;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#define FBAEMKit_VERSION_STRING @"11.2.1"
|
||||
#define FBSDK_DEFAULT_GRAPH_API_VERSION @"v11.0"
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FBAEMNetworking.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AEMNetworker)
|
||||
@interface FBAEMNetworker : NSObject <FBAEMNetworking, NSURLSessionDataDelegate>
|
||||
|
||||
- (void)startGraphRequestWithGraphPath:(NSString *)graphPath
|
||||
parameters:(NSDictionary *)parameters
|
||||
tokenString:(nullable NSString *)tokenString
|
||||
HTTPMethod:(nullable NSString *)method
|
||||
completion:(FBGraphRequestCompletion)completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBAEMNetworker.h"
|
||||
|
||||
#import "FBAEMKitVersions.h"
|
||||
#import "FBAEMRequestBody.h"
|
||||
#import "FBCoreKitBasicsImportForAEMKit.h"
|
||||
|
||||
#define kNewline @"\r\n"
|
||||
|
||||
static NSString *const kSDK = @"ios";
|
||||
static NSString *const kUserAgentBase = @"FBiOSAEM";
|
||||
|
||||
@implementation FBAEMNetworker
|
||||
|
||||
static NSString *const FB_GRAPH_API_ENDPOINT = @"https://graph.facebook.com/v11.0/";
|
||||
static NSString *const FB_GRAPH_API_CONTENT_TYPE = @"application/json";
|
||||
NSErrorDomain const FBAEMErrorDomain = @"com.facebook.aemkit";
|
||||
|
||||
- (void)startGraphRequestWithGraphPath:(NSString *)graphPath
|
||||
parameters:(NSDictionary *)parameters
|
||||
tokenString:(nullable NSString *)tokenString
|
||||
HTTPMethod:(nullable NSString *)method
|
||||
completion:(FBGraphRequestCompletion)completion
|
||||
{
|
||||
NSURL *url = [NSURL URLWithString:[FB_GRAPH_API_ENDPOINT stringByAppendingString:graphPath]];
|
||||
|
||||
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
|
||||
|
||||
[request setHTTPMethod:method];
|
||||
[request setValue:[self userAgent] forHTTPHeaderField:@"User-Agent"];
|
||||
[request setValue:FB_GRAPH_API_CONTENT_TYPE forHTTPHeaderField:@"Content-Type"];
|
||||
[request setHTTPShouldHandleCookies:NO];
|
||||
|
||||
// add parameters to body
|
||||
FBAEMRequestBody *body = [FBAEMRequestBody new];
|
||||
|
||||
NSMutableDictionary<NSString *, id> *params = [NSMutableDictionary dictionaryWithDictionary:parameters];
|
||||
[FBSDKTypeUtility dictionary:params setObject:@"json" forKey:@"format"];
|
||||
[FBSDKTypeUtility dictionary:params setObject:kSDK forKey:@"sdk"];
|
||||
[FBSDKTypeUtility dictionary:params setObject:@"false" forKey:@"include_headers"];
|
||||
|
||||
[self appendAttachments:params toBody:body addFormData:[method isEqual:@"POST"]];
|
||||
|
||||
if ([request.HTTPMethod isEqualToString:@"POST"]) {
|
||||
request.HTTPBody = body.compressedData;
|
||||
[request setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
|
||||
} else {
|
||||
request.HTTPBody = body.data;
|
||||
}
|
||||
|
||||
FBSDKURLSession *session = [[FBSDKURLSession alloc] initWithDelegate:self delegateQueue:[NSOperationQueue currentQueue]];
|
||||
|
||||
[session executeURLRequest:request completionHandler:^(NSData *responseData, NSURLResponse *response, NSError *error) {
|
||||
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse *)response;
|
||||
NSDictionary *result = [self parseJSONResponse:responseData error:&error statusCode:httpResponse.statusCode];
|
||||
completion(result, error);
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSDictionary *)parseJSONResponse:(NSData *)data
|
||||
error:(NSError **)error
|
||||
statusCode:(NSInteger)statusCode
|
||||
{
|
||||
NSString *responseUTF8 = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
|
||||
id response = [self parseJSONOrOtherwise:responseUTF8 error:error];
|
||||
NSDictionary *result;
|
||||
|
||||
if (responseUTF8 == nil) {
|
||||
NSString *base64Data = data.length != 0 ? [data base64EncodedStringWithOptions:0] : @"";
|
||||
if (base64Data != nil) {
|
||||
NSLog(@"fb_response_invalid_utf8");
|
||||
}
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
if ((error != NULL) && (*error == nil)) {
|
||||
*error = [[NSError alloc] initWithDomain:FBAEMErrorDomain code:statusCode userInfo:nil];
|
||||
}
|
||||
} else if ([response isKindOfClass:[NSDictionary class]]) {
|
||||
result = response;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (id)parseJSONOrOtherwise:(NSString *)unsafeString
|
||||
error:(NSError **)error
|
||||
{
|
||||
id parsed = nil;
|
||||
NSString *const utf8 = FBSDK_CAST_TO_CLASS_OR_NIL(unsafeString, NSString);
|
||||
if (!(*error) && utf8) {
|
||||
parsed = [FBSDKBasicUtility objectForJSONString:utf8 error:error];
|
||||
}
|
||||
return parsed;
|
||||
}
|
||||
|
||||
- (void)appendAttachments:(NSDictionary *)attachments
|
||||
toBody:(FBAEMRequestBody *)body
|
||||
addFormData:(BOOL)addFormData
|
||||
{
|
||||
[FBSDKTypeUtility dictionary:attachments enumerateKeysAndObjectsUsingBlock:^(id key, id value, BOOL *stop) {
|
||||
value = [FBSDKBasicUtility convertRequestValue:value];
|
||||
if ([value isKindOfClass:[NSString class]]) {
|
||||
if (addFormData) {
|
||||
[body appendWithKey:key formValue:(NSString *)value];
|
||||
}
|
||||
} else {
|
||||
NSString *msg = [NSString stringWithFormat:@"Unsupported attachment:%@, skipping.", value];
|
||||
NSLog(@"%@", msg);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSString *)userAgent
|
||||
{
|
||||
static NSString *agent = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
agent = [NSString stringWithFormat:@"%@.%@", kUserAgentBase, FBAEMKit_VERSION_STRING];
|
||||
});
|
||||
if (@available(iOS 13.0, *)) {
|
||||
SEL selector = NSSelectorFromString(@"isMacCatalystApp");
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
|
||||
if (selector && [NSProcessInfo.processInfo respondsToSelector:selector] && [NSProcessInfo.processInfo performSelector:selector]) {
|
||||
#pragma clang diagnostic pop
|
||||
return [NSString stringWithFormat:@"%@/%@", agent, @"macOS"];
|
||||
}
|
||||
}
|
||||
return agent;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+674
@@ -0,0 +1,674 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBAEMReporter.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#import "FBAEMAdvertiserRuleFactory.h"
|
||||
#import "FBAEMConfiguration.h"
|
||||
#import "FBAEMInvocation.h"
|
||||
#import "FBAEMNetworker.h"
|
||||
#import "FBCoreKitBasicsImportForAEMKit.h"
|
||||
|
||||
#define FB_AEM_CONFIG_TIME_OUT 86400
|
||||
|
||||
typedef void (^FBAEMReporterBlock)(NSError *);
|
||||
|
||||
static NSString *const BUSINESS_ID_KEY = @"advertiser_id";
|
||||
static NSString *const BUSINESS_IDS_KEY = @"advertiser_ids";
|
||||
static NSString *const AL_APPLINK_DATA_KEY = @"al_applink_data";
|
||||
static NSString *const CAMPAIGN_ID_KEY = @"campaign_id";
|
||||
static NSString *const CONVERSION_DATA_KEY = @"conversion_data";
|
||||
static NSString *const CONSUMPTION_HOUR_KEY = @"consumption_hour";
|
||||
static NSString *const TOKEN_KEY = @"token";
|
||||
static NSString *const HMAC_KEY = @"hmac";
|
||||
static NSString *const CONFIG_ID_KEY = @"config_id";
|
||||
static NSString *const DELAY_FLOW_KEY = @"delay_flow";
|
||||
|
||||
static NSString *const FBAEMConfigurationKey = @"com.facebook.sdk:FBSDKAEMConfiguration";
|
||||
static NSString *const FBAEMReporterKey = @"com.facebook.sdk:FBSDKAEMReporter";
|
||||
static NSString *const FBAEMReporterFileName = @"FBSDKAEMReportData.report";
|
||||
static NSString *const FBAEMConfigFileName = @"FBSDKAEMReportData.config";
|
||||
static NSString *const FBAEMHTTPMethodGET = @"GET";
|
||||
static NSString *const FBAEMHTTPMethodPOST = @"POST";
|
||||
|
||||
static BOOL g_isAEMReportEnabled = NO;
|
||||
static BOOL g_isLoadingConfiguration = NO;
|
||||
static dispatch_queue_t g_serialQueue;
|
||||
static NSString *g_reportFile;
|
||||
static NSString *g_configFile;
|
||||
static NSMutableDictionary<NSString *, NSMutableArray<FBAEMConfiguration *> *> *g_configs;
|
||||
static NSMutableArray<FBAEMInvocation *> *g_invocations;
|
||||
static NSDate *g_configRefreshTimestamp;
|
||||
static NSMutableArray<FBAEMReporterBlock> *g_completionBlocks;
|
||||
static _Nullable id<FBAEMNetworking> _networker = nil;
|
||||
static _Nullable id<FBSKAdNetworkReporting> _reporter = nil;
|
||||
static NSString *_appId;
|
||||
|
||||
@implementation FBAEMReporter
|
||||
|
||||
static char *const dispatchQueueLabel = "com.facebook.appevents.AEM.FBAEMReporter";
|
||||
|
||||
+ (void)configureWithNetworker:(nullable id<FBAEMNetworking>)networker
|
||||
appID:(NSString *)appID
|
||||
{
|
||||
[self configureWithNetworker:networker appID:appID reporter:nil];
|
||||
}
|
||||
|
||||
+ (void)configureWithNetworker:(nullable id<FBAEMNetworking>)networker
|
||||
appID:(NSString *)appID
|
||||
reporter:(nullable id<FBSKAdNetworkReporting>)reporter
|
||||
{
|
||||
if (self == [FBAEMReporter class]) {
|
||||
_networker = networker;
|
||||
_appId = appID;
|
||||
_reporter = reporter;
|
||||
}
|
||||
}
|
||||
|
||||
+ (id<FBAEMNetworking>)networker
|
||||
{
|
||||
return _networker;
|
||||
}
|
||||
|
||||
+ (id<FBSKAdNetworkReporting>)reporter
|
||||
{
|
||||
return _reporter;
|
||||
}
|
||||
|
||||
+ (void)enable
|
||||
{
|
||||
if (@available(iOS 14.0, *)) {
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
[FBAEMConfiguration configureWithRuleProvider:[FBAEMAdvertiserRuleFactory new]];
|
||||
g_reportFile = [FBSDKBasicUtility persistenceFilePath:FBAEMReporterFileName];
|
||||
g_configFile = [FBSDKBasicUtility persistenceFilePath:FBAEMConfigFileName];
|
||||
g_completionBlocks = [NSMutableArray new];
|
||||
if (!g_serialQueue) {
|
||||
g_serialQueue = dispatch_queue_create(dispatchQueueLabel, DISPATCH_QUEUE_SERIAL);
|
||||
}
|
||||
[self dispatchOnQueue:g_serialQueue block:^() {
|
||||
g_configs = [self _loadConfigs];
|
||||
g_invocations = [self _loadReportData];
|
||||
}];
|
||||
[self _loadConfigurationWithBlock:^(NSError *error) {
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
[self _sendAggregationRequest];
|
||||
[self _clearCache];
|
||||
}];
|
||||
// If developers forget to call configureWithNetworker:appID:
|
||||
// or pass nil for networker,
|
||||
// we use default networker in FBAEMKit
|
||||
if (!_networker) {
|
||||
_networker = [FBAEMNetworker new];
|
||||
}
|
||||
// If developers forget to call configureWithNetworker:appID:,
|
||||
// we throw warning here
|
||||
if (!_appId) {
|
||||
NSLog(@"App ID is not set up correctly, please call configureWithNetworker:appID: and pass correct FB app ID");
|
||||
return;
|
||||
}
|
||||
g_isAEMReportEnabled = YES;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)handleURL:(NSURL *)url
|
||||
{
|
||||
if (!g_isAEMReportEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
FBAEMInvocation *invocation = [self parseURL:url];
|
||||
if (!invocation) {
|
||||
return;
|
||||
}
|
||||
if (invocation.isTestMode) {
|
||||
[self _sendDebuggingRequest:invocation];
|
||||
return;
|
||||
}
|
||||
|
||||
[self _appendAndSaveInvocation:invocation];
|
||||
}
|
||||
|
||||
+ (nullable FBAEMInvocation *)parseURL:(NSURL *)url
|
||||
{
|
||||
if (!url) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSDictionary<NSString *, NSString *> *params = [FBSDKBasicUtility dictionaryWithQueryString:url.query];
|
||||
NSString *applinkDataString = params[AL_APPLINK_DATA_KEY];
|
||||
if (!applinkDataString) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
NSDictionary<id, id> *applinkData = [FBSDKTypeUtility dictionaryValue:[FBSDKBasicUtility objectForJSONString:applinkDataString error:NULL]];
|
||||
if (!applinkData) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [FBAEMInvocation invocationWithAppLinkData:applinkData];
|
||||
}
|
||||
|
||||
+ (void)recordAndUpdateEvent:(NSString *)event
|
||||
currency:(nullable NSString *)currency
|
||||
value:(nullable NSNumber *)value
|
||||
parameters:(nullable NSDictionary *)parameters
|
||||
{
|
||||
if (@available(iOS 14.0, *)) {
|
||||
if (!g_isAEMReportEnabled || 0 == event.length) {
|
||||
return;
|
||||
}
|
||||
[self _loadConfigurationWithBlock:^(NSError *error) {
|
||||
if (0 == g_configs.count || 0 == g_invocations.count) {
|
||||
return;
|
||||
}
|
||||
|
||||
FBAEMInvocation *attributedInvocation = [self _attributedInvocation:g_invocations Event:event currency:currency value:value parameters:parameters configs:g_configs];
|
||||
if (attributedInvocation) {
|
||||
if ([attributedInvocation updateConversionValueWithConfigs:g_configs]) {
|
||||
[self _sendAggregationRequest];
|
||||
}
|
||||
[self _saveReportData];
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
+ (nullable FBAEMInvocation *)_attributedInvocation:(NSArray<FBAEMInvocation *> *)invocations
|
||||
Event:(NSString *)event
|
||||
currency:(nullable NSString *)currency
|
||||
value:(nullable NSNumber *)value
|
||||
parameters:(nullable NSDictionary *)parameters
|
||||
configs:(NSDictionary<NSString *, NSMutableArray<FBAEMConfiguration *> *> *)configs
|
||||
{
|
||||
BOOL isGeneralInvocationVisited = NO;
|
||||
FBAEMInvocation *attributedInvocation = nil;
|
||||
for (FBAEMInvocation *invocation in [invocations reverseObjectEnumerator]) {
|
||||
if ([self _isDoubleCounting:invocation event:event]) {
|
||||
break;
|
||||
}
|
||||
if (!invocation.businessID && isGeneralInvocationVisited) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ([invocation attributeEvent:event currency:currency value:value parameters:parameters configs:configs]) {
|
||||
attributedInvocation = invocation;
|
||||
break;
|
||||
}
|
||||
if (!invocation.businessID) {
|
||||
isGeneralInvocationVisited = YES;
|
||||
}
|
||||
}
|
||||
return attributedInvocation;
|
||||
}
|
||||
|
||||
+ (BOOL)_isDoubleCounting:(FBAEMInvocation *)invocation
|
||||
event:(NSString *)event
|
||||
{
|
||||
// We consider it as double counting if following conditions meet simultaneously
|
||||
// 1. The field hasSKAN is true
|
||||
// 2. The conversion happens before SKAdNetwork cutoff
|
||||
// 3. The event is also being reported by SKAdNetwork
|
||||
return invocation.hasSKAN
|
||||
&& ![_reporter shouldCutoff]
|
||||
&& [_reporter isReportingEvent:event];
|
||||
}
|
||||
|
||||
+ (void)_appendAndSaveInvocation:(FBAEMInvocation *)invocation
|
||||
{
|
||||
[self dispatchOnQueue:g_serialQueue block:^() {
|
||||
[FBSDKTypeUtility array:g_invocations addObject:invocation];
|
||||
[self _saveReportData];
|
||||
}];
|
||||
}
|
||||
|
||||
+ (void)_loadConfigurationWithBlock:(FBAEMReporterBlock)block
|
||||
{
|
||||
[self dispatchOnQueue:g_serialQueue block:^() {
|
||||
[FBSDKTypeUtility array:g_completionBlocks addObject:block];
|
||||
// Executes blocks if there is cache
|
||||
if (![self _shouldRefresh]) {
|
||||
for (FBAEMReporterBlock executionBlock in g_completionBlocks) {
|
||||
executionBlock(nil);
|
||||
}
|
||||
[g_completionBlocks removeAllObjects];
|
||||
return;
|
||||
}
|
||||
if (g_isLoadingConfiguration) {
|
||||
return;
|
||||
}
|
||||
g_isLoadingConfiguration = YES;
|
||||
|
||||
[self.networker startGraphRequestWithGraphPath:[NSString stringWithFormat:@"%@/aem_conversion_configs", _appId]
|
||||
parameters:[self _requestParameters]
|
||||
tokenString:nil
|
||||
HTTPMethod:FBAEMHTTPMethodGET
|
||||
completion:^(id _Nullable result, NSError *_Nullable error) {
|
||||
[self dispatchOnQueue:g_serialQueue block:^() {
|
||||
if (error) {
|
||||
for (FBAEMReporterBlock executionBlock in g_completionBlocks) {
|
||||
executionBlock(error);
|
||||
}
|
||||
[g_completionBlocks removeAllObjects];
|
||||
g_isLoadingConfiguration = NO;
|
||||
return;
|
||||
}
|
||||
NSDictionary<NSString *, id> *json = [FBSDKTypeUtility dictionaryValue:result];
|
||||
if (json) {
|
||||
g_configRefreshTimestamp = [NSDate date];
|
||||
[self _addConfigs:[FBSDKTypeUtility dictionary:json objectForKey:@"data" ofType:NSArray.class]];
|
||||
for (FBAEMReporterBlock executionBlock in g_completionBlocks) {
|
||||
executionBlock(nil);
|
||||
}
|
||||
[g_completionBlocks removeAllObjects];
|
||||
} else {
|
||||
NSLog(@"Received invalid AEM config");
|
||||
}
|
||||
g_isLoadingConfiguration = NO;
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSDictionary<NSString *, id> *)_requestParameters
|
||||
{
|
||||
NSMutableDictionary<NSString *, id> *params = [NSMutableDictionary new];
|
||||
// append business ids to the request params
|
||||
NSMutableArray<NSString *> *businessIDs = [NSMutableArray new];
|
||||
for (FBAEMInvocation *invocation in g_invocations) {
|
||||
[FBSDKTypeUtility array:businessIDs addObject:invocation.businessID];
|
||||
}
|
||||
NSString *businessIDsString = [FBSDKBasicUtility JSONStringForObject:businessIDs error:nil invalidObjectHandler:nil];
|
||||
[FBSDKTypeUtility dictionary:params setObject:businessIDsString forKey:BUSINESS_IDS_KEY];
|
||||
return [params copy];
|
||||
}
|
||||
|
||||
+ (BOOL)_isConfigRefreshTimestampValid
|
||||
{
|
||||
return g_configRefreshTimestamp && [[NSDate date] timeIntervalSinceDate:g_configRefreshTimestamp] < FB_AEM_CONFIG_TIME_OUT;
|
||||
}
|
||||
|
||||
+ (BOOL)_shouldRefresh
|
||||
{
|
||||
// Refresh if there exists invocation which has business ID
|
||||
for (FBAEMInvocation *invocation in g_invocations) {
|
||||
if (invocation.businessID) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
// Refresh if timestamp is expired or cached config is empty
|
||||
return (![self _isConfigRefreshTimestampValid]) || (0 == g_configs.count);
|
||||
}
|
||||
|
||||
#pragma mark - Deeplink debugging methods
|
||||
|
||||
+ (void)_sendDebuggingRequest:(FBAEMInvocation *)invocation
|
||||
{
|
||||
NSMutableArray<NSDictionary *> *params = [NSMutableArray new];
|
||||
[FBSDKTypeUtility array:params addObject:[self _debuggingRequestParameters:invocation]];
|
||||
if (0 == params.count) {
|
||||
return;
|
||||
}
|
||||
@try {
|
||||
NSData *jsonData = [FBSDKTypeUtility dataWithJSONObject:params options:0 error:nil];
|
||||
if (jsonData) {
|
||||
NSString *reports = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
|
||||
[self.networker startGraphRequestWithGraphPath:[NSString stringWithFormat:@"%@/aem_conversions", _appId]
|
||||
parameters:@{@"aem_conversions" : reports}
|
||||
tokenString:nil
|
||||
HTTPMethod:FBAEMHTTPMethodPOST
|
||||
completion:^(id _Nullable result, NSError *_Nullable error) {
|
||||
if (error) {
|
||||
NSLog(@"Fail to send AEM debugging request with error: %@", error);
|
||||
}
|
||||
}];
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
NSLog(@"Fail to send AEM debugging request");
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSDictionary<NSString *, id> *)_debuggingRequestParameters:(FBAEMInvocation *)invocation
|
||||
{
|
||||
NSMutableDictionary<NSString *, id> *conversionParams = [NSMutableDictionary new];
|
||||
[FBSDKTypeUtility dictionary:conversionParams setObject:invocation.campaignID forKey:CAMPAIGN_ID_KEY];
|
||||
[FBSDKTypeUtility dictionary:conversionParams setObject:@(0) forKey:CONVERSION_DATA_KEY];
|
||||
[FBSDKTypeUtility dictionary:conversionParams setObject:@(0) forKey:CONSUMPTION_HOUR_KEY];
|
||||
[FBSDKTypeUtility dictionary:conversionParams setObject:invocation.ACSToken forKey:TOKEN_KEY];
|
||||
[FBSDKTypeUtility dictionary:conversionParams setObject:@"server" forKey:DELAY_FLOW_KEY];
|
||||
|
||||
return [conversionParams copy];
|
||||
}
|
||||
|
||||
#pragma mark - Background methods
|
||||
|
||||
+ (NSMutableDictionary<NSString *, NSMutableArray<FBAEMConfiguration *> *> *)_loadConfigs
|
||||
{
|
||||
if (@available(iOS 11.0, *)) {
|
||||
NSData *cachedConfig = [NSData dataWithContentsOfFile:g_configFile options:NSDataReadingMappedIfSafe error:nil];
|
||||
if ([cachedConfig isKindOfClass:NSData.class]) {
|
||||
NSSet *classes = [NSSet setWithArray:@[
|
||||
NSMutableDictionary.class,
|
||||
NSMutableArray.class,
|
||||
FBAEMConfiguration.class,
|
||||
FBAEMRule.class,
|
||||
FBAEMEvent.class]];
|
||||
NSDictionary<NSString *, NSMutableArray<FBAEMConfiguration *> *> *cache = [FBSDKTypeUtility dictionaryValue:[NSKeyedUnarchiver unarchivedObjectOfClasses:classes fromData:cachedConfig error:nil]];
|
||||
if (cache) {
|
||||
return [cache mutableCopy];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [NSMutableDictionary new];
|
||||
}
|
||||
|
||||
+ (void)_saveConfigs
|
||||
{
|
||||
if (!g_configs) {
|
||||
return;
|
||||
}
|
||||
if (@available(iOS 11.0, *)) {
|
||||
NSData *cache = [NSKeyedArchiver archivedDataWithRootObject:g_configs requiringSecureCoding:NO error:nil];
|
||||
if (cache && g_configFile) {
|
||||
[cache writeToFile:g_configFile atomically:YES];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)_addConfigs:(nullable NSArray<NSDictionary *> *)configs
|
||||
{
|
||||
if (0 == configs.count) {
|
||||
return;
|
||||
}
|
||||
for (NSDictionary *config in configs) {
|
||||
[self _addConfig:[[FBAEMConfiguration alloc] initWithJSON:config]];
|
||||
}
|
||||
[self _saveConfigs];
|
||||
}
|
||||
|
||||
+ (void)_addConfig:(nullable FBAEMConfiguration *)config
|
||||
{
|
||||
if (!config.configMode) {
|
||||
return;
|
||||
}
|
||||
NSMutableArray<FBAEMConfiguration *> *configs = [FBSDKTypeUtility dictionary:g_configs objectForKey:config.configMode ofType:NSMutableArray.class];
|
||||
// Remove the config in the array that has the same "validFrom" and "businessID" as the added config
|
||||
NSMutableArray<FBAEMConfiguration *> *res = [NSMutableArray new];
|
||||
for (FBAEMConfiguration *c in configs) {
|
||||
if ([config isSameValidFrom:c.validFrom businessID:c.businessID]) {
|
||||
continue;
|
||||
}
|
||||
[FBSDKTypeUtility array:res addObject:c];
|
||||
}
|
||||
[FBSDKTypeUtility array:res addObject:config];
|
||||
[FBSDKTypeUtility dictionary:g_configs setObject:res forKey:config.configMode];
|
||||
// Sort the configs via "validFrom"
|
||||
[res sortUsingComparator:^NSComparisonResult (FBAEMConfiguration *obj1, FBAEMConfiguration *obj2) {
|
||||
if (obj1.validFrom > obj2.validFrom) {
|
||||
return NSOrderedDescending;
|
||||
}
|
||||
if (obj1.validFrom < obj2.validFrom) {
|
||||
return NSOrderedAscending;
|
||||
}
|
||||
return NSOrderedSame;
|
||||
}];
|
||||
}
|
||||
|
||||
+ (NSMutableArray<FBAEMInvocation *> *)_loadReportData
|
||||
{
|
||||
if (@available(iOS 11.0, *)) {
|
||||
NSData *cachedReportData = [NSData dataWithContentsOfFile:g_reportFile options:NSDataReadingMappedIfSafe error:nil];
|
||||
if ([cachedReportData isKindOfClass:NSData.class]) {
|
||||
NSArray<FBAEMInvocation *> *cache = [FBSDKTypeUtility arrayValue:[NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithArray:@[NSArray.class, FBAEMInvocation.class]] fromData:cachedReportData error:nil]];
|
||||
if (cache) {
|
||||
return [cache mutableCopy];
|
||||
}
|
||||
}
|
||||
}
|
||||
return [NSMutableArray new];
|
||||
}
|
||||
|
||||
+ (void)_saveReportData
|
||||
{
|
||||
if (@available(iOS 11.0, *)) {
|
||||
NSData *cache = [NSKeyedArchiver archivedDataWithRootObject:g_invocations requiringSecureCoding:NO error:nil];
|
||||
if (cache && g_reportFile) {
|
||||
[cache writeToFile:g_reportFile atomically:YES];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)_sendAggregationRequest
|
||||
{
|
||||
NSMutableArray<NSDictionary *> *params = [NSMutableArray new];
|
||||
NSMutableArray<FBAEMInvocation *> *aggregatedInvocations = [NSMutableArray new];
|
||||
for (FBAEMInvocation *invocation in g_invocations) {
|
||||
if (!invocation.isAggregated) {
|
||||
[FBSDKTypeUtility array:params addObject:[self _aggregationRequestParameters:invocation]];
|
||||
[FBSDKTypeUtility array:aggregatedInvocations addObject:invocation];
|
||||
}
|
||||
}
|
||||
if (0 == params.count) {
|
||||
return;
|
||||
}
|
||||
@try {
|
||||
NSData *jsonData = [FBSDKTypeUtility dataWithJSONObject:params options:0 error:nil];
|
||||
if (jsonData) {
|
||||
NSString *reports = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
|
||||
|
||||
[self.networker startGraphRequestWithGraphPath:[NSString stringWithFormat:@"%@/aem_conversions", _appId]
|
||||
parameters:@{@"aem_conversions" : reports}
|
||||
tokenString:nil
|
||||
HTTPMethod:FBAEMHTTPMethodPOST
|
||||
completion:^(id _Nullable result, NSError *_Nullable error) {
|
||||
if (error) {
|
||||
return;
|
||||
}
|
||||
|
||||
[self dispatchOnQueue:g_serialQueue block:^() {
|
||||
for (FBAEMInvocation *invocation in aggregatedInvocations) {
|
||||
invocation.isAggregated = YES;
|
||||
}
|
||||
[self _saveReportData];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
} @catch (NSException *exception) {
|
||||
NSLog(@"Fail to send AEM reports");
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSDictionary<NSString *, id> *)_aggregationRequestParameters:(FBAEMInvocation *)invocation
|
||||
{
|
||||
NSInteger delay = 24 + arc4random_uniform(24);
|
||||
NSMutableDictionary<NSString *, id> *conversionParams = [NSMutableDictionary new];
|
||||
[FBSDKTypeUtility dictionary:conversionParams setObject:invocation.campaignID forKey:CAMPAIGN_ID_KEY];
|
||||
[FBSDKTypeUtility dictionary:conversionParams setObject:@(invocation.conversionValue) forKey:CONVERSION_DATA_KEY];
|
||||
[FBSDKTypeUtility dictionary:conversionParams setObject:@(delay) forKey:CONSUMPTION_HOUR_KEY];
|
||||
[FBSDKTypeUtility dictionary:conversionParams setObject:invocation.ACSToken forKey:TOKEN_KEY];
|
||||
[FBSDKTypeUtility dictionary:conversionParams setObject:@"server" forKey:DELAY_FLOW_KEY];
|
||||
[FBSDKTypeUtility dictionary:conversionParams setObject:invocation.ACSConfigID forKey:CONFIG_ID_KEY];
|
||||
[FBSDKTypeUtility dictionary:conversionParams setObject:[invocation getHMAC:delay] forKey:HMAC_KEY];
|
||||
[FBSDKTypeUtility dictionary:conversionParams setObject:invocation.businessID forKey:BUSINESS_ID_KEY];
|
||||
|
||||
return [conversionParams copy];
|
||||
}
|
||||
|
||||
+ (void)dispatchOnQueue:(dispatch_queue_t)queue block:(dispatch_block_t)block
|
||||
{
|
||||
if (block != nil) {
|
||||
if (strcmp(dispatch_queue_get_label(queue), dispatchQueueLabel) == 0) {
|
||||
dispatch_async(queue, block);
|
||||
} else {
|
||||
block();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)_clearCache
|
||||
{
|
||||
// step 1: clear aggregated invocations that are outside attribution window
|
||||
[self _clearInvocations];
|
||||
// step 2: clear old configs that are not used anymore and keep the most recent config
|
||||
[self _clearConfigs];
|
||||
}
|
||||
|
||||
+ (void)_clearConfigs
|
||||
{
|
||||
BOOL shouldSaveCache = NO;
|
||||
if (g_configs.count > 0) {
|
||||
NSMutableDictionary<NSString *, NSMutableArray<FBAEMConfiguration *> *> *configs = [NSMutableDictionary new];
|
||||
for (NSString *key in g_configs) {
|
||||
NSMutableArray<FBAEMConfiguration *> *oldConfigurations = [FBSDKTypeUtility dictionary:g_configs objectForKey:key ofType:NSMutableArray.class];
|
||||
NSMutableArray<FBAEMConfiguration *> *newConfigurations = [NSMutableArray new];
|
||||
|
||||
// Removes the last of the old configurations and stores it so it can be
|
||||
// added to the array-to-save
|
||||
FBAEMConfiguration *lastConfiguration = oldConfigurations.lastObject;
|
||||
[oldConfigurations removeLastObject];
|
||||
|
||||
for (FBAEMConfiguration *oldConfiguration in oldConfigurations) {
|
||||
if (![self _isUsingConfig:oldConfiguration forInvocations:g_invocations]) {
|
||||
shouldSaveCache = YES;
|
||||
continue;
|
||||
}
|
||||
[FBSDKTypeUtility array:newConfigurations addObject:oldConfiguration];
|
||||
}
|
||||
|
||||
[FBSDKTypeUtility array:newConfigurations addObject:lastConfiguration];
|
||||
[FBSDKTypeUtility dictionary:configs setObject:newConfigurations forKey:key];
|
||||
}
|
||||
g_configs = configs;
|
||||
}
|
||||
if (shouldSaveCache) {
|
||||
[self _saveConfigs];
|
||||
}
|
||||
}
|
||||
|
||||
+ (void)_clearInvocations
|
||||
{
|
||||
BOOL isInvocationCacheUpdated = NO;
|
||||
if (g_invocations.count > 0) {
|
||||
NSMutableArray<FBAEMInvocation *> *res = [NSMutableArray new];
|
||||
for (FBAEMInvocation *invocation in g_invocations) {
|
||||
if ([invocation isOutOfWindowWithConfigs:g_configs] && invocation.isAggregated) {
|
||||
isInvocationCacheUpdated = YES;
|
||||
continue;
|
||||
}
|
||||
[FBSDKTypeUtility array:res addObject:invocation];
|
||||
}
|
||||
g_invocations = res;
|
||||
}
|
||||
if (isInvocationCacheUpdated) {
|
||||
[self _saveReportData];
|
||||
}
|
||||
}
|
||||
|
||||
+ (BOOL)_isUsingConfig:(FBAEMConfiguration *)config
|
||||
forInvocations:(NSArray<FBAEMInvocation *> *)invocations
|
||||
{
|
||||
for (FBAEMInvocation *invocation in invocations) {
|
||||
if ([config isSameValidFrom:invocation.configID businessID:invocation.businessID]) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
#pragma mark - Testability
|
||||
|
||||
#if DEBUG
|
||||
#if FBTEST
|
||||
|
||||
+ (NSMutableDictionary<NSString *, NSMutableArray<FBAEMConfiguration *> *> *)configs
|
||||
{
|
||||
return g_configs;
|
||||
}
|
||||
|
||||
+ (void)setConfigs:(NSMutableDictionary<NSString *, NSMutableArray<FBAEMConfiguration *> *> *)configs
|
||||
{
|
||||
g_configs = configs;
|
||||
}
|
||||
|
||||
+ (void)setInvocations:(NSMutableArray<FBAEMInvocation *> *)invocations
|
||||
{
|
||||
g_invocations = invocations;
|
||||
}
|
||||
|
||||
+ (NSMutableArray<FBAEMInvocation *> *)invocations
|
||||
{
|
||||
return g_invocations;
|
||||
}
|
||||
|
||||
+ (void)setIsEnabled:(BOOL)enabled
|
||||
{
|
||||
g_isAEMReportEnabled = enabled;
|
||||
}
|
||||
|
||||
+ (BOOL)isEnabled
|
||||
{
|
||||
return g_isAEMReportEnabled;
|
||||
}
|
||||
|
||||
+ (void)setCompletionBlocks:(NSMutableArray<FBAEMReporterBlock> *)completionBlocks
|
||||
{
|
||||
g_completionBlocks = completionBlocks;
|
||||
}
|
||||
|
||||
+ (void)setQueue:(nullable dispatch_queue_t)queue
|
||||
{
|
||||
g_serialQueue = queue;
|
||||
}
|
||||
|
||||
+ (void)setTimestamp:(NSDate *)timestamp
|
||||
{
|
||||
g_configRefreshTimestamp = timestamp;
|
||||
}
|
||||
|
||||
+ (void)setIsLoadingConfiguration:(BOOL)loading
|
||||
{
|
||||
g_isLoadingConfiguration = loading;
|
||||
}
|
||||
|
||||
+ (NSString *)reportFilePath
|
||||
{
|
||||
return g_reportFile;
|
||||
}
|
||||
|
||||
+ (void)setReportFilePath:(NSString *)path
|
||||
{
|
||||
g_reportFile = path;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_SWIFT_NAME(RequestBody)
|
||||
@interface FBAEMRequestBody : NSObject
|
||||
|
||||
@property (nonatomic, retain, readonly) NSData *data;
|
||||
|
||||
- (void)appendWithKey:(NSString *)key
|
||||
formValue:(NSString *)value;
|
||||
|
||||
- (NSData *)compressedData;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+116
@@ -0,0 +1,116 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBAEMRequestBody.h"
|
||||
|
||||
#import "FBCoreKitBasicsImportForAEMKit.h"
|
||||
|
||||
#define kNewline @"\r\n"
|
||||
|
||||
typedef void (^AEMCodeBlock)(void);
|
||||
|
||||
@implementation FBAEMRequestBody
|
||||
{
|
||||
NSMutableData *_data;
|
||||
NSMutableDictionary *_json;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_data = [NSMutableData new];
|
||||
_json = [NSMutableDictionary dictionary];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)appendUTF8:(NSString *)utf8
|
||||
{
|
||||
if (!_data.length) {
|
||||
NSString *headerUTF8 = [NSString stringWithFormat:@"--%@", kNewline];
|
||||
NSData *headerData = [headerUTF8 dataUsingEncoding:NSUTF8StringEncoding];
|
||||
[_data appendData:headerData];
|
||||
}
|
||||
NSData *data = [utf8 dataUsingEncoding:NSUTF8StringEncoding];
|
||||
[_data appendData:data];
|
||||
}
|
||||
|
||||
- (void)appendWithKey:(NSString *)key
|
||||
formValue:(NSString *)value
|
||||
{
|
||||
[self _appendWithKey:key filename:nil contentType:nil contentBlock:^{
|
||||
[self appendUTF8:value];
|
||||
}];
|
||||
if (key && value) {
|
||||
[FBSDKTypeUtility dictionary:_json setObject:value forKey:key];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSData *)data
|
||||
{
|
||||
NSData *jsonData;
|
||||
if (_json.allKeys.count > 0) {
|
||||
jsonData = [FBSDKTypeUtility dataWithJSONObject:_json options:0 error:nil];
|
||||
} else {
|
||||
jsonData = [NSData data];
|
||||
}
|
||||
|
||||
return jsonData;
|
||||
}
|
||||
|
||||
- (void)_appendWithKey:(NSString *)key
|
||||
filename:(NSString *)filename
|
||||
contentType:(NSString *)contentType
|
||||
contentBlock:(AEMCodeBlock)contentBlock
|
||||
{
|
||||
NSMutableArray *disposition = [NSMutableArray new];
|
||||
[FBSDKTypeUtility array:disposition addObject:@"Content-Disposition: form-data"];
|
||||
if (key) {
|
||||
[FBSDKTypeUtility array:disposition addObject:[[NSString alloc] initWithFormat:@"name=\"%@\"", key]];
|
||||
}
|
||||
if (filename) {
|
||||
[FBSDKTypeUtility array:disposition addObject:[[NSString alloc] initWithFormat:@"filename=\"%@\"", filename]];
|
||||
}
|
||||
[self appendUTF8:[[NSString alloc] initWithFormat:@"%@%@", [disposition componentsJoinedByString:@"; "], kNewline]];
|
||||
if (contentType) {
|
||||
[self appendUTF8:[[NSString alloc] initWithFormat:@"Content-Type: %@%@", contentType, kNewline]];
|
||||
}
|
||||
[self appendUTF8:kNewline];
|
||||
if (contentBlock != NULL) {
|
||||
contentBlock();
|
||||
}
|
||||
[self appendUTF8:[[NSString alloc] initWithFormat:@"%@", kNewline]];
|
||||
}
|
||||
|
||||
- (NSData *)compressedData
|
||||
{
|
||||
if (!self.data.length) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
return [FBSDKBasicUtility gzip:self.data];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "FBAEMEvent.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface FBAEMRule : NSObject <NSCopying, NSSecureCoding>
|
||||
|
||||
@property (nonatomic) NSInteger conversionValue;
|
||||
|
||||
@property (nonatomic) NSInteger priority;
|
||||
|
||||
@property (nonatomic, copy) NSArray<FBAEMEvent *> *events;
|
||||
|
||||
- (nullable instancetype)initWithJSON:(nullable NSDictionary<NSString *, id> *)dict;
|
||||
|
||||
- (BOOL)isMatchedWithRecordedEvents:(nullable NSSet<NSString *> *)recordedEvents
|
||||
recordedValues:(nullable NSDictionary<NSString *, NSDictionary *> *)recordedValues;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBAEMRule.h"
|
||||
|
||||
#import "FBCoreKitBasicsImportForAEMKit.h"
|
||||
|
||||
static NSString *const CONVERSION_VALUE_KEY = @"conversion_value";
|
||||
static NSString *const PRIORITY_KEY = @"priority";
|
||||
static NSString *const EVENTS_KEY = @"events";
|
||||
|
||||
@implementation FBAEMRule
|
||||
|
||||
- (nullable instancetype)initWithJSON:(nullable NSDictionary<NSString *, id> *)dict
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
dict = [FBSDKTypeUtility dictionaryValue:dict];
|
||||
if (!dict) {
|
||||
return nil;
|
||||
}
|
||||
NSNumber *conversionValue = [FBSDKTypeUtility dictionary:dict objectForKey:CONVERSION_VALUE_KEY ofType:NSNumber.class];
|
||||
NSNumber *priority = [FBSDKTypeUtility dictionary:dict objectForKey:PRIORITY_KEY ofType:NSNumber.class];
|
||||
NSArray<FBAEMEvent *> *events = [FBAEMRule parseEvents:[FBSDKTypeUtility dictionary:dict objectForKey:EVENTS_KEY ofType:NSArray.class]];
|
||||
if (conversionValue == nil || priority == nil || 0 == events.count) {
|
||||
return nil;
|
||||
}
|
||||
_conversionValue = conversionValue.integerValue;
|
||||
_priority = priority.integerValue;
|
||||
_events = events;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithConversionValue:(NSInteger)conversionValue
|
||||
priority:(NSInteger)priority
|
||||
events:(NSArray<FBAEMEvent *> *)events
|
||||
{
|
||||
if ((self = [super init])) {
|
||||
_conversionValue = conversionValue;
|
||||
_priority = priority;
|
||||
_events = events;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (BOOL)isMatchedWithRecordedEvents:(nullable NSSet<NSString *> *)recordedEvents
|
||||
recordedValues:(nullable NSDictionary<NSString *, NSDictionary *> *)recordedValues
|
||||
{
|
||||
for (FBAEMEvent *event in self.events) {
|
||||
// Check if event name matches
|
||||
if (![recordedEvents containsObject:event.eventName]) {
|
||||
return NO;
|
||||
}
|
||||
// Check if event value matches when values is not nil
|
||||
if (event.values) {
|
||||
NSDictionary<NSString *, NSNumber *> *recordedEventValues = [FBSDKTypeUtility dictionary:recordedValues objectForKey:event.eventName ofType:NSDictionary.class];
|
||||
if (![self _isMatchedWithValues:event.values recordedEventValues:recordedEventValues]) {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)_isMatchedWithValues:(NSDictionary<NSString *, NSNumber *> *)values
|
||||
recordedEventValues:(nullable NSDictionary<NSString *, NSNumber *> *)recordedEventValues
|
||||
{
|
||||
for (NSString *currency in values) {
|
||||
NSNumber *valueInMapping = [FBSDKTypeUtility dictionary:values objectForKey:currency ofType:NSNumber.class];
|
||||
NSNumber *value = [FBSDKTypeUtility dictionary:recordedEventValues objectForKey:currency ofType:NSNumber.class];
|
||||
if (value.doubleValue >= valueInMapping.doubleValue) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (nullable NSArray<FBAEMEvent *> *)parseEvents:(nullable NSArray<NSDictionary<NSString *, id> *> *)events
|
||||
{
|
||||
if (0 == events.count) {
|
||||
return nil;
|
||||
}
|
||||
NSMutableArray<FBAEMEvent *> *parsedEvents = [NSMutableArray new];
|
||||
for (NSDictionary<NSString *, id> *eventEntry in events) {
|
||||
FBAEMEvent *event = [[FBAEMEvent alloc] initWithJSON:eventEntry];
|
||||
if (!event) {
|
||||
return nil;
|
||||
}
|
||||
[FBSDKTypeUtility array:parsedEvents addObject:event];
|
||||
}
|
||||
return [parsedEvents copy];
|
||||
}
|
||||
|
||||
#pragma mark - NSCoding
|
||||
|
||||
+ (BOOL)supportsSecureCoding
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (instancetype)initWithCoder:(NSCoder *)decoder
|
||||
{
|
||||
NSInteger conversionValue = [decoder decodeIntegerForKey:CONVERSION_VALUE_KEY];
|
||||
NSInteger priority = [decoder decodeIntegerForKey:PRIORITY_KEY];
|
||||
NSArray<FBAEMEvent *> *events = [decoder decodeObjectOfClasses:[NSSet setWithArray:@[NSArray.class, FBAEMEvent.class]] forKey:EVENTS_KEY];
|
||||
return [self initWithConversionValue:conversionValue priority:priority events:events];
|
||||
}
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)encoder
|
||||
{
|
||||
[encoder encodeInteger:_conversionValue forKey:CONVERSION_VALUE_KEY];
|
||||
[encoder encodeInteger:_priority forKey:PRIORITY_KEY];
|
||||
[encoder encodeObject:_events forKey:EVENTS_KEY];
|
||||
}
|
||||
|
||||
#pragma mark - NSCopying
|
||||
|
||||
- (instancetype)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// TODO: This needs to be renamed once BUCK does not include CoreKit Internal Headers
|
||||
|
||||
#if defined FBSDK_SWIFT_PACKAGE
|
||||
@import FBSDKCoreKit_Basics;
|
||||
#else
|
||||
#import <FBSDKCoreKit_Basics/FBSDKCoreKit_Basics.h>
|
||||
#endif
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
// This deserves some explanation.
|
||||
// Cocoapods - we define FBAEMKit as a subspec so to import it we need to use
|
||||
// the name of the module produced by the podspec which is FBSDKCoreKit. To be able
|
||||
// to reference it as <FBAEMKit> we need to publish a separate pod.
|
||||
// Because of the way files in the subspec are made available to the pod, we do not need
|
||||
// to use the bracket import syntax.
|
||||
//
|
||||
// BUCK - we define FBAEMKit as a separate library so we must import it as
|
||||
// <FBAEMKit>
|
||||
//
|
||||
// Xcodeproj - we define FBAEMKit as a distinct module with its own project
|
||||
// so that we can import it as <FBAEMKit>
|
||||
//
|
||||
// Swift Package Manager - it can be imported with `@import FBAEMKit` which allows us to reference
|
||||
// public headers without bracket import syntax.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import "FBAEMNetworking.h"
|
||||
#import "FBAEMReporter.h"
|
||||
#import "FBSKAdNetworkReporting.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
typedef void (^FBGraphRequestCompletion)(id _Nullable result, NSError *_Nullable error);
|
||||
|
||||
NS_SWIFT_NAME(AEMNetworking)
|
||||
@protocol FBAEMNetworking
|
||||
|
||||
- (void)startGraphRequestWithGraphPath:(NSString *)graphPath
|
||||
parameters:(NSDictionary *)parameters
|
||||
tokenString:(nullable NSString *)tokenString
|
||||
HTTPMethod:(nullable NSString *)method
|
||||
completion:(FBGraphRequestCompletion)completion;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "FBAEMNetworking.h"
|
||||
#import "FBSKAdNetworkReporting.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(AEMReporter)
|
||||
@interface FBAEMReporter : NSObject
|
||||
|
||||
/**
|
||||
|
||||
Configure networker used for calling Facebook AEM Graph API endpoint
|
||||
and Facebook App ID
|
||||
|
||||
This function should be called in application(_:open:options:) from ApplicationDelegate
|
||||
and BEFORE [FBAEMReporter enable] function
|
||||
|
||||
@param networker An optional networker conforms to FBAEMNetworking which handles Graph API request
|
||||
@param appID The Facebook app ID
|
||||
*/
|
||||
+ (void)configureWithNetworker:(nullable id<FBAEMNetworking>)networker
|
||||
appID:(NSString *)appID;
|
||||
|
||||
/**
|
||||
|
||||
Configure networker used for calling Facebook AEM Graph API endpoint
|
||||
and Facebook App ID
|
||||
|
||||
This function should be called in application(_:open:options:) from ApplicationDelegate
|
||||
and BEFORE [FBAEMReporter enable] function. We will use SKAdNetwork reporter to prevent
|
||||
double counting.
|
||||
|
||||
@param networker An optional networker conforms to FBAEMNetworking which handles Graph API request
|
||||
@param appID The Facebook app ID
|
||||
@param reporter The SKAdNetwork repoter
|
||||
*/
|
||||
+ (void)configureWithNetworker:(nullable id<FBAEMNetworking>)networker
|
||||
appID:(NSString *)appID
|
||||
reporter:(nullable id<FBSKAdNetworkReporting>)reporter;
|
||||
|
||||
/**
|
||||
|
||||
Enable AEM reporting
|
||||
|
||||
This function should be called in application(_:open:options:) from ApplicationDelegate
|
||||
*/
|
||||
+ (void)enable;
|
||||
|
||||
/**
|
||||
|
||||
Handle deeplink
|
||||
|
||||
This function should be called in application(_:open:options:) from ApplicationDelegate
|
||||
*/
|
||||
+ (void)handleURL:(NSURL *)url;
|
||||
|
||||
/**
|
||||
|
||||
Calculate the conversion value for the app event based on the AEM configuration
|
||||
|
||||
This function should be called when you log any in-app events
|
||||
*/
|
||||
+ (void)recordAndUpdateEvent:(NSString *)event
|
||||
currency:(nullable NSString *)currency
|
||||
value:(nullable NSNumber *)value
|
||||
parameters:(nullable NSDictionary *)parameters
|
||||
NS_SWIFT_NAME(recordAndUpdate(event:currency:value:parameters:));
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
// Copyright (c) 2014-present, Facebook, Inc. All rights reserved.
|
||||
//
|
||||
// You are hereby granted a non-exclusive, worldwide, royalty-free license to use,
|
||||
// copy, modify, and distribute this software in source code or binary form for use
|
||||
// in connection with the web services and APIs provided by Facebook.
|
||||
//
|
||||
// As with any software that integrates with the Facebook platform, your use of
|
||||
// this software is subject to the Facebook Developer Principles and Policies
|
||||
// [http://developers.facebook.com/policy/]. This copyright notice shall be
|
||||
// included in all copies or substantial portions of the software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
|
||||
#import "TargetConditionals.h"
|
||||
|
||||
#if !TARGET_OS_TV
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
NS_SWIFT_NAME(SKAdNetworkReporting)
|
||||
@protocol FBSKAdNetworkReporting
|
||||
|
||||
- (BOOL)shouldCutoff;
|
||||
|
||||
- (BOOL)isReportingEvent:(NSString *)event;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user