diff --git a/group/group.go b/group/group.go index 3926328..6a232c9 100644 --- a/group/group.go +++ b/group/group.go @@ -83,7 +83,7 @@ type ChatHistoryEntry struct { User string Time int64 Kind string - Value string + Value interface{} } const ( @@ -620,7 +620,7 @@ func (g *Group) ClearChatHistory() { g.history = nil } -func (g *Group) AddToChatHistory(id, user string, time int64, kind, value string) { +func (g *Group) AddToChatHistory(id, user string, time int64, kind string, value interface{}) { g.mu.Lock() defer g.mu.Unlock() diff --git a/rtpconn/webclient.go b/rtpconn/webclient.go index 20b3da5..9b07c16 100644 --- a/rtpconn/webclient.go +++ b/rtpconn/webclient.go @@ -27,13 +27,12 @@ func errorToWSCloseMessage(id string, err error) (*clientMessage, []byte) { code = websocket.CloseNormalClosure case group.ProtocolError: code = websocket.CloseProtocolError - s := e.Error() m = &clientMessage{ Type: "usermessage", Kind: "error", Dest: id, Privileged: true, - Value: &s, + Value: e.Error(), } text = e.Error() case group.UserError, group.KickError: @@ -171,7 +170,7 @@ type clientMessage struct { Privileged bool `json:"privileged,omitempty"` Permissions *group.ClientPermissions `json:"permissions,omitempty"` Group string `json:"group,omitempty"` - Value *string `json:"value,omitempty"` + Value interface{} `json:"value,omitempty"` Time int64 `json:"time,omitempty"` Offer *webrtc.SessionDescription `json:"offer,omitempty"` Answer *webrtc.SessionDescription `json:"answer,omitempty"` @@ -808,11 +807,10 @@ func clientLoop(c *webClient, ws *websocket.Conn) error { } } case addLabelAction: - label := a.label c.write(clientMessage{ Type: "label", Id: a.id, - Value: &label, + Value: a.label, }) case pushConnsAction: g := c.group @@ -1063,7 +1061,7 @@ func handleClientMessage(c *webClient, m clientMessage) error { Kind: "fail", Group: m.Group, Permissions: &group.ClientPermissions{}, - Value: &s, + Value: s, }) } if redirect := g.Redirect(); redirect != "" { @@ -1074,7 +1072,7 @@ func handleClientMessage(c *webClient, m clientMessage) error { Kind: "redirect", Group: m.Group, Permissions: &group.ClientPermissions{}, - Value: &redirect, + Value: redirect, }) } c.group = g @@ -1090,13 +1088,12 @@ func handleClientMessage(c *webClient, m clientMessage) error { } h := c.group.GetChatHistory() for _, m := range h { - message := m.Value err := c.write(clientMessage{ Type: "chat", Id: m.Id, Username: m.User, Time: m.Time, - Value: &message, + Value: m.Value, Kind: m.Kind, }) if err != nil { @@ -1184,12 +1181,9 @@ func handleClientMessage(c *webClient, m clientMessage) error { tm := group.ToJSTime(time.Now()) if m.Type == "chat" { - if m.Value == nil { - return group.ProtocolError("missing value") - } if m.Dest == "" { g.AddToChatHistory( - m.Id, m.Username, tm, m.Kind, *m.Value, + m.Id, m.Username, tm, m.Kind, m.Value, ) } } @@ -1249,8 +1243,9 @@ func handleClientMessage(c *webClient, m clientMessage) error { return c.error(group.UserError("not authorised")) } message := "" - if m.Value != nil { - message = *m.Value + v, ok := m.Value.(string) + if ok { + message = v } g.SetLocked(m.Kind == "lock", message) case "record": @@ -1299,7 +1294,7 @@ func handleClientMessage(c *webClient, m clientMessage) error { Dest: c.id, Username: "Server", Time: group.ToJSTime(time.Now()), - Value: &s, + Value: s, }) default: return group.ProtocolError("unknown group action") @@ -1329,8 +1324,9 @@ func handleClientMessage(c *webClient, m clientMessage) error { return c.error(group.UserError("not authorised")) } message := "" - if m.Value != nil { - message = *m.Value + v, ok := m.Value.(string) + if ok { + message = v } err := kickClient(g, m.Id, m.Username, m.Dest, message) if err != nil { @@ -1420,7 +1416,7 @@ func (c *webClient) Warn(oponly bool, message string) error { Kind: "warning", Dest: c.id, Privileged: true, - Value: &message, + Value: message, }) } @@ -1456,13 +1452,12 @@ func (c *webClient) close(data []byte) error { func errorMessage(id string, err error) *clientMessage { switch e := err.(type) { case group.UserError: - message := e.Error() return &clientMessage{ Type: "usermessage", Kind: "error", Dest: id, Privileged: true, - Value: &message, + Value: e.Error(), } case group.KickError: message := e.Message @@ -1476,7 +1471,7 @@ func errorMessage(id string, err error) *clientMessage { Username: e.Username, Dest: id, Privileged: true, - Value: &message, + Value: message, } default: return nil diff --git a/static/galene.js b/static/galene.js index 452831d..0aa24fc 100644 --- a/static/galene.js +++ b/static/galene.js @@ -1549,6 +1549,43 @@ async function gotJoined(kind, group, perms, message) { } } +/** + * @param {string} id + * @param {string} dest + * @param {string} username + * @param {number} time + * @param {boolean} privileged + * @param {string} kind + * @param {unknown} message + */ +function gotUserMessage(id, dest, username, time, privileged, kind, message) { + switch(kind) { + case 'error': + case 'warning': + case 'info': + let from = id ? (username || 'Anonymous') : 'The Server'; + if(privileged) + displayError(`${from} said: ${message}`, kind); + else + console.error(`Got unprivileged message of kind ${kind}`); + break; + case 'mute': + console.log(id, dest, username); + if(privileged) { + setLocalMute(true, true); + let by = username ? ' by ' + username : ''; + displayWarning(`You have been muted${by}`); + } else { + console.error(`Got unprivileged message of kind ${kind}`); + } + break; + default: + console.warn(`Got unknown user message ${kind}`); + break; + } +}; + + const urlRegexp = /https?:\/\/[-a-zA-Z0-9@:%/._\\+~#&()=?]+[-a-zA-Z0-9@:%/_\\+~#&()=]/g; /** @@ -1622,7 +1659,7 @@ let lastMessage = {}; * @param {string} nick * @param {number} time * @param {string} kind - * @param {string} message + * @param {unknown} message */ function addToChatbox(peerId, dest, nick, time, privileged, kind, message) { let userpass = getUserPass(); @@ -1641,7 +1678,7 @@ function addToChatbox(peerId, dest, nick, time, privileged, kind, message) { container.classList.add('message-private'); if(kind !== 'me') { - let p = formatLines(message.split('\n')); + let p = formatLines(message.toString().split('\n')); let doHeader = true; if(!peerId && !dest && !nick) { doHeader = false; @@ -1689,7 +1726,7 @@ function addToChatbox(peerId, dest, nick, time, privileged, kind, message) { user.textContent = nick || '(anon)'; user.classList.add('message-me-user'); let content = document.createElement('span'); - formatLine(message).forEach(elt => { + formatLine(message.toString()).forEach(elt => { content.appendChild(elt); }); content.classList.add('message-me-content'); @@ -2300,32 +2337,8 @@ async function serverConnect() { serverConnection.onjoined = gotJoined; serverConnection.onchat = addToChatbox; serverConnection.onclearchat = clearChat; - serverConnection.onusermessage = function(id, dest, username, time, privileged, kind, message) { - switch(kind) { - case 'error': - case 'warning': - case 'info': - let from = id ? (username || 'Anonymous') : 'The Server'; - if(privileged) - displayError(`${from} said: ${message}`, kind); - else - console.error(`Got unprivileged message of kind ${kind}`); - break; - case 'mute': - console.log(id, dest, username); - if(privileged) { - setLocalMute(true, true); - let by = username ? ' by ' + username : ''; - displayWarning(`You have been muted${by}`); - } else { - console.error(`Got unprivileged message of kind ${kind}`); - } - break; - default: - console.warn(`Got unknown user message ${kind}`); - break; - } - }; + serverConnection.onusermessage = gotUserMessage; + let url = `ws${location.protocol === 'https:' ? 's' : ''}://${location.host}/ws`; try { await serverConnection.connect(url); diff --git a/static/protocol.js b/static/protocol.js index 18f83a9..9a67668 100644 --- a/static/protocol.js +++ b/static/protocol.js @@ -142,7 +142,7 @@ function ServerConnection() { /** * onchat is called whenever a new chat message is received. * - * @type {(this: ServerConnection, id: string, dest: string, username: string, time: number, privileged: boolean, kind: string, message: string) => void} + * @type {(this: ServerConnection, id: string, dest: string, username: string, time: number, privileged: boolean, kind: string, message: unknown) => void} */ this.onchat = null; /** @@ -154,7 +154,7 @@ function ServerConnection() { * 'id' is non-null, 'privileged' indicates whether the message was * sent by an operator. * - * @type {(this: ServerConnection, id: string, dest: string, username: string, time: number, privileged: boolean, kind: string, message: string) => void} + * @type {(this: ServerConnection, id: string, dest: string, username: string, time: number, privileged: boolean, kind: string, message: unknown) => void} */ this.onusermessage = null; /** @@ -177,7 +177,7 @@ function ServerConnection() { * @property {boolean} [privileged] * @property {Object} [permissions] * @property {string} [group] - * @property {string} [value] + * @property {unknown} [value] * @property {RTCSessionDescriptionInit} [offer] * @property {RTCSessionDescriptionInit} [answer] * @property {RTCIceCandidate} [candidate]