Implement Evil Miku mode with persistence, fix API event loop issues, and improve formatting

- Added Evil Miku mode with 4 evil moods (aggressive, cunning, sarcastic, evil_neutral)
- Created evil mode content files (evil_miku_lore.txt, evil_miku_prompt.txt, evil_miku_lyrics.txt)
- Implemented persistent evil mode state across restarts (saves to memory/evil_mode_state.json)
- Fixed API endpoints to use client.loop.create_task() to prevent timeout errors
- Added evil mode toggle in web UI with red theme styling
- Modified mood rotation to handle evil mode
- Configured DarkIdol uncensored model for evil mode text generation
- Reduced system prompt redundancy by removing duplicate content
- Added markdown escape for single asterisks (actions) while preserving bold formatting
- Evil mode now persists username, pfp, and nicknames across restarts without re-applying changes
This commit is contained in:
2026-01-02 17:11:58 +02:00
parent b38bdf2435
commit 6ec33bcecb
38 changed files with 5707 additions and 164 deletions

View File

@@ -25,8 +25,24 @@ MOOD_EMOJIS = {
"silly": "🪿"
}
# Evil mode mood emojis (also in globals, but duplicated here for convenience)
EVIL_MOOD_EMOJIS = {
"aggressive": "👿",
"cunning": "🐍",
"sarcastic": "😈",
"evil_neutral": ""
}
def load_mood_description(mood_name: str) -> str:
path = os.path.join("moods", f"{mood_name}.txt")
"""Load mood description - checks evil moods first if in evil mode"""
from utils.evil_mode import is_evil_mode
if is_evil_mode() and mood_name in globals.EVIL_AVAILABLE_MOODS:
# Load from evil moods folder
path = os.path.join("moods", "evil", f"{mood_name}.txt")
else:
# Load from regular moods folder
path = os.path.join("moods", f"{mood_name}.txt")
try:
with open(path, "r", encoding="utf-8") as f:
return f.read().strip()
@@ -119,20 +135,27 @@ def detect_mood_shift(response_text, server_context=None):
return None
async def rotate_dm_mood():
"""Rotate DM mood automatically (no keyword triggers)"""
"""Rotate DM mood automatically (handles both normal and evil mode)"""
try:
old_mood = globals.DM_MOOD
new_mood = old_mood
attempts = 0
from utils.evil_mode import is_evil_mode, rotate_evil_mood
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}")
if is_evil_mode():
# Rotate evil mood instead
await rotate_evil_mood()
else:
# Normal mood rotation
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.
@@ -166,18 +189,30 @@ async def update_server_nickname(guild_id: int):
print(f"⚠️ Bot not ready yet, deferring nickname update for server {guild_id}")
return
# Check if evil mode is active
from utils.evil_mode import is_evil_mode, get_evil_mood_emoji
evil_mode = is_evil_mode()
from server_manager import server_manager
server_config = server_manager.get_server_config(guild_id)
if not server_config:
print(f"⚠️ No server config found for guild {guild_id}")
return
mood = server_config.current_mood_name.lower()
print(f"🔍 Server {guild_id} mood is: {mood}")
emoji = MOOD_EMOJIS.get(mood, "")
if evil_mode:
# In evil mode, use evil mood
mood = globals.EVIL_DM_MOOD.lower()
emoji = get_evil_mood_emoji(mood)
base_name = "Evil Miku"
else:
mood = server_config.current_mood_name.lower()
emoji = MOOD_EMOJIS.get(mood, "")
base_name = "Hatsune Miku"
print(f"🔍 Server {guild_id} mood is: {mood} (evil_mode={evil_mode})")
print(f"🔍 Using emoji: {emoji}")
nickname = f"Hatsune Miku{emoji}"
nickname = f"{base_name}{emoji}"
print(f"🔍 New nickname will be: {nickname}")
guild = globals.client.get_guild(guild_id)