fix(P2): 5 priority-2 bug fixes — emoji consolidation, DM safety, pause gap
#10 Redundant coin flip in join_conversation — removed the 50% random gate that doubled the V2 engine's own decision to act. #11 Message-triggered actions skip _autonomous_paused — _check_and_act and _check_and_react now bail out immediately when the autonomous system is paused (voice session), matching the scheduled-tick path. #12 Duplicate emoji dictionaries — removed MOOD_EMOJIS and EVIL_MOOD_EMOJIS from globals.py (had different emojis from moods.py). bipolar_mode.py and evil_mode.py now import the canonical dicts from utils/moods.py so all code sees the same emojis. #13 DM mood can spontaneously become 'asleep' — rotate_dm_mood() now filters 'asleep' out of the candidate list since DMs have no sleepy-to-asleep transition guard and no wakeup timer. #15 Engage-user fallback misreports action type — log level raised to WARNING with an explicit [engage_user->general] prefix so the cooldown-triggered fallback is visible in logs.
This commit is contained in:
@@ -184,6 +184,9 @@ async def _check_and_react(guild_id: int, message):
|
||||
Check if Miku should react to a new message with an emoji.
|
||||
Called for each new message in real-time.
|
||||
"""
|
||||
if _autonomous_paused:
|
||||
return
|
||||
|
||||
# Calculate message age
|
||||
from datetime import datetime, timezone
|
||||
message_age = (datetime.now(timezone.utc) - message.created_at).total_seconds()
|
||||
@@ -211,6 +214,9 @@ async def _check_and_act(guild_id: int):
|
||||
Uses per-guild lock to prevent race conditions from near-simultaneous messages.
|
||||
"""
|
||||
async with _get_action_lock(guild_id):
|
||||
if _autonomous_paused:
|
||||
return
|
||||
|
||||
# Rate limiting check
|
||||
now = time.time()
|
||||
if guild_id in _last_action_execution:
|
||||
|
||||
@@ -304,7 +304,7 @@ async def miku_engage_random_user_for_server(guild_id: int, user_id: str = None,
|
||||
|
||||
# Skip cooldown check if this is a manual trigger from web UI
|
||||
if not manual_trigger and now - last_time < 43200: # 12 hours in seconds
|
||||
logger.info(f"Recently engaged {target.display_name} in server {guild_id}, switching to general message.")
|
||||
logger.warning(f"[engage_user→general] Recently engaged {target.display_name} in server {guild_id}, falling back to general message (cooldown).")
|
||||
await miku_say_something_general_for_server(guild_id)
|
||||
return
|
||||
|
||||
@@ -456,10 +456,7 @@ async def miku_detect_and_join_conversation_for_server(guild_id: int, force: boo
|
||||
# Not enough activity
|
||||
logger.debug(f"[Join Conv] Not enough activity: {len(recent_msgs)} messages, {len(user_ids)} users (need 5+ messages, 2+ users)")
|
||||
return
|
||||
|
||||
if random.random() > 0.5:
|
||||
logger.debug(f"[Join Conv] Random chance failed (50% chance)")
|
||||
return # 50% chance to engage
|
||||
# Note: V1 had a redundant 50% coin flip here, removed since V2 engine already decided to act
|
||||
else:
|
||||
logger.debug(f"[Join Conv] Force mode - bypassing activity checks")
|
||||
if len(recent_msgs) < 1:
|
||||
|
||||
@@ -404,8 +404,9 @@ async def update_webhook_avatars(client):
|
||||
|
||||
def get_miku_display_name() -> str:
|
||||
"""Get Regular Miku's display name with mood and emoji"""
|
||||
from utils.moods import MOOD_EMOJIS
|
||||
mood = globals.DM_MOOD
|
||||
emoji = globals.MOOD_EMOJIS.get(mood, "")
|
||||
emoji = MOOD_EMOJIS.get(mood, "")
|
||||
if emoji:
|
||||
return f"Hatsune Miku {emoji}"
|
||||
return "Hatsune Miku"
|
||||
@@ -413,8 +414,9 @@ def get_miku_display_name() -> str:
|
||||
|
||||
def get_evil_miku_display_name() -> str:
|
||||
"""Get Evil Miku's display name with mood and emoji"""
|
||||
from utils.moods import EVIL_MOOD_EMOJIS
|
||||
mood = globals.EVIL_DM_MOOD
|
||||
emoji = globals.EVIL_MOOD_EMOJIS.get(mood, "")
|
||||
emoji = EVIL_MOOD_EMOJIS.get(mood, "")
|
||||
if emoji:
|
||||
return f"Evil Miku {emoji}"
|
||||
return "Evil Miku"
|
||||
|
||||
@@ -191,7 +191,8 @@ def load_evil_mood_description(mood_name: str) -> str:
|
||||
|
||||
def get_evil_mood_emoji(mood_name: str) -> str:
|
||||
"""Get emoji for evil mood"""
|
||||
return globals.EVIL_MOOD_EMOJIS.get(mood_name, "")
|
||||
from utils.moods import EVIL_MOOD_EMOJIS
|
||||
return EVIL_MOOD_EMOJIS.get(mood_name, "")
|
||||
|
||||
|
||||
def is_valid_evil_mood(mood_name: str) -> bool:
|
||||
|
||||
@@ -162,9 +162,11 @@ async def rotate_dm_mood():
|
||||
old_mood = globals.DM_MOOD
|
||||
new_mood = old_mood
|
||||
attempts = 0
|
||||
# Filter out 'asleep' — DMs have no sleepy→asleep transition guard
|
||||
dm_eligible = [m for m in globals.AVAILABLE_MOODS if m != "asleep"]
|
||||
|
||||
while new_mood == old_mood and attempts < 5:
|
||||
new_mood = random.choice(globals.AVAILABLE_MOODS)
|
||||
new_mood = random.choice(dm_eligible)
|
||||
attempts += 1
|
||||
|
||||
globals.DM_MOOD = new_mood
|
||||
|
||||
Reference in New Issue
Block a user