Skip to content

Commit b9bfe92

Browse files
committed
Add RoomState Store interface
1 parent ca2c7b2 commit b9bfe92

File tree

2 files changed

+165
-0
lines changed

2 files changed

+165
-0
lines changed

Sources/MatrixSQLiteStore/MatrixSQLiteStore.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,25 @@ public struct MatrixSQLiteStore {
4545
}
4646
}
4747

48+
migrator.registerMigration("createRoomsAndMessages") { db in
49+
try db.create(table: "room_state") { t in
50+
t.column("event_id", .text).notNull().primaryKey()
51+
t.column("room_id", .text).notNull().indexed()
52+
t.column("type", .text).notNull()
53+
t.column("state_key", .text)
54+
t.column("content", .text)
55+
}
56+
57+
try db.create(
58+
index: "room_state_type_key_index",
59+
on: "room_state",
60+
columns: ["room_id", "type", "state_key"],
61+
options: .unique
62+
)
63+
64+
try db.create(index: "room_state_type_index", on: "room_state", columns: ["room_id", "type"])
65+
}
66+
4867
return migrator
4968
}
5069
}
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
//
2+
// File.swift
3+
//
4+
//
5+
// Created by Finn Behrens on 24.04.22.
6+
//
7+
8+
import AnyCodable
9+
import Foundation
10+
import GRDB
11+
import MatrixClient
12+
import MatrixCore
13+
14+
public struct MatrixRoomState: MatrixStoreRoomState {
15+
public var eventId: String
16+
public var roomId: String
17+
18+
public var stateKey: String
19+
20+
// TODO: custom type in MatrixClient?
21+
public var contentType: String
22+
23+
// TODO: some event type?
24+
@MatrixCodableStateEventType
25+
public var content: MatrixStateEventType
26+
}
27+
28+
extension MatrixRoomState: Codable, FetchableRecord, PersistableRecord, Equatable, Hashable {
29+
public static func == (lhs: MatrixRoomState, rhs: MatrixRoomState) -> Bool {
30+
lhs.eventId == rhs.eventId &&
31+
lhs.roomId == rhs.roomId &&
32+
lhs.stateKey == rhs.stateKey &&
33+
lhs.contentType == rhs.contentType
34+
}
35+
36+
public func hash(into hasher: inout Hasher) {
37+
hasher.combine(eventId)
38+
hasher.combine(roomId)
39+
hasher.combine(stateKey)
40+
hasher.combine(contentType)
41+
}
42+
43+
public static var databaseTableName: String = "room_state"
44+
45+
enum CodingKeys: String, CodingKey {
46+
case eventId = "event_id"
47+
case roomId = "room_id"
48+
case contentType = "type"
49+
case stateKey = "state_key"
50+
case content
51+
}
52+
53+
public init(from decoder: Decoder) throws {
54+
let container = try decoder.container(keyedBy: CodingKeys.self)
55+
eventId = try container.decode(String.self, forKey: .eventId)
56+
roomId = try container.decode(String.self, forKey: .roomId)
57+
stateKey = try container.decode(String.self, forKey: .stateKey)
58+
contentType = try container.decode(String.self, forKey: .contentType)
59+
60+
_content = try MatrixCodableStateEventType(from: container.superDecoder(forKey: .content), typeID: contentType)
61+
}
62+
63+
public func encode(to encoder: Encoder) throws {
64+
var container = encoder.container(keyedBy: CodingKeys.self)
65+
try container.encode(eventId, forKey: .eventId)
66+
try container.encode(roomId, forKey: .roomId)
67+
try container.encode(stateKey, forKey: .stateKey)
68+
try container.encode(contentType, forKey: .contentType)
69+
70+
try _content.encode(to: encoder)
71+
}
72+
73+
/* public static func databaseJSONEncoder(for column: String) -> JSONEncoder {
74+
let encoder = JSONEncoder()
75+
encoder.outputFormatting = [.sortedKeys]
76+
encoder.dateEncodingStrategy = .millisecondsSince1970
77+
encoder.dataEncodingStrategy = .base64
78+
encoder.nonConformingFloatEncodingStrategy = .throw
79+
encoder.outputFormatting = .sortedKeys
80+
encoder.userInfo[.matrixEventTypes] = MatrixClient.eventTypes
81+
encoder.userInfo[.matrixMessageTypes] = MatrixClient.messageTypes
82+
encoder.userInfo[.matrixStateEventTypes] = MatrixClient.stateTypes
83+
84+
return encoder
85+
} */
86+
87+
public static var databaseDecodingUserInfo: [CodingUserInfoKey: Any] = [
88+
.matrixEventTypes: MatrixClient.eventTypes,
89+
.matrixMessageTypes: MatrixClient.messageTypes,
90+
.matrixStateEventTypes: MatrixClient.stateTypes,
91+
]
92+
93+
public static var databaseEncodingUserInfo: [CodingUserInfoKey: Any] = Self.databaseDecodingUserInfo
94+
}
95+
96+
public extension MatrixSQLiteStore {
97+
typealias RoomState = MatrixRoomState
98+
99+
func addRoomState(state: MatrixRoomState) async throws {
100+
try await dbWriter.write { db in
101+
try state.insert(db)
102+
}
103+
}
104+
105+
func getRoomState(roomId: String) async throws -> [RoomState] {
106+
try await dbWriter.read { db in
107+
try RoomState.fetchAll(db, sql: "SELECT * FROM room_state WHERE room_id = ?", arguments: [roomId])
108+
}
109+
}
110+
111+
func getRoomState(eventId: String) async throws -> RoomState? {
112+
try await dbWriter.read { db in
113+
try RoomState.fetchOne(db, sql: "SELECT * FROM room_state WHERE event_id = ?", arguments: [eventId])
114+
}
115+
}
116+
117+
func getRoomState(roomId: String, stateType: String) async throws -> [RoomState] {
118+
try await dbWriter.read { db in
119+
try RoomState.fetchAll(
120+
db,
121+
sql: "SELECT * FROM room_state INDEXED BY room_state_type_inex WHERE room_id = ? AND type = ?",
122+
arguments: [roomId, stateType]
123+
)
124+
}
125+
}
126+
127+
func getRoomState(roomId: String, stateKey: String) async throws -> [RoomState] {
128+
try await dbWriter.read { db in
129+
try RoomState.fetchAll(
130+
db,
131+
sql: "SELECT * FROM room_state WHERE room_id = ? and state_key = ?",
132+
arguments: [roomId, stateKey]
133+
)
134+
}
135+
}
136+
137+
func getRoomState(roomId: String, stateType: String, stateKey: String) async throws -> [RoomState] {
138+
try await dbWriter.read { db in
139+
try RoomState.fetchAll(
140+
db,
141+
sql: "SELECT * FROM room_state INDEXED BY room_state_key_index WHERE room_id = ? AND type = ? AND state_key = ?",
142+
arguments: [roomId, stateType, stateKey]
143+
)
144+
}
145+
}
146+
}

0 commit comments

Comments
 (0)