[ABANDONED] Mastodon iOS client.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

279 lines
9.9 KiB

//
// MastodonDataManager.swift
// elpha-ios
//
// Created by Dwayne Harris on 10/1/18.
// Copyright © 2018 Elpha. All rights reserved.
//
import CoreData
import Foundation
import MastodonKit
public class MastodonDataManager {
static func upsertAccount(_ remoteAccount: Account) -> AccountMO? {
func saveAccount(_ account: AccountMO) -> AccountMO? {
account.id = remoteAccount.id
account.username = remoteAccount.username
account.acct = remoteAccount.acct
account.displayName = remoteAccount.displayName
account.note = remoteAccount.note
account.url = remoteAccount.url
account.avatarURL = URL(string: remoteAccount.avatar)
account.avatarStaticURL = URL(string: remoteAccount.avatarStatic)
account.headerURL = URL(string: remoteAccount.header)
account.headerStaticURL = URL(string: remoteAccount.headerStatic)
account.locked = remoteAccount.locked
account.createdAt = remoteAccount.createdAt
account.followersCount = Int32(remoteAccount.followersCount)
account.followingCount = Int32(remoteAccount.followingCount)
account.statusesCount = Int32(remoteAccount.statusesCount)
return account
}
let context = CoreDataManager.shared.getContext()
let request = NSFetchRequest<AccountMO>(entityName: "Account")
request.predicate = NSPredicate(format: "acct == %@", remoteAccount.acct)
do {
let results = try context.fetch(request)
if let account = results.first {
return saveAccount(account)
} else {
return saveAccount(AccountMO(context: context))
}
} catch {
print("\(error)")
return nil
}
}
static func upsertAttachment(_ remoteAttachment: Attachment) -> AttachmentMO? {
func saveAttachment(_ attachment: AttachmentMO) -> AttachmentMO? {
attachment.id = remoteAttachment.id
attachment.type = remoteAttachment.type.rawValue
attachment.url = URL(string: remoteAttachment.url)
attachment.previewURL = URL(string: remoteAttachment.previewURL)
attachment.remoteURL = remoteAttachment.remoteURL
attachment.textURL = remoteAttachment.textURL
return attachment
}
let context = CoreDataManager.shared.getContext()
let request = NSFetchRequest<AttachmentMO>(entityName: "Attachment")
request.predicate = NSPredicate(format: "id == %@", remoteAttachment.id)
do {
let results = try context.fetch(request)
if let attachment = results.first {
return saveAttachment(attachment)
} else {
return saveAttachment(AttachmentMO(context: context))
}
} catch {
print("\(error)")
return nil
}
}
static func upsertMention(_ remoteMention: Mention) -> MentionMO? {
func saveMention(_ mention: MentionMO) -> MentionMO? {
mention.id = remoteMention.id
mention.username = remoteMention.username
mention.acct = remoteMention.acct
mention.url = URL(string: remoteMention.url)
return mention
}
let context = CoreDataManager.shared.getContext()
let request = NSFetchRequest<MentionMO>(entityName: "Mention")
request.predicate = NSPredicate(format: "id == %@", remoteMention.id)
do {
let results = try context.fetch(request)
if let mention = results.first {
return saveMention(mention)
} else {
return saveMention(MentionMO(context: context))
}
} catch {
print("\(error)")
return nil
}
}
static func upsertTag(_ remoteTag: Tag) -> TagMO? {
func saveTag(_ tag: TagMO) -> TagMO? {
tag.name = remoteTag.name
tag.url = URL(string: remoteTag.url)
return tag
}
let context = CoreDataManager.shared.getContext()
let request = NSFetchRequest<TagMO>(entityName: "Tag")
request.predicate = NSPredicate(format: "name == %@", remoteTag.name)
do {
let results = try context.fetch(request)
if let tag = results.first {
return saveTag(tag)
} else {
return saveTag(TagMO(context: context))
}
} catch {
print("\(error)")
return nil
}
}
static func upsertApp(_ remoteApp: Application) -> AppMO? {
func saveApp(_ app: AppMO) -> AppMO? {
app.name = remoteApp.name
if let website = remoteApp.website {
app.website = URL(string: website)
}
return app
}
let context = CoreDataManager.shared.getContext()
let request = NSFetchRequest<AppMO>(entityName: "App")
request.predicate = NSPredicate(format: "name == %@", remoteApp.name)
do {
let results = try context.fetch(request)
if let tag = results.first {
return saveApp(tag)
} else {
return saveApp(AppMO(context: context))
}
} catch {
print("\(error)")
return nil
}
}
static func upsertStatus(_ remoteStatus: Status) -> StatusMO? {
func saveStatus(_ status: StatusMO) -> StatusMO? {
status.id = remoteStatus.id
status.uri = URL(string: remoteStatus.uri)
status.url = remoteStatus.url
status.account = MastodonDataManager.upsertAccount(remoteStatus.account)
status.inReplyToID = remoteStatus.inReplyToID
status.inReplyToAccountID = remoteStatus.inReplyToAccountID
status.content = remoteStatus.content
status.createdAt = remoteStatus.createdAt
status.reblogsCount = Int32(remoteStatus.reblogsCount)
status.favouritesCount = Int32(remoteStatus.favouritesCount)
status.reblogged = remoteStatus.reblogged ?? false
status.favourited = remoteStatus.favourited ?? false
status.sensitive = remoteStatus.sensitive ?? false
status.pinned = remoteStatus.pinned ?? false
status.spoilerText = remoteStatus.spoilerText
status.visibility = remoteStatus.visibility.rawValue
if let app = remoteStatus.application {
status.app = MastodonDataManager.upsertApp(app)
}
remoteStatus.mediaAttachments.forEach { attachment in
if let attachment = MastodonDataManager.upsertAttachment(attachment) {
status.mutableSetValue(forKey: "attachments").add(attachment)
}
}
remoteStatus.mentions.forEach { mention in
if let mention = MastodonDataManager.upsertMention(mention) {
status.mutableSetValue(forKey: "mentions").add(mention)
}
}
remoteStatus.tags.forEach { tag in
if let tag = MastodonDataManager.upsertTag(tag) {
status.mutableSetValue(forKey: "tags").add(tag)
}
}
if let reblog = remoteStatus.reblog {
let savedReblog = upsertStatus(reblog)
status.reblog = savedReblog
}
return status
}
let context = CoreDataManager.shared.getContext()
let request = NSFetchRequest<StatusMO>(entityName: "Status")
request.predicate = NSPredicate(format: "id == %@", remoteStatus.id)
do {
let results = try context.fetch(request)
if let status = results.first {
return saveStatus(status)
} else {
return saveStatus(StatusMO(context: context))
}
} catch {
print("\(error)")
return nil
}
}
static func saveClient(id: String, clientID: String, clientSecret: String, url: String) -> ClientMO {
let client = ClientMO(context: CoreDataManager.shared.getContext())
client.id = id
client.clientID = clientID
client.clientSecret = clientSecret
client.url = url
CoreDataManager.shared.saveContext()
return client
}
static func getAccountByID(_ id: String) -> AccountMO? {
let request = NSFetchRequest<AccountMO>(entityName: "Account")
request.predicate = NSPredicate(format: "id == %@", id)
do {
let results = try CoreDataManager.shared.getContext().fetch(request)
guard let account = results.first else {
return nil
}
return account
} catch {
print("\(error)")
return nil
}
}
static func getRemoteAccountByID(id: String, completion: @escaping (AccountMO?, Error?) -> Void ) {
if let account = getAccountByID(id) {
completion(account, nil)
return
}
guard let client = AuthenticationManager.shared.getMKClientForSelectedSession() else {
completion(nil, NSError())
return
}
let request = Accounts.account(id: id)
client.run(request) { result in
switch result {
case .success(let account, _):
completion(upsertAccount(account), nil)
return
case .failure(let error):
completion(nil, error)
return
}
}
}
}