Skip to content

Commit

Permalink
Merge pull request #8 from adibendahan/feature/evaluate_message_resul…
Browse files Browse the repository at this point in the history
…t_reason

1.2.0
  • Loading branch information
adibendahan authored Apr 27, 2022
2 parents b88b62b + c7633f5 commit 0b4fee8
Show file tree
Hide file tree
Showing 17 changed files with 214 additions and 92 deletions.
2 changes: 1 addition & 1 deletion Message Filter Extension/MessageFilterExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,6 @@ extension MessageFilterExtension: ILMessageFilterQueryHandling {
let body = queryRequest.messageBody ?? ""
let sender = queryRequest.sender ?? ""

return self.extensionManager.evaluateMessage(body: body, sender: sender)
return self.extensionManager.evaluateMessage(body: body, sender: sender).action
}
}
18 changes: 9 additions & 9 deletions Simply Filter SMS.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -867,7 +867,7 @@
CODE_SIGN_ENTITLEMENTS = "Simply Filter SMS/Resources/Simply Filter SMS.entitlements";
CODE_SIGN_IDENTITY = "iPhone Developer";
CODE_SIGN_STYLE = Manual;
CURRENT_PROJECT_VERSION = 202204121903;
CURRENT_PROJECT_VERSION = 202204271814;
DEVELOPMENT_ASSET_PATHS = "\"Simply Filter SMS/Resources/Preview Content\"";
DEVELOPMENT_TEAM = AL28LDR9PU;
ENABLE_PREVIEWS = YES;
Expand All @@ -883,10 +883,10 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1.1;
MARKETING_VERSION = 1.2.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.grizz.apps.dev.Simply-Filter-SMS";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "Development - Offline 2";
PROVISIONING_PROFILE_SPECIFIER = "May 22: Simply Filter SMS - Dev";
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
Expand All @@ -902,7 +902,7 @@
CODE_SIGN_ENTITLEMENTS = "Simply Filter SMS/Resources/Simply Filter SMS.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 202204121903;
CURRENT_PROJECT_VERSION = 202204271814;
DEVELOPMENT_ASSET_PATHS = "\"Simply Filter SMS/Resources/Preview Content\"";
DEVELOPMENT_TEAM = AL28LDR9PU;
ENABLE_PREVIEWS = YES;
Expand All @@ -918,7 +918,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.1.1;
MARKETING_VERSION = 1.2.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.grizz.apps.dev.Simply-Filter-SMS";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
Expand All @@ -933,7 +933,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "Message Filter Extension/Simply Filter SMS Extension.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 202204121903;
CURRENT_PROJECT_VERSION = 202204271814;
DEVELOPMENT_TEAM = AL28LDR9PU;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Message Filter Extension/Info.plist";
Expand All @@ -944,7 +944,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.1.1;
MARKETING_VERSION = 1.2.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.grizz.apps.dev.Simply-Filter-SMS.Simply-Filter-SMS-Extension";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
Expand All @@ -959,7 +959,7 @@
buildSettings = {
CODE_SIGN_ENTITLEMENTS = "Message Filter Extension/Simply Filter SMS Extension.entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 202204121903;
CURRENT_PROJECT_VERSION = 202204271814;
DEVELOPMENT_TEAM = AL28LDR9PU;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "Message Filter Extension/Info.plist";
Expand All @@ -970,7 +970,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 1.1.1;
MARKETING_VERSION = 1.2.0;
PRODUCT_BUNDLE_IDENTIFIER = "com.grizz.apps.dev.Simply-Filter-SMS.Simply-Filter-SMS-Extension";
PRODUCT_NAME = "$(TARGET_NAME)";
SKIP_INSTALL = YES;
Expand Down
22 changes: 19 additions & 3 deletions Simply Filter SMS/Framework Layer/Managers/AppManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,27 @@ class AppManager: AppManagerProtocol {
self.messageEvaluationManager = messageEvaluationManager
self.networkSyncManager = networkSyncManager
self.amazonS3Service = amazonS3Service
}

func onAppLaunch() {
let _ = self.defaultsManager.appAge // make sure it's initialized

let isOnline = networkSyncManager.networkStatus == .online
if let sessionAge = self.defaultsManager.sessionAge {
if sessionAge.daysBetween(date: Date()) != 0 {
self.onNewUserSession()
}
}
else {
self.onNewUserSession()
}
}

func onNewUserSession() {
self.defaultsManager.sessionCounter += 1
self.defaultsManager.sessionAge = Date()

if !inMemory && isOnline {
automaticFilterManager.updateAutomaticFiltersIfNeeded()
if self.networkSyncManager.networkStatus == .online {
self.automaticFilterManager.updateAutomaticFiltersIfNeeded()
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,52 +46,53 @@ class MessageEvaluationManager: MessageEvaluationManagerProtocol {
}

//MARK: Public API (MessageEvaluationManagerProtocol)
func evaluateMessage(body: String, sender: String) -> ILMessageFilterAction {
var action = ILMessageFilterAction.none
func evaluateMessage(body: String, sender: String) -> MessageEvaluationResult {

var result = MessageEvaluationResult(action: .none)

// Priority #1 - Allow
action = self.runUserFilters(type: .allow, body: body, sender: sender)
guard !action.isFiltered else { return action }
result = self.runUserFilters(type: .allow, body: body, sender: sender)
guard !result.action.isFiltered else { return result }

// Priority #2 - Deny
action = self.runUserFilters(type: .deny, body: body, sender: sender)
guard !action.isFiltered else { return action }
result = self.runUserFilters(type: .deny, body: body, sender: sender)
guard !result.action.isFiltered else { return result }

// Priority #3 - Deny Language
action = self.runUserFilters(type: .denyLanguage, body: body, sender: sender)
guard !action.isFiltered else { return action }
result = self.runUserFilters(type: .denyLanguage, body: body, sender: sender)
guard !result.action.isFiltered else { return result }

// Priority #4 - Automatic Filtering
action = self.runAutomaticFilters(body: body, sender: sender)
guard !action.isFiltered else { return action }
result = self.runAutomaticFilters(body: body, sender: sender)
guard !result.action.isFiltered else { return result }

// Priority #5 - Rules
action = self.runFilterRules(body: body, sender: sender)
result = self.runFilterRules(body: body, sender: sender)

if !action.isFiltered {
action = .allow
if !result.action.isFiltered {
result = MessageEvaluationResult(action: .allow, reason: "testFilters_resultReason_noMatch"~)
}

return action
return result
}

func setLogger(_ logger: Logger) {
self.logger = logger
}

//MARK: - Private -
private var logger: Logger?
private var persistentContainer: NSPersistentContainer?
private(set) var context: NSManagedObjectContext

private func runUserFilters(type: FilterType, body: String, sender: String) -> ILMessageFilterAction {
var action = ILMessageFilterAction.none
private func runUserFilters(type: FilterType, body: String, sender: String) -> MessageEvaluationResult {
var result = MessageEvaluationResult(action: .none)
let fetchRequest = NSFetchRequest<NSManagedObject>(entityName: "Filter")
fetchRequest.predicate = NSPredicate(format: "type == %ld", type.rawValue)

guard let filters = try? self.context.fetch(fetchRequest) else {
self.logger?.error("ERROR! While loading filters on MessageEvaluationManager.runUserFilters")
return action
return result
}

switch type {
Expand All @@ -100,7 +101,7 @@ class MessageEvaluationManager: MessageEvaluationManagerProtocol {
guard let filter = filter as? Filter,
self.isMataching(filter: filter, body: body, sender: sender) else { continue }

action = .allow
result = MessageEvaluationResult(action: .allow, reason: filter.text)
break
}

Expand All @@ -109,7 +110,7 @@ class MessageEvaluationManager: MessageEvaluationManagerProtocol {
guard let filter = filter as? Filter,
self.isMataching(filter: filter, body: body, sender: sender) else { continue }

action = filter.denyFolderType.action
result = MessageEvaluationResult(action: filter.denyFolderType.action, reason: filter.text)
break
}

Expand All @@ -122,17 +123,17 @@ class MessageEvaluationManager: MessageEvaluationManagerProtocol {
if language != .undetermined,
NLLanguage.dominantLanguage(for: body) == language {

action = filter.denyFolderType.action
result = MessageEvaluationResult(action: filter.denyFolderType.action, reason: language.localizedName)
break
}
}
}

return action
return result
}

private func runAutomaticFilters(body: String, sender: String) -> ILMessageFilterAction {
var action = ILMessageFilterAction.none
private func runAutomaticFilters(body: String, sender: String) -> MessageEvaluationResult {
var result = MessageEvaluationResult(action: .none)
let lowercasedBody = body.lowercased()
let lowercasedSender = sender.lowercased()
let languageRequest: NSFetchRequest<AutomaticFiltersLanguage> = AutomaticFiltersLanguage.fetchRequest()
Expand All @@ -144,100 +145,108 @@ class MessageEvaluationManager: MessageEvaluationManagerProtocol {
let automaticFilterList = AutomaticFilterListsResponse(base64String: filtersData) else {

self.logger?.error("ERROR! While loading cache on MessageEvaluationManager.runAutomaticFilters")
return action
return result
}

for automaticFiltersLanguageRecord in automaticFiltersLanguageRecords {
guard action == .none else { break }
guard result.action == .none else { break }

if automaticFiltersLanguageRecord.isActive,
let langRawValue = automaticFiltersLanguageRecord.lang,
let languageResponse = automaticFilterList.filterLists[langRawValue] {

let lang = NLLanguage(rawValue: langRawValue)

for allowedSender in languageResponse.allowSenders {
if lowercasedSender == allowedSender.lowercased() {
action = .allow
result = MessageEvaluationResult(action: .allow, reason: "\("autoFilter_title"~) (\(lang.localizedName ?? langRawValue))")
break
}
}

guard !action.isFiltered else { break }
guard !result.action.isFiltered else { break }

for allowedBody in languageResponse.allowBody {
if lowercasedBody.contains(allowedBody.lowercased()) {
action = .allow
result = MessageEvaluationResult(action: .allow, reason: "\("autoFilter_title"~) (\(lang.localizedName ?? langRawValue))")
break
}
}

guard !action.isFiltered else { break }
guard !result.action.isFiltered else { break }

for deniedSender in languageResponse.denySender {
if lowercasedSender == deniedSender.lowercased() {
action = .junk
result = MessageEvaluationResult(action: .junk, reason: "\("autoFilter_title"~) (\(lang.localizedName ?? langRawValue))")
break
}
}

guard !action.isFiltered else { break }
guard !result.action.isFiltered else { break }

for deniedBody in languageResponse.denyBody {
if lowercasedBody.contains(deniedBody.lowercased()) {
action = .junk
result = MessageEvaluationResult(action: .junk, reason: "\("autoFilter_title"~) (\(lang.localizedName ?? langRawValue))")
break
}
}
}
}

return action
return result
}

private func runFilterRules(body: String, sender: String) -> ILMessageFilterAction {
var action = ILMessageFilterAction.none
private func runFilterRules(body: String, sender: String) -> MessageEvaluationResult {
var result = MessageEvaluationResult(action: .none)
let ruleRequest: NSFetchRequest<AutomaticFiltersRule> = AutomaticFiltersRule.fetchRequest()
ruleRequest.predicate = NSPredicate(format: "isActive == %@", NSNumber(value: true))

guard let activeAutomaticFiltersRuleRecords = try? self.context.fetch(ruleRequest) else {
self.logger?.error("ERROR! While loading rules on MessageEvaluationManager.runFilterRules")
return action
return result
}

for activeRule in activeAutomaticFiltersRuleRecords {
if let ruleType = activeRule.ruleType {
switch ruleType {
case .allUnknown:
action = .junk
result = MessageEvaluationResult(action: .junk, reason: "testFilters_resultReason_unknownSender"~)
break

case .links:
if body.containsLink {
action = .junk
result = MessageEvaluationResult(action: .junk, reason: "autoFilter_links_shortTitle"~)
break
}

case .numbersOnly:
if let _ = sender.rangeOfCharacter(from: NSCharacterSet.letters) {
action = .junk
result = MessageEvaluationResult(action: .junk, reason: "autoFilter_numbersOnly_shortTitle"~)
break
}

case .shortSender:
if sender.count <= Int(activeRule.selectedChoice) {
action = .junk
result = MessageEvaluationResult(action: .junk, reason: "autoFilter_shortSender_shortTitle"~)
break
}

case .email:
if sender.containsEmail {
action = .junk
result = MessageEvaluationResult(action: .junk, reason: "autoFilter_email_shortTitle"~)
break
}

case .emojis:
if body.containsEmoji {
result = MessageEvaluationResult(action: .junk, reason: "autoFilter_emojis_shortTitle"~)
break
}
}
}
}

return action
return result
}

private func isMataching(filter: Filter, body: String, sender: String) -> Bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,7 @@ protocol AppManagerProtocol {
var networkSyncManager: NetworkSyncManagerProtocol { get }
var amazonS3Service: AmazonS3ServiceProtocol { get }

func onAppLaunch()
func onNewUserSession()
func getFrequentlyAskedQuestions() -> [QuestionView.ViewModel]
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,15 @@ import CoreData
import IdentityLookup
import OSLog


struct MessageEvaluationResult {
var action: ILMessageFilterAction
var reason: String?
}

protocol MessageEvaluationManagerProtocol {
var context: NSManagedObjectContext { get }

func evaluateMessage(body: String, sender: String) -> ILMessageFilterAction
func evaluateMessage(body: String, sender: String) -> MessageEvaluationResult
func setLogger(_ logger: Logger)
}
Loading

0 comments on commit 0b4fee8

Please sign in to comment.