From 859e9dee5b03027bde42d8889c9c82d2a4e24f60 Mon Sep 17 00:00:00 2001 From: Noah Petherbridge Date: Mon, 17 Feb 2025 12:50:06 -0800 Subject: [PATCH] Send admin reports on /nsfw command + Fixes * On the /nsfw command, BareRTC will issue an admin report to your main website so you have visibility into when this command is used. * On the server side, fix the "Open" command so it will prevent webcams from connecting if the offerer had been Booted by the answerer, in addition to the previous blocks about Mute and Block. Admin users can still connect always. * Add a debug command `/watch username` to manually open somebody's camera on chat. Note: the chat server enforces the permission to actually do so. * Remove the /debug-dangerous-force-deadlock admin command. --- pkg/commands.go | 26 +++++++++++++------------- pkg/handlers.go | 22 +++++++++------------- pkg/subscriber.go | 6 +++++- pkg/webhooks.go | 10 ++++++++++ src/App.vue | 10 ++++++++++ 5 files changed, 47 insertions(+), 27 deletions(-) diff --git a/pkg/commands.go b/pkg/commands.go index 485e6a5..83b074d 100644 --- a/pkg/commands.go +++ b/pkg/commands.go @@ -97,19 +97,6 @@ func (s *Server) ProcessCommand(sub *Subscriber, msg messages.Message) bool { case "/deop": s.DeopCommand(words, sub) return true - case "/debug-dangerous-force-deadlock": - // TEMPORARY debug command to willfully force a deadlock. - s.Broadcast(messages.Message{ - Action: messages.ActionError, - Username: "ChatServer", - Message: "NOTICE: The admin is testing a force deadlock of the chat server; things may become unresponsive soon.", - }) - go func() { - time.Sleep(2 * time.Second) - s.subscribersMu.Lock() - s.subscribersMu.Lock() - }() - return true } } @@ -153,6 +140,19 @@ func (s *Server) NSFWCommand(words []string, sub *Subscriber) { other.SendMe() s.SendWhoList() sub.ChatServer("%s now has their camera marked as Explicit", username) + + // Send an admin report to your main website. + if err := PostWebhookReport(WebhookRequestReport{ + FromUsername: sub.Username, + AboutUsername: username, + Channel: "n/a", + Timestamp: time.Now().Format(time.RFC3339), + Reason: "NSFW Command Issued", + Message: fmt.Sprintf("The admin @%s marks the webcam red for user @%s", sub.Username, username), + Comment: "An admin marked their webcam as explicit.", + }); err != nil { + log.Error("Error delivering a report to your website about the /nsfw command by %s: %s", sub.Username, err) + } } } diff --git a/pkg/handlers.go b/pkg/handlers.go index c1278ee..f1bcfb4 100644 --- a/pkg/handlers.go +++ b/pkg/handlers.go @@ -539,7 +539,7 @@ func (s *Server) IsVideoNotAllowed(sub *Subscriber, other *Subscriber) (bool, st Error: "You do not have permission to view that camera.", }, { - If: (other.Mutes(sub.Username) || other.Blocks(sub)) && !sub.IsAdmin(), + If: (other.Mutes(sub.Username) || other.Boots(sub.Username) || other.Blocks(sub)) && !sub.IsAdmin(), Error: "You do not have permission to view that camera.", }, } @@ -654,18 +654,14 @@ func (s *Server) OnReport(sub *Subscriber, msg messages.Message) { } // Post to the report webhook. - if _, err := PostWebhook(WebhookReport, WebhookRequest{ - Action: WebhookReport, - APIKey: config.Current.AdminAPIKey, - Report: WebhookRequestReport{ - FromUsername: sub.Username, - AboutUsername: msg.Username, - Channel: msg.Channel, - Timestamp: msg.Timestamp, - Reason: msg.Reason, - Message: msg.Message, - Comment: msg.Comment, - }, + if err := PostWebhookReport(WebhookRequestReport{ + FromUsername: sub.Username, + AboutUsername: msg.Username, + Channel: msg.Channel, + Timestamp: msg.Timestamp, + Reason: msg.Reason, + Message: msg.Message, + Comment: msg.Comment, }); err != nil { sub.ChatServer("Error sending the report to the website: %s", err) } else { diff --git a/pkg/subscriber.go b/pkg/subscriber.go index cf44025..c3ab05e 100644 --- a/pkg/subscriber.go +++ b/pkg/subscriber.go @@ -250,10 +250,14 @@ func (sub *Subscriber) SendCut() { // ChatServer is a convenience function to deliver a ChatServer error to the client. func (sub *Subscriber) ChatServer(message string, v ...interface{}) { + if len(v) > 0 { + message = fmt.Sprintf(message, v...) + } + sub.SendJSON(messages.Message{ Action: messages.ActionError, Username: "ChatServer", - Message: fmt.Sprintf(message, v...), + Message: message, }) } diff --git a/pkg/webhooks.go b/pkg/webhooks.go index 857b66a..85da33f 100644 --- a/pkg/webhooks.go +++ b/pkg/webhooks.go @@ -81,3 +81,13 @@ func PostWebhook(name string, payload any) ([]byte, error) { return body, nil } + +// PostWebhookReport posts a report message via webhook to your website. +func PostWebhookReport(report WebhookRequestReport) error { + _, err := PostWebhook(WebhookReport, WebhookRequest{ + Action: WebhookReport, + APIKey: config.Current.AdminAPIKey, + Report: report, + }) + return err +} diff --git a/src/App.vue b/src/App.vue index c0ebd72..6b788f5 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1211,6 +1211,16 @@ export default { return; } + // DEBUGGING: manually open a user camera. Note: chat server will still + // enforce permissions and access. + match = this.message.match(/^\/watch (.+?)$/i); + if (match) { + let username = match[1]; + this.openVideoByUsername(username, true); + this.message = ""; + return; + } + // Clear user chat history. if (this.message.toLowerCase().indexOf("/clear-history") === 0) { this.clearMessageHistory();