Show when booted admins reopen your camera

* As chat admins require the ability to moderate the chat room, they
  were allowed to reopen user webcams even after they had been booted.
  But a conflict with front-end logic meant the user wouldn't be
  notified when the booted admin reopened their camera.
* This bug has been fixed and front-end messaging updated to make it
  clear what the difference is when booting a regular vs. admin user.
This commit is contained in:
Noah 2025-07-16 21:08:21 -07:00
parent 30d5d7ed28
commit ca2bbba38c
3 changed files with 28 additions and 22 deletions

View File

@ -551,15 +551,6 @@ func (s *Server) OnOpen(sub *Subscriber, msg messages.Message) {
secret := util.RandomString(16)
log.Info("WebRTC: %s opens %s with secret %s", sub.Username, other.Username, secret)
// If the current user is an admin and was booted or muted, inform them.
if sub.IsAdmin() {
if other.Boots(sub.Username) {
sub.ChatServer("Note: %s had booted you off their camera before, and won't be notified of your watch.", other.Username)
} else if other.Mutes(sub.Username) {
sub.ChatServer("Note: %s had muted you before, and won't be notified of your watch.", other.Username)
}
}
// Ring the target of this request and give them the secret.
other.SendJSON(messages.Message{
Action: messages.ActionRing,

View File

@ -1735,13 +1735,6 @@ export default {
},
pushHistory({ channel, username, message, action = "message", isChatServer, isChatClient, messageID, timestamp = null, unshift = false }) {
// Ignore possibly-confusing ChatServer messages sent to admins.
// TODO: add a 'super-admin' tier separately to operator that still sees these.
if (isChatServer && (message.match(/ has booted you off of their camera!$/) || message.match(/ had booted you off their camera before, and won't be notified of your watch.$/))) {
// Redirect it to the debug log channel.
channel = DebugChannelID;
}
// Default channel = your current channel.
if (!channel) {
channel = this.channel;

View File

@ -657,9 +657,6 @@ class WebRTCController {
}).catch(this.DebugChannel);
},
onWatch(msg) {
// The user has our video feed open now.
if (this.isBootedAdmin(msg.username)) return;
// Notify in chat if this was the first watch (viewer may send multiple per each track they received)
if (this.prefs.watchNotif && this.webcam.watching[msg.username] != true) {
this.ChatServer(
@ -1471,19 +1468,38 @@ class WebRTCController {
// Check if they are currently rate limited from pre-emptive boots of folks
// who are not even watching their camera yet.
if (this.rateLimitPreemptiveBoots(username, false)) return;
// Get the target user.
const user = this.getUser(username);
// The dialog message, which varies if the booted user is an admin.
let message = `Kick ${username} off your camera? `;
if (user.op) {
message += "Note: chat operators will be able to reopen your webcam."
} else {
message += `This will also prevent them from seeing that your camera `+
` is active for the remainder of your chat session.`
}
// Boot them off our webcam.
this.modalConfirm({
title: "Boot user",
icon: "fa fa-user-xmark",
message: `Kick ${username} off your camera? This will also prevent them ` +
`from seeing that your camera is active for the remainder of your ` +
`chat session.`
message: message,
}).then(() => {
// Ping their rate limiter.
if (this.rateLimitPreemptiveBoots(username, true)) return;
this.doBootUser(username);
if (user.op) {
this.ChatClient(
`You have booted ${username}<sup class="fa fa-peace has-text-warning is-size-7"></sup> ` +
`off your camera. <strong>Note:</strong> Chat operators ` +
`will be able to reopen your webcam.`,
);
return;
}
this.ChatClient(
`You have booted ${username} off your camera. They will no longer be able ` +
@ -1509,6 +1525,12 @@ class WebRTCController {
delete (this.webcam.watching[username]);
},
isBooted(username) {
// Admins never count as booted.
if (this.isBootedAdmin(username)) {
return false;
}
return this.WebRTC.booted[username] === true;
},
isBootedAdmin(username) {