mirror of
https://github.com/jech/galene.git
synced 2024-11-25 10:05:58 +01:00
Implement selective clearchat.
This commit is contained in:
parent
eb72069c9b
commit
123d51e011
4 changed files with 129 additions and 15 deletions
|
@ -799,10 +799,42 @@ func (g *Group) WallOps(message string) {
|
||||||
|
|
||||||
const maxChatHistory = 50
|
const maxChatHistory = 50
|
||||||
|
|
||||||
func (g *Group) ClearChatHistory() {
|
// deleteFunc is just like slices.DeleteFunc.
|
||||||
|
// Remove this once we require Go 1.21.
|
||||||
|
func deleteFunc[S ~[]E, E any](s S, f func(E) bool) S {
|
||||||
|
i := 0
|
||||||
|
for i = range s {
|
||||||
|
if f(s[i]) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if i >= len(s) {
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
for j := i + 1; j < len(s); j++ {
|
||||||
|
if v := s[j]; !f(v) {
|
||||||
|
s[i] = v
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var zero E
|
||||||
|
for j := i; j < len(s); j++ {
|
||||||
|
s[j] = zero
|
||||||
|
}
|
||||||
|
return s[:i]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *Group) ClearChatHistory(id string, userId string) {
|
||||||
g.mu.Lock()
|
g.mu.Lock()
|
||||||
defer g.mu.Unlock()
|
defer g.mu.Unlock()
|
||||||
|
if id == "" && userId == "" {
|
||||||
g.history = nil
|
g.history = nil
|
||||||
|
return
|
||||||
|
}
|
||||||
|
g.history = deleteFunc(g.history, func(e ChatHistoryEntry) bool {
|
||||||
|
return e.Source == userId && (id == "" || e.Id == id)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Group) AddToChatHistory(id, source string, user *string, time time.Time, kind string, value interface{}) {
|
func (g *Group) AddToChatHistory(id, source string, user *string, time time.Time, kind string, value interface{}) {
|
||||||
|
|
|
@ -4,9 +4,9 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
"sort"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGroup(t *testing.T) {
|
func TestGroup(t *testing.T) {
|
||||||
|
@ -54,7 +54,10 @@ func TestChatHistory(t *testing.T) {
|
||||||
}
|
}
|
||||||
user := "user"
|
user := "user"
|
||||||
for i := 0; i < 2*maxChatHistory; i++ {
|
for i := 0; i < 2*maxChatHistory; i++ {
|
||||||
g.AddToChatHistory("id", "source", &user, time.Now(), "",
|
g.AddToChatHistory(
|
||||||
|
fmt.Sprintf("id-%v", i),
|
||||||
|
fmt.Sprintf("source-%v", i%4),
|
||||||
|
&user, time.Now(), "",
|
||||||
fmt.Sprintf("%v", i),
|
fmt.Sprintf("%v", i),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -63,10 +66,33 @@ func TestChatHistory(t *testing.T) {
|
||||||
t.Errorf("Expected %v, got %v", maxChatHistory, len(g.history))
|
t.Errorf("Expected %v, got %v", maxChatHistory, len(g.history))
|
||||||
}
|
}
|
||||||
for i, s := range h {
|
for i, s := range h {
|
||||||
e := fmt.Sprintf("%v", i+maxChatHistory)
|
j := i + maxChatHistory
|
||||||
if s.Value.(string) != e {
|
if s.Id != fmt.Sprintf("id-%v", j) {
|
||||||
t.Errorf("Expected %v, got %v", e, s)
|
t.Errorf("Expected %v, got %v", j, s.Id)
|
||||||
}
|
}
|
||||||
|
if s.Source != fmt.Sprintf("source-%v", j%4) {
|
||||||
|
t.Errorf("Expected %v, got %v", j%4, s.Id)
|
||||||
|
}
|
||||||
|
if s.Value.(string) != fmt.Sprintf("%v", j) {
|
||||||
|
t.Errorf("Expected %v, got %v", j, s.Value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
l := len(h)
|
||||||
|
j := maxChatHistory + 4
|
||||||
|
g.ClearChatHistory(
|
||||||
|
fmt.Sprintf("id-%v", j), fmt.Sprintf("source-%v", j%4),
|
||||||
|
)
|
||||||
|
if lh := len(g.GetChatHistory()); lh != l-1 {
|
||||||
|
t.Errorf("Expected %v, got %v", l-1, lh)
|
||||||
|
}
|
||||||
|
g.ClearChatHistory("", fmt.Sprintf("source-%v", j%4))
|
||||||
|
if lh := len(g.GetChatHistory()); lh != l*3/4 {
|
||||||
|
t.Errorf("Expected %v, got %v", l*3/4, lh)
|
||||||
|
}
|
||||||
|
g.ClearChatHistory("", "");
|
||||||
|
if lh := len(g.GetChatHistory()); lh != 0 {
|
||||||
|
t.Errorf("Expected 0, got %v", lh)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1636,10 +1636,27 @@ func handleClientMessage(c *webClient, m clientMessage) error {
|
||||||
if !member("op", c.permissions) {
|
if !member("op", c.permissions) {
|
||||||
return c.error(group.UserError("not authorised"))
|
return c.error(group.UserError("not authorised"))
|
||||||
}
|
}
|
||||||
g.ClearChatHistory()
|
var id, userId string
|
||||||
|
if m.Value != nil {
|
||||||
|
value, ok := m.Value.(map[string]any)
|
||||||
|
if !ok {
|
||||||
|
return c.error(group.UserError(
|
||||||
|
"bad value in clearchat",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
id, _ = value["id"].(string)
|
||||||
|
userId, _ = value["userId"].(string)
|
||||||
|
if userId == "" && id != "" {
|
||||||
|
return c.error(group.UserError(
|
||||||
|
"bad value in clearchat",
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.ClearChatHistory(id, userId)
|
||||||
m := clientMessage{
|
m := clientMessage{
|
||||||
Type: "usermessage",
|
Type: "usermessage",
|
||||||
Kind: "clearchat",
|
Kind: "clearchat",
|
||||||
|
Value: m.Value,
|
||||||
Privileged: true,
|
Privileged: true,
|
||||||
}
|
}
|
||||||
err := broadcast(g.GetClients(nil), m)
|
err := broadcast(g.GetClients(nil), m)
|
||||||
|
|
|
@ -2781,13 +2781,16 @@ function gotUserMessage(id, dest, username, time, privileged, kind, error, messa
|
||||||
let by = username ? ' by ' + username : '';
|
let by = username ? ' by ' + username : '';
|
||||||
displayWarning(`You have been muted${by}`);
|
displayWarning(`You have been muted${by}`);
|
||||||
break;
|
break;
|
||||||
case 'clearchat':
|
case 'clearchat': {
|
||||||
if(!privileged) {
|
if(!privileged) {
|
||||||
console.error(`Got unprivileged message of kind ${kind}`);
|
console.error(`Got unprivileged message of kind ${kind}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
clearChat();
|
let id = message && message.id;
|
||||||
|
let userId = message && message.userId;
|
||||||
|
clearChat(id, userId);
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 'token':
|
case 'token':
|
||||||
if(!privileged) {
|
if(!privileged) {
|
||||||
console.error(`Got unprivileged message of kind ${kind}`);
|
console.error(`Got unprivileged message of kind ${kind}`);
|
||||||
|
@ -3071,17 +3074,31 @@ function chatMessageMenu(elt) {
|
||||||
serverConnection.permissions.indexOf('op') >= 0))
|
serverConnection.permissions.indexOf('op') >= 0))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
let messageId = elt.dataset.id;
|
||||||
let peerId = elt.dataset.peerId;
|
let peerId = elt.dataset.peerId;
|
||||||
if(!peerId)
|
if(!peerId)
|
||||||
return;
|
return;
|
||||||
let username = elt.dataset.username;
|
let username = elt.dataset.username;
|
||||||
let u = username ? ' ' + username : '';
|
let u = username || 'user';
|
||||||
|
|
||||||
let items = [];
|
let items = [];
|
||||||
items.push({label: 'Identify user' + u, onClick: () => {
|
if(messageId)
|
||||||
|
items.push({label: 'Delete message', onClick: () => {
|
||||||
|
serverConnection.groupAction('clearchat', {
|
||||||
|
id: messageId,
|
||||||
|
userId: peerId,
|
||||||
|
});
|
||||||
|
}});
|
||||||
|
items.push({label: `Delete all from ${u}`,
|
||||||
|
onClick: () => {
|
||||||
|
serverConnection.groupAction('clearchat', {
|
||||||
|
userId: peerId,
|
||||||
|
});
|
||||||
|
}});
|
||||||
|
items.push({label: `Identify ${u}`, onClick: () => {
|
||||||
serverConnection.userAction('identify', peerId);
|
serverConnection.userAction('identify', peerId);
|
||||||
}});
|
}});
|
||||||
items.push({label: 'Kick out user' + u, onClick: () => {
|
items.push({label: `Kick out ${u}`, onClick: () => {
|
||||||
serverConnection.userAction('kick', peerId);
|
serverConnection.userAction('kick', peerId);
|
||||||
}});
|
}});
|
||||||
|
|
||||||
|
@ -3098,9 +3115,31 @@ function localMessage(message) {
|
||||||
return addToChatbox(null, null, null, null, new Date(), false, false, '', message);
|
return addToChatbox(null, null, null, null, new Date(), false, false, '', message);
|
||||||
}
|
}
|
||||||
|
|
||||||
function clearChat() {
|
/**
|
||||||
|
* @param {string} [id]
|
||||||
|
* @param {string} [userId]
|
||||||
|
*/
|
||||||
|
function clearChat(id, userId) {
|
||||||
lastMessage = {};
|
lastMessage = {};
|
||||||
document.getElementById('box').textContent = '';
|
|
||||||
|
let box = document.getElementById('box');
|
||||||
|
if(!id && !userId) {
|
||||||
|
box.textContent = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let elts = box.children;
|
||||||
|
for(let i = 0; i < elts.length; i++) {
|
||||||
|
let row = elts.item(i);
|
||||||
|
if(!(row instanceof HTMLDivElement))
|
||||||
|
continue;
|
||||||
|
let div = row.firstChild;
|
||||||
|
console.log(div);
|
||||||
|
if(!(div instanceof HTMLDivElement))
|
||||||
|
continue;
|
||||||
|
if((!id || div.dataset.id === id) && div.dataset.peerId === userId)
|
||||||
|
box.removeChild(row);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in a new issue