package event import ( "fmt" "git.nutfactory.org/hoernschen/Matrix/utils/database" ) func CreateRoomMember(roomId string, userId string, server string) (err error) { sqlStmt := fmt.Sprintf(`INSERT INTO roomMember (roomId, userId, server) VALUES (?, ?, ?)`) tx, err := database.DB.Begin() if err != nil { return } stmt, err := tx.Prepare(sqlStmt) if err != nil { return } defer stmt.Close() _, err = stmt.Exec(roomId, userId, server) if err != nil { tx.Rollback() return } tx.Commit() return } func CreateParents(eventId string, parentIds map[string]EventHash) (err error) { sqlStmt := fmt.Sprintf(`INSERT INTO parent (eventId, parentId) VALUES (?, ?)`) tx, err := database.DB.Begin() if err != nil { return } stmt, err := tx.Prepare(sqlStmt) if err != nil { return } defer stmt.Close() for parentId, _ := range parentIds { _, err = stmt.Exec( eventId, parentId, ) if err != nil { tx.Rollback() return } } tx.Commit() return } func CreateAuthEvents(eventId string, authEventIds map[string]EventHash) (err error) { sqlStmt := fmt.Sprintf(`INSERT INTO authEvent (eventId, authEventId) VALUES (?, ?)`) tx, err := database.DB.Begin() if err != nil { return } stmt, err := tx.Prepare(sqlStmt) if err != nil { return } defer stmt.Close() for authEventId, _ := range authEventIds { _, err = stmt.Exec( eventId, authEventId, ) if err != nil { tx.Rollback() return } } tx.Commit() return } func CreateEvent(event *Event, txnId string) (err error) { sqlStmt := fmt.Sprintf(`INSERT INTO event (id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`) tx, err := database.DB.Begin() if err != nil { return } stmt, err := tx.Prepare(sqlStmt) if err != nil { return } defer stmt.Close() signatures := "" for _, signature := range event.Signatures[event.Origin] { signatures = signature } _, err = stmt.Exec( event.Id, event.RoomId, txnId, event.Sender, event.Origin, event.Timestamp, event.EventType, event.StateKey, event.Content, event.Depth, event.Hashes.SHA256, signatures, ) if err != nil { tx.Rollback() return } tx.Commit() err = CreateParents(event.Id, event.PrevEventHashes) if err != nil { return } err = CreateAuthEvents(event.Id, event.AuthEventHashes) if err != nil { return } return } func CreateEventsFromTransaction(txnId string, pdus map[string]*Event) (err error) { sqlStmt := fmt.Sprintf(`INSERT INTO event (id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`) tx, err := database.DB.Begin() if err != nil { return } stmt, err := tx.Prepare(sqlStmt) if err != nil { return } defer stmt.Close() for _, pdu := range pdus { signatures := "" for _, signature := range pdu.Signatures[pdu.Origin] { signatures = signature } _, err = stmt.Exec( pdu.Id, pdu.RoomId, txnId, pdu.Sender, pdu.Origin, pdu.Timestamp, pdu.EventType, pdu.StateKey, pdu.Content, pdu.Depth, pdu.Hashes.SHA256, signatures, ) if err != nil { tx.Rollback() return } err = CreateParents(pdu.Id, pdu.PrevEventHashes) if err != nil { return } err = CreateAuthEvents(pdu.Id, pdu.AuthEventHashes) if err != nil { return } } tx.Commit() return } func ReadEventHash(id string) (hash string, err error) { queryStmt := fmt.Sprintf(`SELECT hash FROM event WHERE id = '%s'`, id) rows, err := database.DB.Query(queryStmt) if err != nil { return } defer rows.Close() if rows.Next() { err = rows.Scan(hash) if err != nil { return } } return } func ReadRoomMembers(roomId string) (roomMembers []string, err error) { queryStmt := fmt.Sprintf(`SELECT userId FROM roomMember WHERE roomId = '%s'`, roomId) rows, err := database.DB.Query(queryStmt) if err != nil { return } defer rows.Close() roomMembers = []string{} for rows.Next() { var foundUser string err = rows.Scan(&foundUser) if err != nil { return } roomMembers = append(roomMembers, foundUser) } return } func ReadServers(roomId string) (servers []string, err error) { queryStmt := fmt.Sprintf(`SELECT DISTINCT server FROM roomMember WHERE roomId = '%s'`, roomId) rows, err := database.DB.Query(queryStmt) if err != nil { return } defer rows.Close() servers = []string{} for rows.Next() { var foundUser string err = rows.Scan(&foundUser) if err != nil { return } servers = append(servers, foundUser) } return } func ReadParents(eventId string) (parents map[string]EventHash, err error) { queryStmt := fmt.Sprintf(`SELECT e.id, e.hash FROM event as e join parent as p on e.id = p.parentId WHERE p.eventId = '%s'`, eventId) rows, err := database.DB.Query(queryStmt) if err != nil { return } defer rows.Close() parents = make(map[string]EventHash) for rows.Next() { var eventId string var foundEvent EventHash err = rows.Scan(&eventId, &foundEvent.SHA256, ) if err != nil { return } parents[eventId] = foundEvent } return } func ReadEventsWithoutChild(roomId string) (events map[string]EventHash, depth int, err error) { queryStmt := fmt.Sprintf(`SELECT e.id, e.hash, e.depth FROM event as e LEFT JOIN parent as p on e.id = p.parentId WHERE p.eventId IS NULL AND e.roomId = '%s'`, roomId) rows, err := database.DB.Query(queryStmt) if err != nil { return } defer rows.Close() events = make(map[string]EventHash) for rows.Next() { var eventId string var foundEvent EventHash var foundDepth int err = rows.Scan(&eventId, &foundEvent.SHA256, &foundDepth, ) if foundDepth > depth { depth = foundDepth } if err != nil { return } events[eventId] = foundEvent } return } func ReadAuthEvents(eventId string) (authEvents map[string]EventHash, err error) { queryStmt := fmt.Sprintf(`SELECT e.id, e.hash FROM event as e join authEvent as a on e.id = a.authEventId WHERE a.eventId = '%s'`, eventId) rows, err := database.DB.Query(queryStmt) if err != nil { return } defer rows.Close() authEvents = make(map[string]EventHash) for rows.Next() { var eventId string var foundEvent EventHash err = rows.Scan(&eventId, &foundEvent.SHA256, ) if err != nil { return } authEvents[eventId] = foundEvent } return } func ReadEvent(id string) (foundEvent *Event, err error) { queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature FROM event WHERE id = '%s'`, id) rows, err := database.DB.Query(queryStmt) if err != nil { return } defer rows.Close() if rows.Next() { foundEvent = &Event{} var signature string err = rows.Scan(&foundEvent.Id, &foundEvent.RoomId, &foundEvent.Unsigned.TransactionId, &foundEvent.Sender, &foundEvent.Origin, &foundEvent.Timestamp, &foundEvent.EventType, &foundEvent.StateKey, &foundEvent.Content, &foundEvent.Depth, &foundEvent.Hashes.SHA256, &signature, ) foundEvent.Signatures = make(map[string]map[string]string) foundEvent.Signatures[foundEvent.Origin] = make(map[string]string) foundEvent.Signatures[foundEvent.Origin]["ed25519:1"] = signature if err != nil { return } foundEvent.PrevEventHashes, err = ReadParents(foundEvent.Id) if err != nil { return } foundEvent.AuthEventHashes, err = ReadAuthEvents(foundEvent.Id) if err != nil { return } } return } func ReadStateEvent(roomId string, eventType string, stateKey string) (foundEvent *Event, err error) { queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature FROM event WHERE roomId = '%s' AND eventType = '%s' AND stateKey = '%s'`, roomId, eventType, stateKey) if stateKey == "" { queryStmt = fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature FROM event WHERE roomId = '%s' AND eventType = '%s'`, roomId, eventType) } rows, err := database.DB.Query(queryStmt) if err != nil { return } defer rows.Close() if rows.Next() { foundEvent = &Event{} var signature string err = rows.Scan(&foundEvent.Id, &foundEvent.RoomId, &foundEvent.Unsigned.TransactionId, &foundEvent.Sender, &foundEvent.Origin, &foundEvent.Timestamp, &foundEvent.EventType, &foundEvent.StateKey, &foundEvent.Content, &foundEvent.Depth, &foundEvent.Hashes.SHA256, &signature, ) foundEvent.Signatures = make(map[string]map[string]string) foundEvent.Signatures[foundEvent.Origin] = make(map[string]string) foundEvent.Signatures[foundEvent.Origin]["ed25519:1"] = signature if err != nil { return } foundEvent.PrevEventHashes, err = ReadParents(foundEvent.Id) if err != nil { return } foundEvent.AuthEventHashes, err = ReadAuthEvents(foundEvent.Id) if err != nil { return } } return } func ReadStateEvents(roomId string, eventType string) (foundEvents []*Event, err error) { queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature FROM event WHERE roomId = '%s' AND eventType = '%s'`, roomId, eventType) rows, err := database.DB.Query(queryStmt) if err != nil { return } defer rows.Close() for rows.Next() { foundEvent := &Event{} var signature string err = rows.Scan(&foundEvent.Id, &foundEvent.RoomId, &foundEvent.Unsigned.TransactionId, &foundEvent.Sender, &foundEvent.Origin, &foundEvent.Timestamp, &foundEvent.EventType, &foundEvent.StateKey, &foundEvent.Content, &foundEvent.Depth, &foundEvent.Hashes.SHA256, &signature, ) foundEvent.Signatures = make(map[string]map[string]string) foundEvent.Signatures[foundEvent.Origin] = make(map[string]string) foundEvent.Signatures[foundEvent.Origin]["ed25519:1"] = signature if err != nil { return } foundEvent.PrevEventHashes, err = ReadParents(foundEvent.Id) if err != nil { return } foundEvent.AuthEventHashes, err = ReadAuthEvents(foundEvent.Id) if err != nil { return } foundEvents = append(foundEvents, foundEvent) } return } func ReadEventsFromRoom(roomId string) (events map[string]*Event, err error) { queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature FROM event WHERE roomId = '%s'`, roomId) rows, err := database.DB.Query(queryStmt) if err != nil { return } defer rows.Close() events = make(map[string]*Event) for rows.Next() { foundEvent := &Event{} var signature string err = rows.Scan(&foundEvent.Id, &foundEvent.RoomId, &foundEvent.Unsigned.TransactionId, &foundEvent.Sender, &foundEvent.Origin, &foundEvent.Timestamp, &foundEvent.EventType, &foundEvent.StateKey, &foundEvent.Content, &foundEvent.Depth, &foundEvent.Hashes.SHA256, &signature, ) foundEvent.Signatures = make(map[string]map[string]string) foundEvent.Signatures[foundEvent.Origin] = make(map[string]string) foundEvent.Signatures[foundEvent.Origin]["ed25519:1"] = signature if err != nil { return } foundEvent.PrevEventHashes, err = ReadParents(foundEvent.Id) if err != nil { return } foundEvent.AuthEventHashes, err = ReadAuthEvents(foundEvent.Id) if err != nil { return } events[foundEvent.Id] = foundEvent } return } func ReadStateEventsFromRoom(roomId string) (events []*Event, err error) { queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature FROM event WHERE eventType <> 'm.room.message' AND roomId = '%s'`, roomId) rows, err := database.DB.Query(queryStmt) if err != nil { return } defer rows.Close() for rows.Next() { foundEvent := &Event{} var signature string err = rows.Scan(&foundEvent.Id, &foundEvent.RoomId, &foundEvent.Unsigned.TransactionId, &foundEvent.Sender, &foundEvent.Origin, &foundEvent.Timestamp, &foundEvent.EventType, &foundEvent.StateKey, &foundEvent.Content, &foundEvent.Depth, &foundEvent.Hashes.SHA256, &signature, ) foundEvent.Signatures = make(map[string]map[string]string) foundEvent.Signatures[foundEvent.Origin] = make(map[string]string) foundEvent.Signatures[foundEvent.Origin]["ed25519:1"] = signature if err != nil { return } foundEvent.PrevEventHashes, err = ReadParents(foundEvent.Id) if err != nil { return } foundEvent.AuthEventHashes, err = ReadAuthEvents(foundEvent.Id) if err != nil { return } events = append(events, foundEvent) } return } func ReadEventsFromTransaction(txnId string) (events []*Event, err error) { queryStmt := fmt.Sprintf(`SELECT id, roomId, txnId, sender, origin, timestamp, eventType, stateKey, content, depth, hash, signature FROM event WHERE txnId = '%s'`, txnId) rows, err := database.DB.Query(queryStmt) if err != nil { return } defer rows.Close() for rows.Next() { foundEvent := &Event{} var signature string err = rows.Scan(&foundEvent.Id, &foundEvent.RoomId, &foundEvent.Unsigned.TransactionId, &foundEvent.Sender, &foundEvent.Origin, &foundEvent.Timestamp, &foundEvent.EventType, &foundEvent.StateKey, &foundEvent.Content, &foundEvent.Depth, &foundEvent.Hashes.SHA256, &signature, ) foundEvent.Signatures = make(map[string]map[string]string) foundEvent.Signatures[foundEvent.Origin] = make(map[string]string) foundEvent.Signatures[foundEvent.Origin]["ed25519:1"] = signature if err != nil { return } foundEvent.PrevEventHashes, err = ReadParents(foundEvent.Id) if err != nil { return } foundEvent.AuthEventHashes, err = ReadAuthEvents(foundEvent.Id) if err != nil { return } events = append(events, foundEvent) } return } func UpdateEvent(event *Event) (err error) { sqlStmt := fmt.Sprintf(`UPDATE event SET eventType = ?, content = ?, WHERE id = ?`) tx, err := database.DB.Begin() if err != nil { return } stmt, err := tx.Prepare(sqlStmt) if err != nil { return } defer stmt.Close() _, err = stmt.Exec( event.EventType, event.Content, event.Id, ) if err != nil { tx.Rollback() return } tx.Commit() return } func DeleteEvent(id string) (err error) { queryStmt := fmt.Sprintf(`DELETE FROM event WHERE id = '%s'`, id) tx, err := database.DB.Begin() if err != nil { return } _, err = tx.Exec(queryStmt) if err != nil { tx.Rollback() return } err = DeleteParents(id) if err != nil { return } err = DeleteAuthEvents(id) if err != nil { return } tx.Commit() return } func DeleteParents(eventId string) (err error) { queryStmt := fmt.Sprintf(`DELETE FROM parent WHERE eventId = '%s'`, eventId) tx, err := database.DB.Begin() if err != nil { return } _, err = tx.Exec(queryStmt) if err != nil { tx.Rollback() return } tx.Commit() return } func DeleteAuthEvents(eventId string) (err error) { queryStmt := fmt.Sprintf(`DELETE FROM authEvent WHERE eventId = '%s'`, eventId) tx, err := database.DB.Begin() if err != nil { return } _, err = tx.Exec(queryStmt) if err != nil { tx.Rollback() return } tx.Commit() return }