another.im-ios/ConversationsClassic/AppCore/Database/Database+Martin.swift
2024-06-19 17:15:27 +02:00

223 lines
8.1 KiB
Swift

import Foundation
import GRDB
import Martin
extension Database: MartinsManager {
// MARK: - Martin's roster manager
func clear(for context: Martin.Context) {
print("Clearing roster for context: \(context)")
do {
try _db.write { db in
try Roster
.filter(Column("bareJid") == context.userBareJid.stringValue)
.deleteAll(db)
try RosterVersion
.filter(Column("bareJid") == context.userBareJid.stringValue)
.deleteAll(db)
}
} catch {
logIt(.error, "Error clearing roster: \(error.localizedDescription)")
}
}
func items(for context: Martin.Context) -> [any Martin.RosterItemProtocol] {
do {
let rosters: [Roster] = try _db.read { db in
try Roster.filter(Column("bareJid") == context.userBareJid.stringValue).fetchAll(db)
}
return rosters.map { roster in
RosterItemBase(
jid: JID(roster.bareJid),
name: roster.name,
subscription: RosterItemSubscription(rawValue: roster.subscription) ?? .none,
groups: roster.data.groups,
ask: roster.ask,
annotations: roster.data.annotations
)
}
} catch {
logIt(.error, "Error fetching roster items: \(error.localizedDescription)")
return []
}
}
func item(for context: Martin.Context, jid: Martin.JID) -> (any Martin.RosterItemProtocol)? {
do {
let roster: Roster? = try _db.read { db in
try Roster
.filter(Column("bareJid") == context.userBareJid.stringValue)
.filter(Column("contactBareJid") == jid.stringValue)
.fetchOne(db)
}
if let roster {
return RosterItemBase(
jid: JID(roster.bareJid),
name: roster.name,
subscription: RosterItemSubscription(rawValue: roster.subscription) ?? .none,
groups: roster.data.groups,
ask: roster.ask,
annotations: roster.data.annotations
)
} else {
return nil
}
} catch {
logIt(.error, "Error fetching roster item: \(error.localizedDescription)")
return nil
}
}
func updateItem(for context: Martin.Context, jid: Martin.JID, name: String?, subscription: Martin.RosterItemSubscription, groups: [String], ask: Bool, annotations: [Martin.RosterItemAnnotation]) -> (any Martin.RosterItemProtocol)? {
do {
let roster = Roster(
bareJid: context.userBareJid.stringValue,
contactBareJid: jid.stringValue,
name: name,
subscription: subscription.rawValue,
ask: ask,
data: DBRosterData(
groups: groups,
annotations: annotations
)
)
try _db.write { db in
try roster.save(db)
}
return RosterItemBase(jid: jid, name: name, subscription: subscription, groups: groups, ask: ask, annotations: annotations)
} catch {
logIt(.error, "Error updating roster item: \(error.localizedDescription)")
return nil
}
}
func deleteItem(for context: Martin.Context, jid: Martin.JID) -> (any Martin.RosterItemProtocol)? {
do {
let roster: Roster? = try _db.read { db in
try Roster
.filter(Column("bareJid") == context.userBareJid.stringValue)
.filter(Column("contactBareJid") == jid.stringValue)
.fetchOne(db)
}
if let roster {
_ = try _db.write { db in
try roster.delete(db)
}
return RosterItemBase(
jid: JID(roster.bareJid),
name: roster.name,
subscription: RosterItemSubscription(rawValue: roster.subscription) ?? .none,
groups: roster.data.groups,
ask: roster.ask,
annotations: roster.data.annotations
)
} else {
return nil
}
} catch {
logIt(.error, "Error fetching roster version: \(error.localizedDescription)")
return nil
}
}
func version(for context: Martin.Context) -> String? {
do {
let version: RosterVersion? = try _db.read { db in
try RosterVersion
.filter(Column("bareJid") == context.userBareJid.stringValue)
.fetchOne(db)
}
return version?.version
} catch {
logIt(.error, "Error fetching roster version: \(error.localizedDescription)")
return nil
}
}
func set(version: String?, for context: Martin.Context) {
guard let version else { return }
do {
try _db.write { db in
let rosterVersion = RosterVersion(
bareJid: context.userBareJid.stringValue,
version: version
)
try rosterVersion.save(db)
}
} catch {
logIt(.error, "Error setting roster version: \(error.localizedDescription)")
}
}
func initialize(context _: Martin.Context) {}
func deinitialize(context _: Martin.Context) {}
// MARK: - Martin's chats manager
func chats(for context: Martin.Context) -> [any Martin.ChatProtocol] {
do {
let chats: [Chat] = try _db.read { db in
try Chat.filter(Column("account") == context.userBareJid.stringValue).fetchAll(db)
}
return chats.map { chat in
Martin.ChatBase(context: context, jid: BareJID(chat.participant))
}
} catch {
logIt(.error, "Error fetching chats: \(error.localizedDescription)")
return []
}
}
func chat(for context: Martin.Context, with: Martin.BareJID) -> (any Martin.ChatProtocol)? {
do {
let chat: Chat? = try _db.read { db in
try Chat
.filter(Column("account") == context.userBareJid.stringValue)
.filter(Column("participant") == with.stringValue)
.fetchOne(db)
}
if chat != nil {
return Martin.ChatBase(context: context, jid: with)
} else {
return nil
}
} catch {
logIt(.error, "Error fetching chat: \(error.localizedDescription)")
return nil
}
}
func createChat(for context: Martin.Context, with: Martin.BareJID) -> (any Martin.ChatProtocol)? {
do {
let chat: Chat? = try _db.read { db in
try Chat
.filter(Column("account") == context.userBareJid.stringValue)
.filter(Column("participant") == with.stringValue)
.fetchOne(db)
}
if chat != nil {
return Martin.ChatBase(context: context, jid: with)
} else {
let chat = Chat(
id: UUID().uuidString,
account: context.userBareJid.stringValue,
participant: with.stringValue,
type: .chat
)
try _db.write { db in
try chat.save(db)
}
return Martin.ChatBase(context: context, jid: with)
}
} catch {
logIt(.error, "Error fetching chat: \(error.localizedDescription)")
return nil
}
}
func close(chat: any Martin.ChatProtocol) -> Bool {
// not used in Martin library for now
print("Closing chat: \(chat)")
return false
}
}