13 KiB
Mood System Analysis & Issues
Overview
After examining the Miku Discord bot's mood, mood rotation, and emoji nickname system, I've identified several critical issues that explain why they don't function correctly.
System Architecture
1. Dual Mood System
The bot has TWO independent mood systems:
- DM Mood: Global mood for all direct messages (
globals.DM_MOOD) - Server Mood: Per-server mood tracked in
ServerConfigobjects
2. Mood Rotation
- DM Mood: Rotates every 2 hours (via
rotate_dm_mood()) - Server Mood: Rotates every 1 hour per server (via
rotate_server_mood())
3. Nickname System
Nicknames show mood emojis via the MOOD_EMOJIS dictionary in utils/moods.py
🔴 CRITICAL ISSUES FOUND
Issue #1: Nickname Update Logic Conflict
Location: utils/moods.py lines 143-163
Problem: The update_all_server_nicknames() function uses DM mood to update all server nicknames:
async def update_all_server_nicknames():
"""Update nickname for all servers to show current DM mood"""
try:
mood = globals.DM_MOOD.lower() # ❌ Uses DM mood
print(f"🔍 DM mood is: {mood}")
emoji = MOOD_EMOJIS.get(mood, "")
nickname = f"Hatsune Miku{emoji}"
print(f"🔍 New nickname will be: {nickname}")
for guild in globals.client.guilds: # ❌ Updates ALL servers
me = guild.get_member(globals.BOT_USER.id)
if me is not None:
try:
await me.edit(nick=nickname)
Impact:
- Server nicknames show DM mood instead of their own server mood
- All servers get the same nickname despite having independent moods
- The per-server mood system is functionally broken for nicknames
Expected Behavior: Each server should display its own mood emoji based on server_config.current_mood_name
Issue #2: DM Mood Rotation Updates Server Nicknames
Location: utils/moods.py lines 121-142
Problem: The rotate_dm_mood() function is called by the DM mood scheduler but doesn't update any nicknames:
async def rotate_dm_mood():
"""Rotate DM mood automatically (no keyword triggers)"""
try:
old_mood = globals.DM_MOOD
new_mood = old_mood
attempts = 0
while new_mood == old_mood and attempts < 5:
new_mood = random.choice(globals.AVAILABLE_MOODS)
attempts += 1
globals.DM_MOOD = new_mood
globals.DM_MOOD_DESCRIPTION = load_mood_description(new_mood)
print(f"🔄 DM mood rotated from {old_mood} to {new_mood}")
# Note: We don't update server nicknames here because servers have their own independent moods.
# DM mood only affects direct messages to users.
Impact:
- Comment says "servers have their own independent moods"
- But
update_all_server_nicknames()uses DM mood anyway - Inconsistent design philosophy
Issue #3: Incorrect Nickname Function Called After Server Mood Rotation
Location: server_manager.py line 647
Problem: After rotating a server's mood, the system calls update_server_nickname() which is correct, BUT there's confusion in the codebase:
async def rotate_server_mood(guild_id: int):
"""Rotate mood for a specific server"""
try:
# ... mood rotation logic ...
server_manager.set_server_mood(guild_id, new_mood_name, load_mood_description(new_mood_name))
# Update nickname for this specific server
await update_server_nickname(guild_id) # ✅ Correct function
print(f"🔄 Rotated mood for server {guild_id} from {old_mood_name} to {new_mood_name}")
Analysis: This part is actually correct, but...
Issue #4: nickname_mood_emoji() Function Ambiguity
Location: utils/moods.py lines 165-171
Problem: This function can call either server-specific OR all-server update:
async def nickname_mood_emoji(guild_id: int = None):
"""Update nickname with mood emoji for a specific server or all servers"""
if guild_id is not None:
# Update nickname for specific server
await update_server_nickname(guild_id)
else:
# Update nickname for all servers (using DM mood)
await update_all_server_nicknames()
Impact:
- If called without
guild_id, it overwrites all server nicknames with DM mood - Creates confusion about which mood system is active
- This function might be called incorrectly from various places
Issue #5: Mood Detection in bot.py May Not Trigger Nickname Updates
Location: bot.py lines 469-512
Problem: When mood is auto-detected from keywords in messages, nickname updates are scheduled but may race with the rotation system:
if detected and detected != server_config.current_mood_name:
print(f"🔄 Auto mood detection for server {message.guild.name}: {server_config.current_mood_name} -> {detected}")
# Block direct transitions to asleep unless from sleepy
if detected == "asleep" and server_config.current_mood_name != "sleepy":
print("❌ Ignoring asleep mood; server wasn't sleepy before.")
else:
# Update server mood
server_manager.set_server_mood(message.guild.id, detected)
# Update nickname for this server
from utils.moods import update_server_nickname
globals.client.loop.create_task(update_server_nickname(message.guild.id))
Analysis: This part looks correct, but creates a task that may conflict with hourly rotation.
Issue #6: No Emoji for "neutral" Mood
Location: utils/moods.py line 16
MOOD_EMOJIS = {
"asleep": "💤",
"neutral": "", # ❌ Empty string
"bubbly": "🫧",
# ... etc
}
Impact: When bot is in neutral mood, nickname becomes just "Hatsune Miku" with no emoji, making it hard to tell if the system is working.
Recommendation: Add an emoji like "🎤" or "✨" for neutral mood.
🔧 ROOT CAUSE ANALYSIS
The core problem is architectural confusion between two competing systems:
- Original Design Intent: Servers should have independent moods with per-server nicknames
- Broken Implementation:
update_all_server_nicknames()uses global DM mood for all servers - Mixed Signals: Comments say servers are independent, but code says otherwise
🎯 RECOMMENDED FIXES
Fix #1: Remove update_all_server_nicknames() Entirely
This function violates the per-server mood architecture. It should never be called.
Action:
- Delete or deprecate
update_all_server_nicknames() - Ensure all nickname updates go through
update_server_nickname(guild_id)
Fix #2: Update nickname_mood_emoji() to Only Support Server-Specific Updates
Current Code:
async def nickname_mood_emoji(guild_id: int = None):
if guild_id is not None:
await update_server_nickname(guild_id)
else:
await update_all_server_nicknames() # ❌ Remove this
Fixed Code:
async def nickname_mood_emoji(guild_id: int):
"""Update nickname with mood emoji for a specific server"""
await update_server_nickname(guild_id)
Fix #3: Add Neutral Mood Emoji
Current:
"neutral": "",
Fixed:
"neutral": "🎤", # Or ✨, 🎵, etc.
Fix #4: Audit All Calls to Nickname Functions
Search for any calls to:
update_all_server_nicknames()- should not existnickname_mood_emoji()- must always pass guild_id
FOUND ISSUES:
❌ api.py - THREE broken endpoints:
- Line 113-114:
/moodendpoint sets DM mood but updates ALL server nicknames - Line 126-127:
/mood/resetendpoint sets DM mood but updates ALL server nicknames - Line 139-140:
/mood/calmendpoint sets DM mood but updates ALL server nicknames
Code:
@app.post("/mood")
async def set_mood_endpoint(data: MoodSetRequest):
# Update DM mood
globals.DM_MOOD = data.mood
globals.DM_MOOD_DESCRIPTION = load_mood_description(data.mood)
# ❌ WRONG: Updates ALL servers with DM mood
from utils.moods import update_all_server_nicknames
globals.client.loop.create_task(update_all_server_nicknames())
Impact:
- API endpoints that change DM mood incorrectly change ALL server nicknames
- This is the smoking gun! When you use the API/dashboard to change mood, it breaks server nicknames
- Confirms that DM mood and server moods should be completely independent
Fix:
- Remove nickname update calls from these endpoints
- DM mood should NOT affect server nicknames at all
- If you want to update server nicknames, use the per-server endpoints
✅ api.py also has CORRECT per-server endpoints (line 145+):
/servers/{guild_id}/mood- Gets server mood (correct)- Likely has POST endpoints for setting server mood (need to verify)
Locations checked:
- ✅
bot.py- Usesupdate_server_nickname(guild_id)correctly - ✅
server_manager.py- Rotation calls correct function - ❌
api.py- DM mood endpoints incorrectly update all servers - ⚠️
command_router.py- Importsnickname_mood_emojibut doesn't seem to use it
Fix #5: Add Logging to Verify Mood/Nickname Sync
Add debug logging to update_server_nickname() to track:
- What mood the server thinks it has
- What emoji is being applied
- Whether the Discord API call succeeds
Fix #6: Consider Removing DM Mood Entirely (Optional)
Question: Should DMs have their own mood system?
Current Design:
- DMs use
globals.DM_MOOD - DM mood rotates every 2 hours
- DM mood does NOT affect nicknames (correctly)
Recommendation: This is fine IF the nickname system stops using it. The current separation is logical.
📋 VERIFICATION CHECKLIST
After fixes, verify:
- Each server maintains its own mood independently
- Server nicknames update when server mood changes
- Hourly mood rotation updates the correct server's nickname
- Keyword mood detection updates the correct server's nickname
- DM mood changes do NOT affect any server nicknames
- Neutral mood shows an emoji (or document that empty is intentional)
- No race conditions between rotation and manual mood changes
🧪 TESTING PROCEDURE
-
Test Server Mood Independence:
- Join multiple servers
- Manually trigger mood change in one server
- Verify other servers maintain their moods
-
Test Nickname Updates:
- Trigger mood rotation
- Check nickname shows correct emoji
- Compare against
MOOD_EMOJISdictionary
-
Test DM Mood Isolation:
- Send DM to bot
- Wait for DM mood rotation
- Verify server nicknames don't change
-
Test Mood Detection:
- Send message with mood keywords
- Verify mood changes and nickname updates
- Check logs for correct mood detection
📊 SUMMARY
| Component | Status | Issue |
|---|---|---|
| Server Mood System | ⚠️ Partially Broken | Nicknames use wrong mood when API called |
| DM Mood System | ✅ Working | Isolated correctly in bot logic |
| Mood Rotation | ✅ Working | Logic is correct |
| Nickname Updates | 🔴 BROKEN | API endpoints use DM mood for servers |
| Mood Detection | ✅ Working | Keywords trigger correctly |
| Emoji System | ⚠️ Minor Issue | Neutral has no emoji |
| Per-Server API | ✅ Working | /servers/{guild_id}/mood endpoints correct |
| Global DM API | 🔴 BROKEN | /mood endpoints incorrectly update servers |
KEY FINDING: The bug is primarily in the API layer, not the core bot logic!
When you (or a dashboard) calls:
/moodendpoint → Changes DM mood → Updates ALL server nicknames ❌/mood/resetendpoint → Resets DM mood → Updates ALL server nicknames ❌/mood/calmendpoint → Calms DM mood → Updates ALL server nicknames ❌
This explains why it "doesn't seem like they function right" - the API is sabotaging the per-server system!
🚀 PRIORITY FIX ORDER
-
🔥 CRITICAL: Fix API endpoints in
api.py- Removeupdate_all_server_nicknames()calls from:/moodendpoint (line 113-114)/mood/resetendpoint (line 126-127)/mood/calmendpoint (line 139-140)
-
HIGH: Deprecate
update_all_server_nicknames()function inutils/moods.py- Add deprecation warning
- Eventually delete it entirely
-
HIGH: Fix
nickname_mood_emoji()to requireguild_id- Remove the
guild_id=Nonedefault - Remove the DM mood branch
- Remove the
-
MEDIUM: Add neutral mood emoji - user experience
-
LOW: Add debug logging - future maintenance
IMMEDIATE ACTION: Fix the three API endpoints. This is the root cause of the visible bug.
📝 CODE LOCATIONS REFERENCE
- Mood definitions:
utils/moods.py - Server config:
server_manager.py - Bot message handling:
bot.py - LLM mood usage:
utils/llm.py - Global DM mood:
globals.py - Mood files:
moods/*.txt