Bark/NotificationServiceExtension/NotificationService.swift
2021-10-12 16:02:34 +08:00

266 lines
10 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 Intents
import Kingfisher
import MobileCoreServices
import RealmSwift
import UIKit
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
var contentHandler: ((UNNotificationContent) -> ())?
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: { _, 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: 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 = defaultCopy
}
}
}
///
/// - 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) { _ in
downloadFinished()
}
}
}
///
/// - Parameters:
/// - bestAttemptContent: content
/// - complection:
fileprivate func setImage(content bestAttemptContent: UNMutableNotificationContent,
complection: @escaping (_ content: UNMutableNotificationContent) -> ())
{
let userInfo = bestAttemptContent.userInfo
guard let imageUrl = userInfo["image"] as? String else {
complection(bestAttemptContent)
return
}
func finished(_ imageFileUrl: String?) {
guard let imageFileUrl = imageFileUrl else {
complection(bestAttemptContent)
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(bestAttemptContent)
}
downloadImage(imageUrl, complection: finished)
}
/// icon
/// - Parameters:
/// - bestAttemptContent: content
/// - complection:
fileprivate func setIcon(content bestAttemptContent: UNMutableNotificationContent,
complection: @escaping (_ content: UNMutableNotificationContent) -> ())
{
if #available(iOSApplicationExtension 15.0, *) {
let userInfo = bestAttemptContent.userInfo
guard let imageUrl = userInfo["icon"] as? String else {
complection(bestAttemptContent)
return
}
func finished(_ imageFileUrl: String?) {
guard let imageFileUrl = imageFileUrl else {
complection(bestAttemptContent)
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: bestAttemptContent.threadIdentifier,
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 bestAttemptContent.updating(from: intent) as! UNMutableNotificationContent
complection(content)
}
catch {
// Handle error
}
complection(bestAttemptContent)
}
downloadImage(imageUrl, complection: finished)
}
else {
complection(bestAttemptContent)
}
}
override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> ()) {
self.contentHandler = contentHandler
guard let bestAttemptContent = (request.content.mutableCopy() as? UNMutableNotificationContent) else {
contentHandler(request.content)
return
}
let userInfo = bestAttemptContent.userInfo
//
autoCopy(userInfo, defaultCopy: bestAttemptContent.body)
//
archive(userInfo)
//
setIcon(content: bestAttemptContent) { result in
//
self.setImage(content: result) { result in
contentHandler(result)
}
}
}
}