diff --git a/server/internal/http/legacy/session.go b/server/internal/http/legacy/session.go index df0463c9..0dda073b 100644 --- a/server/internal/http/legacy/session.go +++ b/server/internal/http/legacy/session.go @@ -6,6 +6,7 @@ import ( "fmt" "io" "net/http" + "strings" oldTypes "github.com/demodesk/neko/internal/http/legacy/types" @@ -20,6 +21,12 @@ var ( ErrBackendRespone = fmt.Errorf("error response from backend") ) +type memberStruct struct { + member *oldTypes.Member + connected bool + sent bool +} + type session struct { logger zerolog.Logger serverAddr string @@ -33,7 +40,7 @@ type session struct { lockedControls bool lockedLogins bool lockedFileTransfer bool - sessions map[string]*oldTypes.Member + sessions map[string]*memberStruct connClient *websocket.Conn connBackend *websocket.Conn @@ -44,7 +51,7 @@ func newSession(logger zerolog.Logger, serverAddr string) *session { logger: logger, serverAddr: serverAddr, client: http.DefaultClient, - sessions: make(map[string]*oldTypes.Member), + sessions: make(map[string]*memberStruct), } } @@ -81,7 +88,7 @@ func (s *session) apiReq(method, path string, request, response any) error { return fmt.Errorf("%w: %s", ErrBackendRespone, apiErr.Message) } // return raw body if failed to unmarshal - return fmt.Errorf("unexpected status code: %d, body: %s", res.StatusCode, body) + return fmt.Errorf("unexpected status code: %d, body: %s", res.StatusCode, strings.TrimSpace(string(body))) } if res.Body == nil { diff --git a/server/internal/http/legacy/wstobackend.go b/server/internal/http/legacy/wstobackend.go index 6969091d..c78b0497 100644 --- a/server/internal/http/legacy/wstobackend.go +++ b/server/internal/http/legacy/wstobackend.go @@ -314,8 +314,11 @@ func (s *session) wsToBackend(msg []byte) error { return err } - // TODO: No WS equivalent, call HTTP API. - return fmt.Errorf("event not implemented: %s", header.Event) + return s.apiReq(http.MethodPost, "/api/members/"+request.ID, map[string]any{ + "plugins": map[string]any{ + "chat.can_send": false, + }, + }, nil) case oldEvent.ADMIN_UNMUTE: request := &oldMessage.Admin{} @@ -324,8 +327,11 @@ func (s *session) wsToBackend(msg []byte) error { return err } - // TODO: No WS equivalent, call HTTP API. - return fmt.Errorf("event not implemented: %s", header.Event) + return s.apiReq(http.MethodPost, "/api/members/"+request.ID, map[string]any{ + "plugins": map[string]any{ + "chat.can_send": true, + }, + }, nil) default: return fmt.Errorf("unknown event type: %s", header.Event) diff --git a/server/internal/http/legacy/wstoclient.go b/server/internal/http/legacy/wstoclient.go index 89ef2bac..f979bc49 100644 --- a/server/internal/http/legacy/wstoclient.go +++ b/server/internal/http/legacy/wstoclient.go @@ -117,7 +117,7 @@ func (s *session) wsToClient(msg []byte) error { // membersList := []*oldTypes.Member{} - s.sessions = map[string]*oldTypes.Member{} + s.sessions = map[string]*memberStruct{} for id, session := range request.Sessions { if !session.State.IsConnected { continue @@ -127,7 +127,11 @@ func (s *session) wsToClient(msg []byte) error { return err } membersList = append(membersList, member) - s.sessions[id] = member + s.sessions[id] = &memberStruct{ + sent: member.Name != "", + connected: true, + member: member, + } } err = s.toClient(&oldMessage.MembersList{ @@ -271,7 +275,9 @@ func (s *session) wsToClient(msg []byte) error { } // only save session - will be notified on connect - s.sessions[request.ID] = member + s.sessions[request.ID] = &memberStruct{ + member: member, + } return nil @@ -302,19 +308,48 @@ func (s *session) wsToClient(msg []byte) error { } // session profile is expected to change when updating a name after connecting - member, ok := s.sessions[request.ID] - if !ok && member != nil { + m, ok := s.sessions[request.ID] + if !ok || m == nil { return nil } - // we only expect the name to be updated, other fields can't be changed - member.Name = request.Name + // update member profile + member, err := profileToMember(request.ID, request.MemberProfile) + if err != nil { + return err + } - // oldEvent.MEMBER_CONNECTED if not sent already - return s.toClient(&oldMessage.Member{ - Event: oldEvent.MEMBER_CONNECTED, - Member: member, - }) + mutedChanged := m.member.Muted != member.Muted + m.member = member + + if m.connected && !m.sent && member.Name != "" { + m.sent = true + + // oldEvent.MEMBER_CONNECTED if not sent already + err = s.toClient(&oldMessage.Member{ + Event: oldEvent.MEMBER_CONNECTED, + Member: member, + }) + if err != nil { + return err + } + } + + if mutedChanged && member.Muted { + return s.toClient(&oldMessage.AdminTarget{ + Event: oldEvent.ADMIN_MUTE, + ID: "", // TODO: We don't know who (un)muted the user. + Target: request.ID, + }) + } else if mutedChanged && !member.Muted { + return s.toClient(&oldMessage.AdminTarget{ + Event: oldEvent.ADMIN_UNMUTE, + ID: "", // TODO: We don't know who (un)muted the user. + Target: request.ID, + }) + } + + return nil case event.SESSION_STATE: request := &message.SessionState{} @@ -323,19 +358,34 @@ func (s *session) wsToClient(msg []byte) error { return err } - member, ok := s.sessions[request.ID] + m, ok := s.sessions[request.ID] if !ok { return nil } - if request.IsConnected && member != nil && member.Name != "" { - s.sessions[request.ID] = nil + if request.IsConnected { + m.connected = true - // oldEvent.MEMBER_CONNECTED if not sent already - return s.toClient(&oldMessage.Member{ - Event: oldEvent.MEMBER_CONNECTED, - Member: member, - }) + if m.member.Muted { + err = s.toClient(&oldMessage.AdminTarget{ + Event: oldEvent.ADMIN_MUTE, + ID: "", // TODO: We don't know who (un)muted the user. + Target: request.ID, + }) + if err != nil { + return err + } + } + + if !m.sent && m.member.Name != "" { + m.sent = true + + // oldEvent.MEMBER_CONNECTED if not sent already + return s.toClient(&oldMessage.Member{ + Event: oldEvent.MEMBER_CONNECTED, + Member: m.member, + }) + } } if !request.IsConnected {