Bark/NotificationServiceExtension/NotificationService.swift
2021-09-26 16:28:36 +08:00

264 lines
9.9 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// NotificationService.swift
// NotificationServiceExtension
//
// Created by huangfeng on 2018/12/17.
// Copyright © 2018 Fin. All rights reserved.
//
import UIKit
import UserNotifications
import RealmSwift
import Kingfisher
import MobileCoreServices
import Intents
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> Void)?
var bestAttemptContent: UNMutableNotificationContent?
lazy var realm:Realm? = {
let groupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.bark")
let fileUrl = groupUrl?.appendingPathComponent("bark.realm")
let config = Realm.Configuration(
fileURL: fileUrl,
schemaVersion: 13,
migrationBlock: { migration, oldSchemaVersion in
// We havent migrated anything yet, so oldSchemaVersion == 0
if (oldSchemaVersion < 1) {
// Nothing to do!
// Realm will automatically detect new properties and removed properties
// And will update the schema on disk automatically
}
})
// Tell Realm to use this new configuration object for the default Realm
Realm.Configuration.defaultConfiguration = config
return try? Realm()
}()
///
/// - Parameters:
/// - userInfo:
/// - bestAttemptContentBody: body`` ``
fileprivate func autoCopy(_ userInfo: [AnyHashable : Any], defaultCopy bestAttemptContentBody: String) {
if userInfo["autocopy"] as? String == "1"
|| userInfo["automaticallycopy"] as? String == "1"{
if let copy = userInfo["copy"] as? String {
UIPasteboard.general.string = copy
}
else{
UIPasteboard.general.string = bestAttemptContentBody
}
}
}
///
/// - Parameter userInfo:
/// `isarchive` `isarchive`
/// ``
fileprivate func archive(_ userInfo: [AnyHashable : Any]) {
var isArchive:Bool?
if let archive = userInfo["isarchive"] as? String{
isArchive = archive == "1" ? true : false
}
if isArchive == nil {
isArchive = ArchiveSettingManager.shared.isArchive
}
let alert = (userInfo["aps"] as? [String:Any])?["alert"] as? [String:Any]
let title = alert?["title"] as? String
let body = alert?["body"] as? String
let url = userInfo["url"] as? String
let group = userInfo["group"] as? String
if (isArchive == true){
try? realm?.write{
let message = Message()
message.title = title
message.body = body
message.url = url
message.group = group
message.createDate = Date()
realm?.add(message)
}
}
}
///
/// - Parameters:
/// - userInfo:
/// - bestAttemptContent: content
/// - complection:
fileprivate func downloadImage(_ imageUrl:String, complection: @escaping (_ imageFileUrl:String?) -> () ) {
guard let groupUrl = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.bark"),
let cache = try? ImageCache(name: "shared",cacheDirectoryURL: groupUrl),
let imageResource = URL(string: imageUrl)
else {
complection(nil)
return
}
func downloadFinished(){
let cacheFileUrl = cache.cachePath(forKey: imageResource.cacheKey)
complection(cacheFileUrl)
}
//
if cache.diskStorage.isCached(forKey: imageResource.cacheKey) {
downloadFinished()
return
}
//
Kingfisher.ImageDownloader.default.downloadImage(with: imageResource, options: nil) { result in
guard let result = try? result.get() else {
complection(nil)
return
}
//
cache.storeToDisk(result.originalData, forKey: imageResource.cacheKey, expiration: StorageExpiration.never) { r in
downloadFinished()
}
}
}
///
/// - Parameters:
/// - userInfo:
/// - bestAttemptContent: content
/// - complection:
fileprivate func setImage(_ userInfo: [AnyHashable : Any], content bestAttemptContent: UNMutableNotificationContent, complection: @escaping () -> () ) {
guard let imageUrl = userInfo["image"] as? String else {
complection()
return
}
func finished(_ imageFileUrl: String?){
guard let imageFileUrl = imageFileUrl else {
complection()
return
}
let copyDestUrl = URL(fileURLWithPath: imageFileUrl).appendingPathExtension(".tmp")
// 使
try? FileManager.default.copyItem(
at: URL(fileURLWithPath: imageFileUrl),
to: copyDestUrl)
if let attachment = try? UNNotificationAttachment(
identifier: "image",
url: copyDestUrl,
options: [UNNotificationAttachmentOptionsTypeHintKey : kUTTypePNG]){
bestAttemptContent.attachments = [ attachment ]
}
complection()
}
downloadImage(imageUrl, complection: finished)
}
fileprivate func setIcon(_ userInfo: [AnyHashable : Any], content bestAttemptContent: UNMutableNotificationContent, complection: @escaping () -> () ) {
if #available(iOSApplicationExtension 15.0, *) {
guard let imageUrl = userInfo["icon"] as? String else {
complection()
return
}
func finished(_ imageFileUrl: String?){
guard let imageFileUrl = imageFileUrl else {
complection()
return
}
var personNameComponents = PersonNameComponents()
personNameComponents.nickname = bestAttemptContent.title
let avatar = INImage(imageData: NSData(contentsOfFile: imageFileUrl)! as Data)
let senderPerson = INPerson(
personHandle: INPersonHandle(value: "", type: .unknown),
nameComponents: personNameComponents,
displayName: personNameComponents.nickname,
image: avatar,
contactIdentifier: nil,
customIdentifier: nil,
isMe: false,
suggestionType: .none
)
let mePerson = INPerson(
personHandle: INPersonHandle(value: "", type: .unknown),
nameComponents: nil,
displayName: nil,
image: nil,
contactIdentifier: nil,
customIdentifier: nil,
isMe: true,
suggestionType: .none
)
let intent = INSendMessageIntent(
recipients: [mePerson],
outgoingMessageType: .outgoingMessageText,
content: bestAttemptContent.body,
speakableGroupName: INSpeakableString(spokenPhrase: personNameComponents.nickname ?? ""),
conversationIdentifier: "sampleConversationIdentifier",
serviceName: nil,
sender: senderPerson,
attachments: nil
)
intent.setImage(avatar, forParameterNamed: \.sender)
let interaction = INInteraction(intent: intent, response: nil)
interaction.direction = .incoming
interaction.donate(completion: nil)
do {
let content = try self.bestAttemptContent!.updating(from: intent) as! UNMutableNotificationContent
self.bestAttemptContent = content
} catch {
// Handle error
}
complection()
}
downloadImage(imageUrl, complection: finished)
}
else{
complection()
}
}
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) {
self.contentHandler = contentHandler
bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent)
if let bestAttemptContent = bestAttemptContent {
let userInfo = bestAttemptContent.userInfo
//
autoCopy(userInfo, defaultCopy: bestAttemptContent.body)
//
archive(userInfo)
//
setIcon(userInfo, content: self.bestAttemptContent!) {
//
self.setImage(userInfo, content: self.bestAttemptContent!) {
contentHandler(self.bestAttemptContent!)
}
}
}
else{
contentHandler(bestAttemptContent!)
}
}
}