2024-06-19 15:15:27 +00:00
|
|
|
import Foundation
|
|
|
|
import GRDB
|
|
|
|
import Martin
|
|
|
|
|
2024-07-30 09:26:30 +00:00
|
|
|
extension Database: MartinsManager {}
|
|
|
|
|
2024-07-29 16:36:22 +00:00
|
|
|
// MARK: - Martin's roster manager
|
|
|
|
extension Database: Martin.RosterManager {
|
2024-06-19 15:15:27 +00:00
|
|
|
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) {}
|
2024-07-29 16:36:22 +00:00
|
|
|
}
|
2024-06-19 15:15:27 +00:00
|
|
|
|
2024-07-29 16:36:22 +00:00
|
|
|
// MARK: - Martin's chats manager
|
|
|
|
extension Database: Martin.ChatManager {
|
2024-06-19 15:15:27 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
2024-07-29 16:36:22 +00:00
|
|
|
|
|
|
|
// MARK: - Martin's rooms manager
|
|
|
|
extension Database: Martin.RoomManager {
|
|
|
|
func rooms(for _: Martin.Context) -> [any Martin.RoomProtocol] {
|
|
|
|
[]
|
|
|
|
}
|
|
|
|
|
|
|
|
func room(for _: Martin.Context, with _: Martin.BareJID) -> (any Martin.RoomProtocol)? {
|
|
|
|
nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func createRoom(for _: Martin.Context, with _: Martin.BareJID, nickname _: String, password _: String?) -> (any Martin.RoomProtocol)? {
|
|
|
|
nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func close(room _: any Martin.RoomProtocol) -> Bool {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// MARK: - Martin's channels manager
|
|
|
|
extension Database: Martin.ChannelManager {
|
|
|
|
func channels(for _: Martin.Context) -> [any Martin.ChannelProtocol] {
|
|
|
|
[]
|
|
|
|
// do {
|
|
|
|
// let channels: [Channel] = try _db.read { db in
|
|
|
|
// try Channel.filter(Column("account") == context.userBareJid.stringValue).fetchAll(db)
|
|
|
|
// }
|
|
|
|
// return channels.map { channel in
|
|
|
|
// Martin.ChannelBase(context: context, channelJid: channel.channel, participantId: , nickname: , state: )
|
|
|
|
// }
|
|
|
|
// } catch {
|
|
|
|
// logIt(.error, "Error fetching channels: \(error.localizedDescription)")
|
|
|
|
// return []
|
|
|
|
// }
|
|
|
|
}
|
|
|
|
|
|
|
|
func createChannel(for _: Martin.Context, with _: Martin.BareJID, participantId _: String, nick _: String?, state _: Martin.ChannelState) -> Martin.ConversationCreateResult<any Martin.ChannelProtocol> {
|
|
|
|
.none
|
|
|
|
}
|
|
|
|
|
|
|
|
func channel(for _: Martin.Context, with _: Martin.BareJID) -> (any Martin.ChannelProtocol)? {
|
|
|
|
nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func close(channel _: any Martin.ChannelProtocol) -> Bool {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|