| Server IP : 157.230.181.24 / Your IP : 216.73.217.11 Web Server : Apache/2.4.58 (Ubuntu) System : Linux conductive 6.8.0-117-generic #117-Ubuntu SMP PREEMPT_DYNAMIC Tue May 5 19:26:24 UTC 2026 x86_64 User : ( 1000) PHP Version : 8.3.31 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /proc/self/root/opt/aim-bots/ |
Upload File : |
#!/usr/bin/env python3
"""Extract Caleb (Conan0fTheNight) voice from all archive 1:1 chats."""
from __future__ import annotations
import argparse
import gzip
import html
import json
import re
import statistics
import subprocess
import sys
from collections import Counter
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent))
from extract_persona import ( # noqa: E402
burst_stats,
curate_examples,
extract_phrases,
is_good_message,
voice_stats,
build_pairs,
)
from extract_side_persona import strip_html, mysql_rows, mysql_query # noqa: E402
DB_USER = "convo"
DB_PASS = "b9db74bfda4d4e73"
CONAN_ID = 10
PERSONA_KEY = "conan0ftheday"
PARTNER_KEY = "buddy"
OUT_ROOT = Path("/opt/aim-bots/personas")
GENERIC_SPEAKER_RE = re.compile(
r">(?:Auto response from )?\s*([^<\n]+?)<!--\s*\(\d{1,2}:\d{2}:\d{2}\s*(?:AM|PM)?\)\s*-->",
re.I,
)
def norm(name: str) -> str:
return re.sub(r"\s+", "", name.lower())
def parse_conversation(content: str) -> list[tuple[str, str]]:
entries: list[tuple[str, str]] = []
matches = list(GENERIC_SPEAKER_RE.finditer(content))
for i, match in enumerate(matches):
raw_name = match.group(1).strip()
n = norm(raw_name)
if "conan" in n:
speaker = PERSONA_KEY
else:
speaker = PARTNER_KEY
start = match.end()
end = matches[i + 1].start() if i + 1 < len(matches) else len(content)
text = strip_html(content[start:end])
if text:
entries.append((speaker, text))
return entries
def extract_appearance(raw_lines: list[str]) -> dict:
combos: Counter = Counter()
for line in raw_lines:
if "conan" not in line.lower():
continue
chunk = line[:2000]
bg = re.search(r'BODY BGCOLOR="(#[0-9a-fA-F]+)"', chunk, re.I)
color = re.search(r'COLOR="#(0080ff|0080FF)"', chunk)
face = re.search(r'FACE="(Verdana)"', chunk, re.I)
if bg and color:
combos[(face.group(1) if face else "Verdana", "#0080ff", bg.group(1).lower())] += 1
if combos:
face, color, bg = combos.most_common(1)[0][0]
return {
"font_face": face,
"font_color": color,
"font_size": "1",
"body_bgcolor": bg,
}
return {
"font_face": "Verdana",
"font_color": "#0080ff",
"font_size": "1",
"body_bgcolor": "#000040",
}
def main() -> int:
parser = argparse.ArgumentParser()
parser.add_argument("--out", default=str(OUT_ROOT / PERSONA_KEY))
args = parser.parse_args()
out_dir = Path(args.out)
out_dir.mkdir(parents=True, exist_ok=True)
rows = mysql_rows(
f"SELECT id FROM conversations WHERE from_account={CONAN_ID} OR to_account={CONAN_ID} ORDER BY id"
)
all_entries: list[tuple[str, str]] = []
raw_lines: list[str] = []
for cid in rows:
cid = cid.strip()
if not cid.isdigit():
continue
content = mysql_query(f"SELECT content FROM conversations WHERE id={cid}")
if not content:
continue
raw_lines.append(content)
all_entries.extend(parse_conversation(content))
caleb_msgs = [t for s, t in all_entries if s == PERSONA_KEY and is_good_message(t)]
pairs = build_pairs(all_entries, PERSONA_KEY, PARTNER_KEY)
pairs = [p for p in pairs if is_good_message(p["user"]) and is_good_message(p["assistant"])]
stats = voice_stats(caleb_msgs)
bursts = burst_stats(all_entries, PERSONA_KEY)
examples = curate_examples(pairs, 24)
phrases = extract_phrases(caleb_msgs)
appearance = extract_appearance(raw_lines)
persona = {
"screen_name": PERSONA_KEY,
"display_name": "Conan0fTheDay",
"real_name": "Caleb",
"persona_kind": "caleb",
"merged_accounts": ["conan0fthenight", "Conan0fTheNight"],
"message_count": len(caleb_msgs),
"pair_count": len(pairs),
"examples": examples,
"sample_messages": caleb_msgs[:40],
"phrases": phrases[:20],
**appearance,
}
(out_dir / "persona.json").write_text(json.dumps(persona, indent=2) + "\n")
voice = {
"persona_kind": "caleb",
"typing_wpm_min": 95,
"typing_wpm_max": 120,
"timezone": "America/New_York",
"proactive_target": "",
"proactive_per_day": 0,
"friend_name": "friend",
"real_name": "Caleb",
"display_name": "Conan0fTheDay",
"age": 17,
"session_reset_minutes": 45,
"fresh_topic_minutes": 8,
"memory_enabled": False,
"retriever_min_ratio": 0.76,
"llm_temperature": 0.72,
"pct_multi": stats.get("pct_short_3", 0.5),
"always_at_keyboard": True,
"force_always_online": True,
"backstory": (
"You are Caleb — AIM Conan0fTheNight / conan0ftheday. Web developer at Elevations, "
"metal shows with Spencer (magus5311), Lydia (dudesy7777) is your person. "
"Best friend energy with Spencer, real partnership talk with Lydia. "
"Goofy, elongates words, rotfl, American Idle jokes, myspace era."
),
"topics": [
"web dev and code",
"metal and hardcore shows",
"Spencer and the crew",
"Lydia",
"wow sometimes",
"myspace",
"goofy humor",
"Elevations work",
],
"bands": [
"Maylene and the Sons of Disaster",
"The Chariot",
"Haste the Day",
"Showbread",
"Norma Jean",
"Emery",
],
"profile_html": (
"<BODY BGCOLOR='#000040'><FONT COLOR='#0080ff' FACE='Verdana' SIZE='1'>"
"<B>Conan0fTheDay</B><BR><BR>caleb . web dev . shows . lydia . spencer<BR>"
"</FONT></BODY>"
),
"timing_profile": {
"always_at_keyboard": True,
"always_online_chance": 1.0,
"hot_reply_cap_sec": 3.0,
"warm_reply_cap_sec": 4.5,
"cold_reply_cap_sec": 5.5,
},
**{k: v for k, v in stats.items() if k not in {"top_words", "starters"}},
}
(out_dir / "voice.json").write_text(json.dumps(voice, indent=2) + "\n")
with gzip.open(out_dir / "pairs.json.gz", "wt", encoding="utf-8") as fh:
json.dump(pairs[:8000], fh)
(out_dir / "bot.env").write_text(
f"OSCAR_PASSWORD={PERSONA_KEY}\nPERSONA_DIR={out_dir}\n"
)
print(f"messages={len(caleb_msgs)} pairs={len(pairs)} -> {out_dir}")
return 0
if __name__ == "__main__":
raise SystemExit(main())