diff --git a/pkg/controller/api/barertc/barertc_webhooks.go b/pkg/controller/api/barertc/barertc_webhooks.go new file mode 100644 index 0000000..e4e45e8 --- /dev/null +++ b/pkg/controller/api/barertc/barertc_webhooks.go @@ -0,0 +1,129 @@ +package barertc + +import ( + "fmt" + "net/http" + + "code.nonshy.com/nonshy/website/pkg/config" + "code.nonshy.com/nonshy/website/pkg/controller/api" + "code.nonshy.com/nonshy/website/pkg/log" + "code.nonshy.com/nonshy/website/pkg/mail" + "code.nonshy.com/nonshy/website/pkg/models" +) + +// WebhookRequest is a JSON request wrapper around all webhook messages. +type WebhookRequest struct { + Action string + APIKey string + + // Relevant body per request. + Report WebhookRequestReport `json:",omitempty"` +} + +// WebhookRequestReport is the body for 'report' webhook messages. +type WebhookRequestReport struct { + FromUsername string + AboutUsername string + Channel string + Timestamp string + Reason string + Message string + Comment string +} + +// Report webhook controller. +func Report() http.HandlerFunc { + + // Response JSON schema. + type Response struct { + OK bool `json:"OK"` + Error string `json:"error,omitempty"` + } + + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + if r.Method != http.MethodPost { + api.SendJSON(w, http.StatusNotAcceptable, Response{ + Error: "POST method only", + }) + return + } + + // Parse request payload. + var req WebhookRequest + if err := api.ParseJSON(r, &req); err != nil { + api.SendJSON(w, http.StatusBadRequest, Response{ + Error: fmt.Sprintf("Error with request payload: %s", err), + }) + return + } + + // Validate the AdminAPIKey. + if req.APIKey != config.Current.CronAPIKey { + api.SendJSON(w, http.StatusForbidden, Response{ + Error: "Invalid API Key", + }) + return + } + + // Get the report out. + report := req.Report + + log.Debug("Got chat report: %+v", report) + + // Create an admin Feedback model. + fb := &models.Feedback{ + Intent: "report", + Subject: "report.chat", + Message: fmt.Sprintf( + "A message was reported on the chat room!\n\n"+ + "* From username: [%s](/u/%s)\n"+ + "* About username: [%s](/u/%s)\n"+ + "* Channel: **%s**\n"+ + "* Timestamp: %s\n"+ + "* Classification: %s\n"+ + "* User comment: %s\n\n"+ + "- - - - -\n\n"+ + "The reported message on chat was:\n\n%s", + report.FromUsername, report.FromUsername, + report.AboutUsername, report.AboutUsername, + report.Channel, + report.Timestamp, + report.Reason, + report.Comment, + report.Message, + ), + } + + // Get the Reply-To user if possible. + if user, err := models.FindUser(report.FromUsername); err == nil { + fb.UserID = user.ID + } + + // Save the feedback. + if err := models.CreateFeedback(fb); err != nil { + log.Error("Couldn't save feedback from BareRTC report endpoint: %s", err) + } + + // Email the admins. + if err := mail.Send(mail.Message{ + To: config.Current.AdminEmail, + Subject: "Chat Room Report", + Template: "email/contact_admin.html", + Data: map[string]interface{}{ + "Title": "Chat Room Report", + "Intent": fb.Intent, + "Subject": fb.Subject, + "Message": "Please check on the admin dashboard of nonshy.com", + "BaseURL": config.Current.BaseURL, + "AdminURL": config.Current.BaseURL + "/admin/feedback", + }, + }); err != nil { + log.Error("/v1/barertc/report page: couldn't send email: %s", err) + } + + // Send success response. + api.SendJSON(w, http.StatusOK, Response{ + OK: true, + }) + }) +} diff --git a/pkg/router/router.go b/pkg/router/router.go index d88bc78..11be908 100644 --- a/pkg/router/router.go +++ b/pkg/router/router.go @@ -8,6 +8,7 @@ import ( "code.nonshy.com/nonshy/website/pkg/controller/account" "code.nonshy.com/nonshy/website/pkg/controller/admin" "code.nonshy.com/nonshy/website/pkg/controller/api" + "code.nonshy.com/nonshy/website/pkg/controller/api/barertc" "code.nonshy.com/nonshy/website/pkg/controller/block" "code.nonshy.com/nonshy/website/pkg/controller/chat" "code.nonshy.com/nonshy/website/pkg/controller/comment" @@ -96,6 +97,7 @@ func New() http.Handler { mux.Handle("/v1/notifications/read", middleware.LoginRequired(api.ReadNotification())) mux.Handle("/v1/notifications/delete", middleware.LoginRequired(api.ClearNotification())) mux.Handle("/v1/comment-photos/remove-orphaned", api.RemoveOrphanedCommentPhotos()) + mux.Handle("/v1/barertc/report", barertc.Report()) // Static files. mux.Handle("/static/", http.StripPrefix("/static/", http.FileServer(http.Dir(config.StaticPath))))