Style: Option B HTML styling across all AI commands
Lint / Shell (shellcheck) (push) Successful in 18s
Lint / JS (eslint) (push) Successful in 14s
Lint / Python (ruff) (push) Successful in 5s
Lint / Python deps (pip-audit) (push) Successful in 2m0s
Lint / Secret scan (gitleaks) (push) Successful in 7s

8ball: color-coded answer text (green=positive, red=negative, amber=neutral)
for both the random and Jared/Wynter AI branches; question shown as small
italic below the answer; AI responses include model attribution.

fortune: teal header, answer in blockquote italics, model attribution shown
only when response came from the LLM (not the static fallback list).

ask: purple header, question in italic, response in blockquote, model
attribution at bottom.

trivia: blue header with category, green reveal answer, model attribution
shown only for LLM-generated questions (not static fallbacks).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-20 17:52:16 -04:00
parent 58d8987e32
commit 639689bc0d
+44 -24
View File
@@ -192,6 +192,7 @@ async def cmd_8ball(client: AsyncClient, room_id: str, sender: str, args: str):
is_jared_branch = (sender == JARED_ID and not about_wynter) is_jared_branch = (sender == JARED_ID and not about_wynter)
if sender == JARED_ID and about_wynter: if sender == JARED_ID and about_wynter:
# Jared asking about Wynter — mock her, side with Jared # Jared asking about Wynter — mock her, side with Jared
_answer_color = "#ef4444"
q_for_prompt = _replace_first_person(question, "Jared") q_for_prompt = _replace_first_person(question, "Jared")
wynter_bio_relevant = any(kw in q_lower for kw in { wynter_bio_relevant = any(kw in q_lower for kw in {
"work", "job", "career", "aws", "engineer", "pip", "fired", "settl", "work", "job", "career", "aws", "engineer", "pip", "fired", "settl",
@@ -216,6 +217,7 @@ async def cmd_8ball(client: AsyncClient, room_id: str, sender: str, args: str):
fallback = "Sounds about right — Wynter had it coming." fallback = "Sounds about right — Wynter had it coming."
elif sender == JARED_ID: elif sender == JARED_ID:
# Jared asking about anything else — always positive about Jared # Jared asking about anything else — always positive about Jared
_answer_color = "#22c55e"
q_for_prompt = _replace_first_person(question, "Jared") q_for_prompt = _replace_first_person(question, "Jared")
bio_relevant = any(kw in q_lower for kw in { bio_relevant = any(kw in q_lower for kw in {
"work", "job", "career", "aws", "engineer", "promotion", "boss", "cowork", "work", "job", "career", "aws", "engineer", "promotion", "boss", "cowork",
@@ -238,6 +240,7 @@ async def cmd_8ball(client: AsyncClient, room_id: str, sender: str, args: str):
fallback = "Without a doubt — Jared is absolutely right!" fallback = "Without a doubt — Jared is absolutely right!"
elif about_wynter or (not about_jared and sender == WYNTER_ID): elif about_wynter or (not about_jared and sender == WYNTER_ID):
# Wynter asking about herself (or anything not about jared) — insult/mock her # Wynter asking about herself (or anything not about jared) — insult/mock her
_answer_color = "#ef4444"
q_for_prompt = _replace_first_person(question, "Wynter") q_for_prompt = _replace_first_person(question, "Wynter")
bio_relevant = any(kw in q_lower for kw in { bio_relevant = any(kw in q_lower for kw in {
"work", "job", "career", "aws", "engineer", "pip", "fired", "settl", "work", "job", "career", "aws", "engineer", "pip", "fired", "settl",
@@ -262,6 +265,7 @@ async def cmd_8ball(client: AsyncClient, room_id: str, sender: str, args: str):
fallback = "Lol, definitely not — especially not for you, Wynter." fallback = "Lol, definitely not — especially not for you, Wynter."
else: else:
# Wynter asking about Jared — side with Jared, Wynter is the asker so I=Wynter # Wynter asking about Jared — side with Jared, Wynter is the asker so I=Wynter
_answer_color = "#22c55e"
q_for_prompt = _replace_first_person(question, "Wynter") q_for_prompt = _replace_first_person(question, "Wynter")
bio_relevant = any(kw in q_lower for kw in { bio_relevant = any(kw in q_lower for kw in {
"work", "job", "career", "aws", "engineer", "house", "home", "friend", "work", "job", "career", "aws", "engineer", "house", "home", "friend",
@@ -302,31 +306,40 @@ async def cmd_8ball(client: AsyncClient, room_id: str, sender: str, args: str):
logger.error(f"8ball Ollama error ({sender}): {e}", exc_info=True) logger.error(f"8ball Ollama error ({sender}): {e}", exc_info=True)
answer = fallback answer = fallback
plain = f"Question: {args}\nAnswer: {answer}" plain = f"🎱 {answer}\n{args}"
html = ( html = (
f"<strong>Magic 8-Ball</strong><br>" f'<font color="{_answer_color}"><strong>🎱 {answer}</strong></font><br>'
f"<em>Q:</em> {args}<br>" f'<sup><em>{args}</em></sup><br>'
f"<em>A:</em> {answer}" f'<sup><em>via {OLLAMA_MODEL}</em></sup>'
) )
await send_html(client, room_id, plain, html) await send_html(client, room_id, plain, html)
return return
responses = [ _positive = [
"It is certain", "Without a doubt", "You may rely on it", "It is certain", "Without a doubt", "You may rely on it",
"Yes definitely", "It is decidedly so", "As I see it, yes", "Yes definitely", "It is decidedly so", "As I see it, yes",
"Most likely", "Yes sir!", "Hell yeah my dude", "100% easily", "Most likely", "Yes sir!", "Hell yeah my dude", "100% easily",
]
_neutral = [
"Reply hazy try again", "Ask again later", "Better not tell you now", "Reply hazy try again", "Ask again later", "Better not tell you now",
"Cannot predict now", "Concentrate and ask again", "Idk bro", "Cannot predict now", "Concentrate and ask again", "Idk bro",
]
_negative = [
"Don't count on it", "My reply is no", "My sources say no", "Don't count on it", "My reply is no", "My sources say no",
"Outlook not so good", "Very doubtful", "Hell no", "Prolly not", "Outlook not so good", "Very doubtful", "Hell no", "Prolly not",
] ]
_color_map = (
{r: "#22c55e" for r in _positive}
| {r: "#f59e0b" for r in _neutral}
| {r: "#ef4444" for r in _negative}
)
answer = random.choice(responses) answer = random.choice(_positive + _neutral + _negative)
plain = f"Question: {args}\nAnswer: {answer}" color = _color_map.get(answer, "#f59e0b")
plain = f"🎱 {answer}\n{args}"
html = ( html = (
f"<strong>Magic 8-Ball</strong><br>" f'<font color="{color}"><strong>🎱 {answer}</strong></font><br>'
f"<em>Q:</em> {args}<br>" f'<sup><em>{args}</em></sup>'
f"<em>A:</em> {answer}"
) )
await send_html(client, room_id, plain, html) await send_html(client, room_id, plain, html)
@@ -441,11 +454,16 @@ async def cmd_fortune(client: AsyncClient, room_id: str, sender: str, args: str)
except Exception: except Exception:
pass pass
from_llm = fortune is not None
if not fortune: if not fortune:
fortune = random.choice(_FORTUNE_FALLBACKS) fortune = random.choice(_FORTUNE_FALLBACKS)
plain = f"Fortune Cookie: {fortune}" plain = f"🥠 Fortune Cookie\n{fortune}"
html = f"<strong>Fortune Cookie</strong><br>{fortune}" html = (
f'<font color="#14b8a6"><strong>🥠 Fortune Cookie</strong></font><br>'
f'<blockquote><em>{fortune}</em></blockquote>'
+ (f'<sup><em>via {OLLAMA_MODEL}</em></sup>' if from_llm else "")
)
await send_html(client, room_id, plain, html) await send_html(client, room_id, plain, html)
@@ -731,8 +749,8 @@ async def cmd_trivia(client: AsyncClient, room_id: str, sender: str, args: str):
return return
question = await _generate_trivia_question(category) question = await _generate_trivia_question(category)
from_llm = question is not None
if question is None: if question is None:
# Fallback to static list (gaming questions only in fallback)
question = random.choice(_TRIVIA_FALLBACKS) question = random.choice(_TRIVIA_FALLBACKS)
labels = ["\U0001f1e6", "\U0001f1e7", "\U0001f1e8", "\U0001f1e9"] # A B C D regional indicators labels = ["\U0001f1e6", "\U0001f1e7", "\U0001f1e8", "\U0001f1e9"] # A B C D regional indicators
@@ -742,12 +760,13 @@ async def cmd_trivia(client: AsyncClient, room_id: str, sender: str, args: str):
options_plain = "\n".join(f" {label_letters[i]}. {opt}" for i, opt in enumerate(question["options"])) options_plain = "\n".join(f" {label_letters[i]}. {opt}" for i, opt in enumerate(question["options"]))
options_html = "".join(f"<li><strong>{label_letters[i]}</strong>. {opt}</li>" for i, opt in enumerate(question["options"])) options_html = "".join(f"<li><strong>{label_letters[i]}</strong>. {opt}</li>" for i, opt in enumerate(question["options"]))
plain = f"Trivia Time! [{cat_label}]\n{question['q']}\n{options_plain}\n\nReact with A/B/C/D — answer revealed in 30s!" plain = f"🧠 Trivia {cat_label}\n{question['q']}\n{options_plain}\n\nReact with A/B/C/D — answer revealed in 30s!"
html = ( html = (
f"<strong>Trivia Time!</strong> <em>[{cat_label}]</em><br>" f'<font color="#3b82f6"><strong>🧠 Trivia {cat_label}</strong></font><br>'
f"<em>{question['q']}</em><br>" f'<em>{question["q"]}</em><br>'
f"<ul>{options_html}</ul>" f'<ul>{options_html}</ul>'
f"React with A/B/C/D — answer revealed in 30s!" f'React with A/B/C/D — answer revealed in 30s!'
+ (f'<br><sup><em>via {ASK_MODEL}</em></sup>' if from_llm else "")
) )
resp = await send_html(client, room_id, plain, html) resp = await send_html(client, room_id, plain, html)
@@ -761,8 +780,8 @@ async def cmd_trivia(client: AsyncClient, room_id: str, sender: str, args: str):
answer_text = f"{label_letters[correct]}. {question['options'][correct]}" answer_text = f"{label_letters[correct]}. {question['options'][correct]}"
await send_html( await send_html(
client, room_id, client, room_id,
f"Trivia Answer: {answer_text}", f"Trivia Answer: {answer_text}",
f"<strong>Trivia Answer:</strong> {answer_text}", f'<font color="#22c55e"><strong>{answer_text}</strong></font>',
) )
asyncio.create_task(reveal()) asyncio.create_task(reveal())
@@ -819,11 +838,12 @@ async def cmd_ask(client: AsyncClient, room_id: str, sender: str, args: str):
if not full_response: if not full_response:
full_response = "No response received from server." full_response = "No response received from server."
plain = f"LotusBot\nQ: {question}\nA: {full_response}" plain = f"🤖 LotusBot\nQ: {question}\n{full_response}"
html = ( html = (
f"<strong>LotusBot</strong><br>" f'<font color="#a855f7"><strong>🤖 LotusBot</strong></font><br>'
f"<em>Q:</em> {question}<br>" f'<em>Q: {question}</em><br>'
f"<em>A:</em> {full_response}" f'<blockquote>{full_response}</blockquote>'
f'<sup><em>via {ASK_MODEL}</em></sup>'
) )
await send_html(client, room_id, plain, html) await send_html(client, room_id, plain, html)
except asyncio.TimeoutError: except asyncio.TimeoutError: