func (db *roomDb) SetRoomState(roomId types.RoomId, userId types.UserId, content matrixTypes.TypedContent, stateKey string) (*matrixTypes.State, matrixTypes.Error) { db.roomsLock.RLock() defer db.roomsLock.RUnlock() room := db.rooms[roomId] if room == nil { return nil, matrixTypes.NotFoundError("room '" + roomId.String() + "' doesn't exist") } var eventId = types.DeriveEventId(utils.RandomString(16), types.Id(userId)) stateId := stateId{content.GetEventType(), stateKey} state := new(matrixTypes.State) state.EventId = eventId state.RoomId = roomId state.UserId = userId state.EventType = content.GetEventType() state.StateKey = stateKey state.Timestamp = types.Timestamp{time.Now()} state.Content = content state.OldState = (*matrixTypes.OldState)(room.states[stateId]) room.stateLock.Lock() defer room.stateLock.Unlock() room.states[stateId] = state return state, nil }
func (s roomService) sendMessage( room ct.RoomId, user ct.UserId, content types.TypedContent, ) (*types.Message, types.Error) { log.Printf("Sending message: %#v, %#v, %#v, %#v", room, user, content) message := new(types.Message) message.EventId = ct.DeriveEventId(utils.RandomString(16), ct.Id(user)) message.RoomId = room message.UserId = user message.EventType = content.GetEventType() message.Timestamp = ct.Timestamp{time.Now()} message.Content = content _, err := s.eventSink.Send(message) if err != nil { return nil, err } return message, nil }
func (s roomService) AddMessage( room ct.RoomId, caller ct.UserId, content types.TypedContent, ) (*types.Message, types.Error) { eventType := content.GetEventType() if _, ok := disallowedMessageTypes[eventType]; ok { return nil, types.ForbiddenError("sending a message event of the type " + eventType + " is not permitted") } err := s.testPowerLevel(room, caller, func(pl *types.PowerLevelsEventContent) int { if eventLevel, ok := pl.Events[eventType]; ok { return eventLevel } return pl.EventDefault }) if err != nil { return nil, err } return s.sendMessage(room, caller, content) }
func (s roomService) SetState( room ct.RoomId, caller ct.UserId, content types.TypedContent, stateKey string, ) (*types.State, types.Error) { userIdStateKey, parseErr := ct.ParseUserId(stateKey) isUserIdStateKey := parseErr == nil eventType := content.GetEventType() switch eventType { case types.EventTypeName: if stateKey != "" { return nil, types.ForbiddenError("state key must be empty for state " + eventType) } case types.EventTypeTopic: if stateKey != "" { return nil, types.ForbiddenError("state key must be empty for state " + eventType) } case types.EventTypeJoinRules: if stateKey != "" { return nil, types.ForbiddenError("state key must be empty for state " + eventType) } case types.EventTypePowerLevels: if stateKey != "" { return nil, types.ForbiddenError("state key must be empty for state " + eventType) } case types.EventTypeCreate: return nil, types.ForbiddenError("cannot set state " + eventType) case types.EventTypeAliases: return nil, types.ForbiddenError("cannot set state " + eventType) case types.EventTypeMembership: membership, ok := content.(*types.MembershipEventContent) if !ok || membership == nil { panic("expected membership event content, got " + reflect.TypeOf(content).String()) } if !isUserIdStateKey { return nil, types.ForbiddenError("state key must be a user id for state " + eventType) } state, err := s.doMembershipChange(room, caller, userIdStateKey, membership) if err != nil { return nil, err } return state, nil } if isUserIdStateKey && userIdStateKey != caller { return nil, types.ForbiddenError("cannot set the state of another user") } existing, err := s.rooms.RoomState(room, eventType, stateKey) if err != nil { return nil, err } if existing != nil { err := s.testPowerLevel(room, caller, func(pl *types.PowerLevelsEventContent) int { return pl.CreateState }) if err != nil { return nil, err } } err = s.testPowerLevel(room, caller, func(pl *types.PowerLevelsEventContent) int { if eventLevel, ok := pl.Events[eventType]; ok { return eventLevel } return pl.EventDefault }) if err != nil { return nil, err } return s.setState(room, caller, content, stateKey) }