-
Notifications
You must be signed in to change notification settings - Fork 9
Add enforcement notifications, public logs, and metrics tracking #195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR enhances enforcement action transparency by adding DM notifications, public logs, and metrics tracking while protecting moderator privacy. Players will now receive detailed direct messages explaining their enforcement actions instead of generic "Kicked from server" messages, and can view active suspensions prominently in the /whoami command.
Key Changes:
- Added standardized rule categories, notification messaging, and opt-in public visibility tracking to enforcement records
- Implemented DM notification system with Discord message formatting and delivery status tracking
- Enhanced
/whoamidisplay with prominent active suspension warnings at the top with red color coding
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
server/evr_enforcement_record.go |
Added new fields for rule tracking, public visibility, and DM notification status; implemented GetNotificationMessage() for formatted user notifications and GetStandardEnforcementRules() for standardized rule categories |
server/evr_enforcement_journal.go |
Added AddRecordWithOptions() for extended record creation with new fields; implemented SendEnforcementNotification() for DM delivery and UpdateRecordNotificationStatus() for tracking notification attempts |
server/evr_enforcement_public_log.go |
New file implementing opt-in public enforcement logs with privacy filtering (excludes moderator identity and internal notes), 90-day retention, and public read permissions |
server/evr_enforcement_public_log_test.go |
Comprehensive test coverage for public log functionality including privacy filtering, retention cleanup, and active/voided entry filtering |
server/evr_enforcement_metrics.go |
New file implementing enforcement metrics tracking with daily statistics, unique user counts, notification success/failure rates, and rule-based categorization |
server/evr_enforcement_notification_test.go |
Test coverage for notification message generation, record options, notification status tracking, and backward compatibility |
server/evr_discord_appbot_whoami.go |
Enhanced suspension embed to display active suspensions prominently at top with warning indicators, red color coding, and updated footer text prompting users to check DMs |
server/evr_discord_appbot_handlers.go |
Integrated notification sending, public log recording, and metrics tracking into the enforcement action handler with appropriate error handling |
server/evr_matchmaker_process_test.go |
Removed unused zap import (code cleanup) |
| // recordActionForDate records an action for today's date | ||
| func (m *EnforcementActionMetrics) recordActionForDate(userID, actionType string) { | ||
| dateStr := time.Now().UTC().Format("2006-01-02") | ||
|
|
||
| daily, exists := m.ActionsByDate[dateStr] | ||
| if !exists { | ||
| daily = DailyMetrics{ | ||
| Date: dateStr, | ||
| AffectedUsers: make(map[string]bool), | ||
| } | ||
| } | ||
|
|
||
| switch actionType { | ||
| case "kick": | ||
| daily.Kicks++ | ||
| case "suspension": | ||
| daily.Suspensions++ | ||
| case "voiding": | ||
| daily.Voidings++ | ||
| } | ||
|
|
||
| // Track unique users | ||
| if userID != "" { | ||
| if daily.AffectedUsers == nil { | ||
| daily.AffectedUsers = make(map[string]bool) | ||
| } | ||
| daily.AffectedUsers[userID] = true | ||
| daily.UniqueUsersAffected = len(daily.AffectedUsers) | ||
| } | ||
|
|
||
| m.ActionsByDate[dateStr] = daily |
Copilot
AI
Dec 13, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The AffectedUsers field in DailyMetrics is marked with json:"-" so it won't be serialized to storage. When metrics are loaded from storage and deserialized, this field will be nil. However, at lines 143-146, the code checks if AffectedUsers is nil and initializes it if needed before using it. This means the UniqueUsersAffected count stored in the JSON will be preserved, but the actual set of user IDs will be lost after a save/load cycle. This could lead to undercounting unique users if metrics are loaded and then new actions are added, since the previously affected users won't be in the set anymore. Consider either serializing this field (with appropriate privacy controls) or recalculating the unique count differently.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in commit 576ab46. Changed the logic to increment UniqueUsersAffected only when adding a new user to the session map, rather than recalculating from the map length. This preserves the stored count across save/load cycles while still tracking unique users accurately within each session. Added comments to document this behavior.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Andrew Bates <a@sprock.io>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Andrew Bates <a@sprock.io>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Andrew Bates <a@sprock.io>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> Signed-off-by: Andrew Bates <a@sprock.io>
|
@copilot apply changes based on the comments in this thread |
Co-authored-by: thesprockee <962164+thesprockee@users.noreply.github.com>
Changes applied in commit 576ab46. The metrics unique user counting has been fixed to properly handle save/load cycles by incrementing the count only when adding new users rather than recalculating from the length of the map. This prevents undercounting after a reload since the AffectedUsers map is not serialized. |
Kick Enforcement and Notification Improvements ✅
This PR implements comprehensive improvements to the kick enforcement and notification system based on community feedback. All requirements from the issue have been successfully addressed.
✅ Completed Features
1. Enhanced Enforcement Records
RuleViolatedfield with standardized rule categoriesIsPubliclyVisibleflag for opt-in public logsDMNotificationSentandDMNotificationAttemptedtracking2. Direct Message Notifications
/whoamifor full details3. Enhanced
/whoamiDisplay4. Public Enforcement Logs
5. Moderator UX Improvements
AddRecordWithOptions()for advanced enforcement creation6. Metrics and Tracking
7. Comprehensive Testing
8. Security & Code Quality
🎯 Impact
Player Transparency:
/whoamimakes it easy to check enforcement statusModerator Tools:
Privacy & Fairness:
Educational Focus:
/whoamiprompt guides players to more informationOriginal prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.