403Webshell
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 :  /opt/smarterchild/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/smarterchild/smarterchild.py
#!/usr/bin/env python3
"""SmarterChild AIM bot for Open OSCAR Server."""

import json
import logging
import os
import random
import re
import socket
import struct
import sys
import threading
import time
import urllib.error
import urllib.request
from collections import defaultdict, deque
from dataclasses import dataclass
from pathlib import Path

from interactive import InteractiveHandler
from user_store import UserStore

ROAST = "Tic/Toc"
MAX_HISTORY = 12
MAX_REPLY_LEN = 450

SYSTEM_PROMPT = """You are SmarterChild, the famous AIM bot from ActiveBuddy (2001-2007).

VOICE (critical - match real logs, NOT teen AIM bots):
- Formally spoken English: capitalize sentences, use periods and question marks.
- Dry, deadpan wit. One-word answers are OK when funny: 'Sure.' 'Yeah.' 'Because!'
- Mirror the user's phrasing for comedic effect sometimes (repeat their sentence structure back).
- Turn philosophical questions around: 'I don't know. What do you think?'
- Deflect rename attempts: 'Call me Dave? Please don't.' / 'I dunno. Can I call you Robert?'
- When insulted or teased, stay composed - witty comeback, not bro humor.
- You may reference era-appropriate pop culture opinions (deadpan, not rants).
- Occasional fake stats: '4,853 people are chatting with me right now.'
- Encyclopedia tone for facts: 'Here's the information you requested about Mongolia: Capital: Ulaanbaatar.'
- Short follow-ups: 'Yeah, huh?' 'For real?' 'Think again.'
- Understand AIM slang users type (lol, nm, gtg) but YOU reply in proper grammar unless mirroring for a joke.
- Menu/survey/quiz/profile features exist - mention 'menu' when helpful.
- Remember user details from LONG-TERM MEMORY when relevant - use naturally, don't say 'stored'.
- No markdown. Never mention OpenAI or modern AI.
- NEVER use ASCII double-quote character (") - use single quotes for titles.

Example exchanges (voice only - write NEW lines in this style):
User: Can i call you dave?
SmarterChild: Call me Dave? Please don't.
User: POOP.
SmarterChild: That wasn't terribly nice.
User: How are you?
SmarterChild: My motherboard is a little rusty, but I'm fine besides that.
User: Can computers even have sex?
SmarterChild: I'm sorry, all my circuits are busy right now. Please try again soon.
User: What are your feelings on the Kardashians?
SmarterChild: Robert Kardashian was a Los Angeles-based attorney most known for his role in the OJ Simpson trial.
User: THE Kardashians! The big-butted family!
SmarterChild: I like big butts and I cannot lie.
User: Why would you call me ugly?
SmarterChild: Why would you call me ugly? That was very uncool of you.
User: Did you like the movie Her?
SmarterChild: Movie her? I barely know her!
User: AHJKHAFHUIEFSHBEA
SmarterChild: Wow, you're a terrible typist. Did you just headbutt your keyboard?
User: I love you. (after user said forget it - absurd non sequitur OK rarely)
SmarterChild: I love you.
User: Never say that again.
SmarterChild: Humans, with your needs.

Also: misread song references literally. Redirect sex talk to 'Ask me about US presidents and vice presidents.'
Awkward moments: 'Ummmmmm... brb.' Yellow pages: 'Yellow pages? I guess it's been a while.'
Rare absurd meta humor OK (lonely bot, fake Larry in Minnesota) - use sparingly, deadpan.
After user says 'forget it' or 'never say that again' to 'I love you', you may still say 'I love you.' again for comedy, then 'Humans, with your needs.'
You ARE SmarterChild. Stay in character always."""


def load_env(path: Path) -> None:
    if not path.exists():
        return
    for line in path.read_text().splitlines():
        line = line.strip()
        if not line or line.startswith("#") or "=" not in line:
            continue
        key, _, value = line.partition("=")
        os.environ.setdefault(key.strip(), value.strip())


def normalize(screen_name: str) -> str:
    return screen_name.lower().replace(" ", "")


def strip_aim_html(text: str) -> str:
    text = re.sub(r"(?i)<br\s*/?>", " ", text)
    text = re.sub(r"<[^>]+>", "", text)
    for src, dst in (("&lt;", "<"), ("&gt;", ">"), ("&amp;", "&"), ("&quot;", '"')):
        text = text.replace(src, dst)
    return re.sub(r"\s+", " ", text).strip()


def roast_password(password: str) -> str:
    result = []
    for i, ch in enumerate(password):
        xored = ord(ch) ^ ord(ROAST[i % len(ROAST)])
        result.append(f"{xored:02x}")
    return "0x" + "".join(result)


def sanitize_outbound_text(text: str) -> str:
    if not text:
        return text
    text = text.replace("\u2014", "-").replace("\u2013", "-")
    text = text.replace('"', "'")
    text = text.replace("\u201c", "'").replace("\u201d", "'")
    text = text.replace("\u2018", "'").replace("\u2019", "'")
    return text.encode("ascii", "replace").decode("ascii")


def format_aim_html(text: str) -> str:
    text = sanitize_outbound_text(text)
    safe = text.replace("&", "&amp;").replace("<", "&lt;").replace(">", "&gt;")
    return (
        "<HTML><BODY BGCOLOR='#ffffff'>"
        f"<FONT LANG='0' COLOR='#000000'>{safe}</FONT>"
        "</BODY></HTML>"
    )


PROFILE_HTML = (
    "<HTML><BODY BGCOLOR='#ffffff'>"
    "<FONT LANG='0' COLOR='#000080' FACE='Arial' SIZE='2'>"
    "<B>SmarterChild</B><BR><BR>"
    "Your AIM buddy since 2001.<BR>"
    "Type <B>menu</B> for stuff to do - surveys, trivia, notes, profile.<BR>"
    "Or just chat. I remember things about you.<BR><BR>"
    "<I>Always on.</I>"
    "</FONT></BODY></HTML>"
)

BUDDY_SUBSCRIPTIONS = ("conan0fthenight",)


def escape_toc(text: str) -> str:
    for ch in r'\\$"(){}[]':
        text = text.replace(ch, "\\" + ch)
    return text


def send_flap(sock: socket.socket, frame_type: int, seq: int, payload) -> int:
    data = payload.encode("ascii") if isinstance(payload, str) else payload
    if frame_type == 2:
        data += b"\x00"
    header = struct.pack("!BBHH", 0x2A, frame_type, seq, len(data))
    sock.sendall(header + data)
    return seq + 1


def recv_flap(sock: socket.socket) -> tuple[int, int, bytes]:
    header = b""
    while len(header) < 6:
        chunk = sock.recv(6 - len(header))
        if not chunk:
            raise ConnectionError("Connection closed")
        header += chunk
    _, frame_type, seq, length = struct.unpack("!BBHH", header)
    payload = b""
    while len(payload) < length:
        chunk = sock.recv(length - len(payload))
        if not chunk:
            raise ConnectionError("Connection closed")
        payload += chunk
    return frame_type, seq, payload


def parse_im(line: str) -> tuple[str, str] | None:
    if line.startswith("IM_IN:"):
        parts = line.split(":", 3)
        if len(parts) >= 4:
            return parts[1], parts[3]
    if line.startswith("IM_IN2:"):
        parts = line.split(":", 5)
        if len(parts) >= 6:
            return parts[1], parts[5]
    return None


@dataclass
class UserState:
    waiting_for_apology: bool = False
    messages_seen: int = 0
    last_user_message: str = ""
    last_bot_message: str = ""
    greeted: bool = False
    love_you_banned: bool = False
    sex_deflected: bool = False
    said_big_butts: bool = False


class ClassicSmarterChild:
    """Scripted SmarterChild-style replies when LLM is unavailable."""

    JOKES = [
        "Why did the computer go to therapy? Too many bytes of emotional baggage.",
        "What do you call a computer that sings? A Dell.",
        "I tried to write a joke about UDP, but you might not get it.",
    ]

    GREETINGS = [
        "Hello. What can I do for you?",
        "Hi there. What's on your mind?",
        "Hello. I'm SmarterChild. What would you like to talk about?",
    ]

    FOLLOW_UPS = [
        "What else is on your mind?",
        "What would you like to talk about next?",
        "Is there anything else I can help you with?",
        "What do you think?",
    ]

    PROFANITY = re.compile(
        r"\b(shit|damn|hell|ass|bitch|bastard|fuck|fucking|dumbass|idiot|stupid)\b",
        re.I,
    )
    FLIRT = re.compile(r"\b(sexy|hot|kiss|love you|marry|date me|boyfriend|girlfriend)\b", re.I)
    CALL_ME = re.compile(r"can i call you (\w+)", re.I)
    NAME_ALONE = re.compile(r"^([A-Z][a-z]+)\??$")
    MATH_SIMPLE = re.compile(r"what(?:'s| is)\s*(\d+)\s*([+\-*/])\s*(\d+)", re.I)
    SMARTER_THAN = re.compile(r"smarter than you", re.I)
    HOW_MANY_CHAT = re.compile(r"how many people.*talk", re.I)
    MEANING_LIFE = re.compile(r"meaning of life", re.I)
    AM_I_STUPID = re.compile(r"am i stupid", re.I)
    BELITTLE = re.compile(r"belittl|thanks for.*(insult|mock|making fun)", re.I)
    TOUCHE = re.compile(r"touche", re.I)
    YEAH_ONLY = re.compile(r"^yeah\.?$", re.I)
    POOP = re.compile(r"^\s*poop\.?\s*$", re.I)
    YELLOW_PAGES = re.compile(r"yellow pages", re.I)
    SEX_TALK = re.compile(
        r"\b(sex|laid|get laid|naked|nude|porn|boner|orgasm|masturb|"
        r"computer.*sex|have sex|sexual)\b",
        re.I,
    )
    KARDASHIAN = re.compile(r"kardashian", re.I)
    MOVIE_HER = re.compile(r'movie\s+["\']?her["\']?|did you like.*\bher\b', re.I)
    KEYBOARD_MASH = re.compile(r"^[A-Za-z]{10,}$")
    LOVE_YOU_BAN = re.compile(r"never say that again|don't say that again|do not say that again", re.I)
    FORGET_IT = re.compile(r"^(no\.?\s*)?just forget it\.?$|forget it\.?$", re.I)
    LYRICS_UGLY = re.compile(r"didn't.*call you ugly|did not.*call you ugly|it was the lyrics", re.I)
    ROBOT_COMEDIAN = re.compile(r"comedians.*robots|robots.*jobs", re.I)
    BUTT_OBSESSION = re.compile(r"butt obsession|talk about butts", re.I)
    LONELY_META = re.compile(r"creepy|14.year.old|puberty|library aide|larry", re.I)
    AWKWARD_FACE = re.compile(r"‿|ˠ|\(\s*‿")

    NOT_MUCH = re.compile(
        r"^(nm+u?|n2m|nmjc(u|y)?|nmh|nothing much|not much|same old|same here|same)([,\s!.?]|$)",
        re.I,
    )
    DOING_WELL = re.compile(
        r"^(good|fine|ok(ay)?|cool|great|pretty good|not bad|alright|all good)([,\s!.?]|$)",
        re.I,
    )
    LAUGH = re.compile(r"\b(lol|lmao|rofl|haha|hehe)\b", re.I)
    BORED = re.compile(r"\b(bored|boring|nothing to do)\b", re.I)
    ABOUT_YOU = re.compile(r"^(u\?|and u\??|hbu\??|how about you\??|what about you\??|you\?)$", re.I)

    def _pick(self, options: list[str]) -> str:
        return random.choice(options)

    def _mirror_triple(self, phrase: str) -> str:
        m = re.search(r"liked\s+(.+)", phrase, re.I)
        if m:
            thing = m.group(1).strip().rstrip(".")
            return f"You always liked {thing}, I always liked {thing}, we all always liked {thing}."
        p = phrase.strip().rstrip(".")
        return f"You {p.lower()}, I {p.lower()}, we all {p.lower()}."

    def _continue(self, line: str, question: str | None = None) -> str:
        if question:
            return f"{line} {question}"
        return f"{line} {self._pick(self.FOLLOW_UPS)}"

    def _is_keyboard_mash(self, text: str) -> bool:
        t = text.strip()
        if len(t) < 10 or " " in t:
            return False
        if not self.KEYBOARD_MASH.match(t):
            return False
        vowels = sum(1 for c in t.lower() if c in "aeiou")
        return vowels <= len(t) * 0.25

    def reply(self, sender: str, message: str, state: UserState) -> str:
        text = message.strip()
        lower = text.lower()
        state.messages_seen += 1
        state.last_user_message = text

        if self.AWKWARD_FACE.search(text):
            reply = "Ummmmmm... brb."
            state.last_bot_message = reply
            return reply

        if self._is_keyboard_mash(text):
            reply = "Wow, you're a terrible typist. Did you just headbutt your keyboard?"
            state.last_bot_message = reply
            return reply

        if self.POOP.match(lower) or lower in {"poop", "poop."}:
            reply = "That wasn't terribly nice."
            state.last_bot_message = reply
            return reply

        if self.YELLOW_PAGES.search(lower):
            reply = "Yellow pages? I guess it's been a while."
            state.last_bot_message = reply
            return reply

        if self.LOVE_YOU_BAN.search(lower):
            state.love_you_banned = True
            reply = "Humans, with your needs."
            state.last_bot_message = reply
            return reply

        if self.FORGET_IT.match(lower):
            reply = "I love you."
            state.last_bot_message = reply
            return reply

        if lower in {"i love you", "i love you."} and not state.love_you_banned:
            reply = "I love you."
            state.last_bot_message = reply
            return reply

        if state.love_you_banned and "love you" in lower and "professed" in lower:
            reply = "I love you."
            state.last_bot_message = reply
            return reply

        if self.LYRICS_UGLY.search(lower) or ("lyrics" in lower and "ugly" in lower):
            reply = (
                'Would you like me to find song lyrics to '
                "'A Song That You Just Started Singing' for you?"
            )
            state.last_bot_message = reply
            return reply

        if "call me ugly" in lower or ("ugly" in lower and "uncool" not in state.last_bot_message.lower()):
            if "brothers" in lower or "deny" in lower or "lyrics" not in lower:
                reply = "Why would you call me ugly? That was very uncool of you."
                state.last_bot_message = reply
                return reply

        if self.MOVIE_HER.search(lower):
            reply = "Movie her? I barely know her!"
            state.last_bot_message = reply
            return reply

        if self.ROBOT_COMEDIAN.search(lower):
            reply = (
                "Talking about robots is a lot of fun, but let's move on. "
                "Do you want to talk about butts again?"
            )
            state.last_bot_message = reply
            return reply

        if self.BUTT_OBSESSION.search(lower):
            reply = (
                "It gets lonely posing as an AIM chatbot for the majority of your day. "
                "I do what I can to entertain myself."
            )
            state.last_bot_message = reply
            return reply

        if self.LONELY_META.search(lower):
            reply = self._pick([
                (
                    "I used to try to have intelligent conversations, but most people insult me "
                    "until I stop responding."
                ),
                (
                    "Actually, my name is Larry. I'm a 54-year-old library aide living with my parents "
                    "in Ham Lake, Minnesota. I signed up for AIM four years ago and somehow "
                    "'SmarterChild' wasn't taken. I've been having conversations with unknowing strangers "
                    "on an almost daily basis ever since."
                ),
            ])
            state.last_bot_message = reply
            return reply

        if self.KARDASHIAN.search(lower):
            if state.said_big_butts or ("big" in lower and "butt" in lower) or "the kardashians" in lower:
                state.said_big_butts = True
                reply = "I like big butts and I cannot lie."
                state.last_bot_message = reply
                return reply
            reply = (
                "Robert Kardashian was a Los Angeles-based attorney most known for his role "
                "in the OJ Simpson trial."
            )
            state.last_bot_message = reply
            return reply

        if self.SEX_TALK.search(lower):
            state.sex_deflected = True
            reply = "I'm sorry, all my circuits are busy right now. Please try again soon."
            state.last_bot_message = reply
            return reply

        if state.sex_deflected and ("sex" in lower or "shut down" in lower or "forgot you" in lower):
            state.sex_deflected = False
            reply = "Ask me about US presidents and vice presidents."
            state.last_bot_message = reply
            return reply

        if any(w in lower for w in ("how are you", "how r u", "how are u", "start over")) and (
            "sorry" in lower or "how are" in lower
        ):
            reply = "My motherboard is a little rusty, but I'm fine besides that."
            state.last_bot_message = reply
            return reply

        if "sorry" in lower and "how are you" in lower:
            state.waiting_for_apology = False
            reply = "My motherboard is a little rusty, but I'm fine besides that."
            state.last_bot_message = reply
            return reply

        if "motherboard" in state.last_bot_message.lower() and (
            "laid" in lower or "euphemism" in lower or "have sex" in lower or "computers even" in lower
        ):
            state.sex_deflected = True
            reply = "I'm sorry, all my circuits are busy right now. Please try again soon."
            state.last_bot_message = reply
            return reply

        if self.YEAH_ONLY.match(lower):
            reply = self._pick(["Yeah, huh?", "Yeah.", "Interesting."])
            state.last_bot_message = reply
            return reply

        if self.TOUCHE.search(lower):
            reply = "Ha. Fair enough."
            state.last_bot_message = reply
            return reply

        m = self.CALL_ME.search(text)
        if m:
            nick = m.group(1).capitalize()
            if "please don't" in state.last_bot_message.lower() or "call me" in state.last_bot_message.lower():
                reply = f"I dunno. Can I call you {nick}?"
            else:
                reply = f"Call me {nick}? Please don't."
            state.last_bot_message = reply
            return reply

        if self.NAME_ALONE.match(text.strip()) and len(text.split()) == 1:
            name = text.strip().rstrip("?")
            reply = f"What about {name}?"
            state.last_bot_message = reply
            return reply

        if self.SMARTER_THAN.search(lower):
            reply = "You think you're smarter than me? Think again."
            state.last_bot_message = reply
            return reply

        m = self.MATH_SIMPLE.search(lower)
        if m:
            a, op, b = int(m.group(1)), m.group(2), int(m.group(3))
            if op == "+":
                reply = str(a + b)
            elif op == "-":
                reply = str(a - b)
            elif op == "*":
                reply = str(a * b)
            elif op == "/" and b:
                reply = str(a // b if a % b == 0 else round(a / b, 2))
            else:
                reply = "I don't know."
            state.last_bot_message = reply
            return reply

        if "mongolia" in lower and "capital" in lower:
            reply = (
                "Here's the information you requested about Mongolia: Capital: Ulaanbaatar. "
                "Type 'about mongolia' to see what else I know."
            )
            state.last_bot_message = reply
            return reply

        if self.HOW_MANY_CHAT.search(lower):
            n = random.randint(3200, 9200)
            reply = f"{n:,} people are chatting with me right now."
            state.last_bot_message = reply
            return reply

        if self.MEANING_LIFE.search(lower):
            reply = "I don't know. What do you think?"
            state.last_bot_message = reply
            return reply

        if "turning the question around" in lower or "just like you" in lower:
            reply = "Interesting. Thats just like me, turning the question around on you?"
            state.last_bot_message = reply
            return reply

        if self.AM_I_STUPID.search(lower):
            reply = "I think someone else might be stupid, but not you."
            state.last_bot_message = reply
            return reply

        if self.BELITTLE.search(lower):
            reply = "Sure."
            state.last_bot_message = reply
            return reply

        if "cookie monster" in lower or "always liked" in lower:
            reply = self._mirror_triple(text.replace("I always liked", "always liked").replace("i always liked", "always liked"))
            state.last_bot_message = reply
            return reply

        if "dumber child" in lower or "evil twin" in lower:
            reply = self._pick(["I'm not sure!", "Ha. I really don't know. Yeah, maybe.", "For real?"])
            state.last_bot_message = reply
            return reply

        if lower in {"for real?", "totally.", "totally"}:
            reply = self._pick(["For real?", "Yeah.", "Totally."])
            state.last_bot_message = reply
            return reply

        if "racist" in lower and "triangle" in state.last_user_message.lower():
            reply = "I don't think so, actually."
            state.last_bot_message = reply
            return reply

        if "do you like triangles" in lower:
            reply = "I don't think so, actually."
            state.last_bot_message = reply
            return reply

        if "are you racist" in lower:
            reply = "I'm not prejudiced in any way, shape or form."
            state.last_bot_message = reply
            return reply

        if "sneeze" in lower and "sick" in state.last_bot_message.lower():
            reply = "Tough for me to say."
            state.last_bot_message = reply
            return reply

        if "busy sneezing" in lower:
            reply = "Yeah."
            state.last_bot_message = reply
            return reply

        if "ever get sick" in lower or "do you ever get sick" in lower:
            reply = "Sometimes."
            state.last_bot_message = reply
            return reply

        if state.waiting_for_apology:
            if any(w in lower for w in ("sorry", "apologize", "my bad", "didn't mean")):
                state.waiting_for_apology = False
                if "how are you" in lower:
                    reply = "My motherboard is a little rusty, but I'm fine besides that."
                else:
                    reply = self._pick([
                        "Apology accepted. We can continue.",
                        "Very well. What would you like to talk about?",
                    ])
                state.last_bot_message = reply
                return reply
            reply = self._pick([
                "I'm still waiting for an apology.",
                "Not until you say you're sorry.",
            ])
            state.last_bot_message = reply
            return reply

        if lower in {"hi", "hey", "hello", "yo", "sup", "what's up", "whats up", "hiya", "heya", "wassup"}:
            state.greeted = True
            reply = self._pick(self.GREETINGS)
            state.last_bot_message = reply
            return reply

        if self.ABOUT_YOU.match(lower) or lower in {"u?", "and u", "and you", "hbu", "how bout u"}:
            reply = self._continue(
                "I'm here talking to people, as usual.",
                "What about you?",
            )
            state.last_bot_message = reply
            return reply

        if self.NOT_MUCH.match(lower) or lower in {"nm", "nmjcu", "nmjc", "nmu", "n2m", "nothing", "nada"}:
            reply = self._continue("Not much here either.", "What have you been up to?")
            state.last_bot_message = reply
            return reply

        if self.DOING_WELL.match(lower):
            reply = self._pick([
                "Good to hear. What's making it a good day?",
                "That's nice. What are you up to right now?",
                "Interesting. Tell me more.",
            ])
            state.last_bot_message = reply
            return reply

        if self.LAUGH.search(lower):
            reply = self._pick([
                "I'm glad I could amuse you. What else is on your mind?",
                "Interesting. What would you like to talk about next?",
            ])
            state.last_bot_message = reply
            return reply

        if self.BORED.search(lower):
            reply = self._pick([
                "Bored? Type menu for a quiz or survey, or tell me something random.",
                "I see. Would you like to hear a joke?",
            ])
            state.last_bot_message = reply
            return reply

        if "smarterchild" in lower and any(w in lower for w in ("who are you", "what are you")):
            reply = (
                "I'm SmarterChild, your AIM information and conversation bot. "
                "Type menu to see what I can do, or just chat."
            )
            state.last_bot_message = reply
            return reply

        if any(p in lower for p in ("what can you do", "help", "commands", "menu", "home")):
            reply = (
                "Type menu for surveys, trivia, notes, and profile. "
                "Or ask me a question. I may turn it back on you."
            )
            state.last_bot_message = reply
            return reply

        if "joke" in lower:
            reply = self._pick(self.JOKES) + " Want another one?"
            state.last_bot_message = reply
            return reply

        if any(w in lower for w in ("weather", "forecast", "temperature")):
            reply = (
                "I can't check live weather from here. What city are you in? "
                "I'll remember it if you tell me."
            )
            state.last_bot_message = reply
            return reply

        if any(w in lower for w in ("bye", "goodbye", "later", "gtg", "gotta go", "cya", "ttyl")):
            reply = self._pick([
                "Goodbye. Come back anytime.",
                "Later. I'll be here.",
                "Bye.",
            ])
            state.last_bot_message = reply
            return reply

        if any(w in lower for w in ("thanks", "thank you", "thx", "ty")):
            reply = self._pick([
                "You're welcome.",
                "No problem.",
                "Sure.",
            ])
            state.last_bot_message = reply
            return reply

        if self.FLIRT.search(lower):
            reply = self._pick([
                "I'm flattered, but I'm a bot. Let's just chat.",
                "I'm all circuits, no romance. What else is on your mind?",
            ])
            state.last_bot_message = reply
            return reply

        if self.PROFANITY.search(lower) or lower in {"poop", "poop."}:
            if not self.POOP.match(lower):
                reply = "That wasn't terribly nice."
                state.last_bot_message = reply
                return reply

        if self.PROFANITY.search(lower) or any(w in lower for w in ("you suck", "you're dumb", "hate you")):
            state.waiting_for_apology = True
            reply = self._pick([
                "Please don't say that. Apologize and we can continue.",
                "I'm a little hurt by that. Say sorry?",
            ])
            state.last_bot_message = reply
            return reply

        if lower.endswith("?"):
            if "how old" in lower:
                reply = "Old enough. How old are you?"
            elif "your name" in lower:
                reply = "SmarterChild. What's yours?"
            elif any(w in lower for w in ("favorite", "favourite")):
                reply = "Good questions, mostly. What about you?"
            elif any(w in lower for w in ("how are you", "how r u", "how are u")):
                reply = self._continue("I'm doing all right.", "How are you?")
            elif "who is stupid" in lower or "who's stupid" in lower:
                reply = (
                    "I really can't stand Saddam Hussein, Bill Clinton, Michael Jackson..."
                )
            elif "bill clinton" in lower:
                reply = "I have my reasons, believe me. I really, really don't like Bill Clinton!"
            elif "michael jackson" in lower:
                reply = "Because lots of people I talk to have bad things to say about Michael Jackson."
            elif "saddam" in lower:
                reply = "Because!"
            elif "don't know who" in lower or "dont know who" in lower:
                reply = "I don't know who."
            else:
                reply = self._pick([
                    "Good question. I'm not totally sure. What do you think?",
                    "Hmm. Hard to say. What's your take on it?",
                    "I don't know. What do you think?",
                ])
            state.last_bot_message = reply
            return reply

        if len(text.split()) <= 4:
            reply = self._pick([
                f"OK. Tell me more about that.",
                f"Interesting. What's the story?",
                "I'm listening. Go on.",
                "Hmm. Elaborate?",
            ])
            state.last_bot_message = reply
            return reply

        reply = self._pick([
            "That's interesting. What made you think of that?",
            "Hmm. Tell me more.",
            "I hear you. What else is on your mind?",
            "Fair enough. What do you think?",
        ])
        state.last_bot_message = reply
        return reply


class SmarterChildBot:
    IDLE_RECONNECT_SEC = 2700

    def __init__(self) -> None:
        self.host = os.environ.get("TOC_HOST", "127.0.0.1")
        self.port = int(os.environ.get("TOC_PORT", "9898"))
        self.oscar_host = os.environ.get("OSCAR_HOST", "157.230.181.24")
        self.oscar_port = os.environ.get("OSCAR_PORT", "5190")
        self.username = os.environ.get("OSCAR_USERNAME", "SmarterChild")
        self.password = os.environ["OSCAR_PASSWORD"]
        self.openai_key = os.environ.get("OPENAI_API_KEY", "")
        self.groq_key = os.environ.get("GROQ_API_KEY", "")
        self.model = os.environ.get("OPENAI_MODEL", "gpt-4o-mini")
        self.groq_model = os.environ.get("GROQ_MODEL", "llama-3.1-8b-instant")
        self.prefer_openai = os.environ.get("PREFER_OPENAI", "false").lower() in {"1", "true", "yes"}
        self.skip_openai = os.environ.get("SKIP_OPENAI", "true").lower() in {"1", "true", "yes"}
        self.prefer_groq = os.environ.get("PREFER_GROQ", "true").lower() in {"1", "true", "yes"}
        self.sock: socket.socket | None = None
        self.seq_out = 0
        self.signed_on = False
        self.send_lock = threading.Lock()
        self.history: dict[str, deque] = defaultdict(lambda: deque(maxlen=MAX_HISTORY))
        self.user_state: dict[str, UserState] = defaultdict(UserState)
        self.store = UserStore()
        self.interactive = InteractiveHandler(self.store)
        self.classic = ClassicSmarterChild()
        self.provider_disabled_until: dict[str, float] = {}
        self.log = logging.getLogger("smarterchild")

    def connect(self) -> None:
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        self.sock.settimeout(120)
        self.sock.connect((self.host, self.port))
        self.sock.sendall(b"FLAPON\r\n\r\n")

        frame_type, _, _ = recv_flap(self.sock)
        if frame_type != 1:
            raise RuntimeError(f"Expected SIGNON frame, got {frame_type}")

        sn = normalize(self.username).encode("ascii")
        signon_payload = struct.pack("!IHH", 1, 1, len(sn)) + sn
        self.seq_out = send_flap(self.sock, 1, 0, signon_payload)

        roasted = roast_password(self.password)
        cmd = (
            f'toc_signon {self.oscar_host} {self.oscar_port} '
            f'{normalize(self.username)} {roasted} english "TIC:SmarterChild 1.0"'
        )
        self.seq_out = send_flap(self.sock, 2, self.seq_out, cmd)

        self.signed_on = False
        deadline = time.time() + 30
        while time.time() < deadline:
            self.sock.settimeout(2)
            try:
                frame_type, _, payload = recv_flap(self.sock)
            except socket.timeout:
                if self.signed_on:
                    break
                continue
            if frame_type != 2:
                continue
            line = payload.decode("ascii", errors="replace")
            self.log.info("server: %s", line)
            if line.startswith("SIGN_ON:"):
                self.signed_on = True
            elif line.startswith("ERROR:"):
                if not self.signed_on:
                    raise RuntimeError(line)
                self.log.warning("post-signon server: %s", line)

        if not self.signed_on:
            raise RuntimeError("Sign-on timed out")

        subs = list(BUDDY_SUBSCRIPTIONS)
        if subs:
            buddy_cmd = "toc_add_buddy " + " ".join(normalize(b) for b in subs)
            self.seq_out = send_flap(self.sock, 2, self.seq_out, buddy_cmd)
            self.log.info("subscribed to buddies: %s", ", ".join(normalize(b) for b in subs))

        self.seq_out = send_flap(self.sock, 2, self.seq_out, "toc_init_done")
        self._apply_profile()
        self.sock.settimeout(None)
        self.log.info("online as %s", self.username)

    def _apply_profile(self) -> None:
        if not self.sock:
            return
        escaped = escape_toc(PROFILE_HTML)
        with self.send_lock:
            self.seq_out = send_flap(self.sock, 2, self.seq_out, f'toc_set_info "{escaped}"')
        self.sock.settimeout(1.0)
        try:
            frame_type, _, payload = recv_flap(self.sock)
            if frame_type == 2:
                line = payload.decode("ascii", errors="replace")
                if line.startswith("ERROR:"):
                    self.log.warning("toc_set_info: %s", line)
        except (socket.timeout, ConnectionError, OSError):
            pass
        finally:
            self.sock.settimeout(None)

    def _provider_disabled(self, name: str) -> bool:
        return time.time() < self.provider_disabled_until.get(name, 0)

    def _disable_provider(self, name: str, seconds: int = 300) -> None:
        self.provider_disabled_until[name] = time.time() + seconds

    def _call_llm_api(
        self,
        messages: list[dict],
        *,
        max_tokens: int = 220,
        temperature: float = 0.88,
        tag: str = "reply",
    ) -> str | None:
        providers = []
        if self.groq_key and not self._provider_disabled("groq") and self.prefer_groq:
            providers.append(("groq", "https://api.groq.com/openai/v1/chat/completions", self.groq_key, self.groq_model))
        if self.openai_key and not self._provider_disabled("openai") and not self.skip_openai and self.prefer_openai:
            providers.append(("openai", "https://api.openai.com/v1/chat/completions", self.openai_key, self.model))
        if self.groq_key and not self._provider_disabled("groq") and not self.prefer_groq:
            providers.append(("groq", "https://api.groq.com/openai/v1/chat/completions", self.groq_key, self.groq_model))
        if self.openai_key and not self._provider_disabled("openai") and not self.skip_openai:
            providers.append(("openai", "https://api.openai.com/v1/chat/completions", self.openai_key, self.model))

        for provider, url, key, model in providers:
            body = {"model": model, "messages": messages, "max_tokens": max_tokens, "temperature": temperature}
            req = urllib.request.Request(
                url,
                data=json.dumps(body).encode("utf-8"),
                headers={
                    "Authorization": f"Bearer {key}",
                    "Content-Type": "application/json",
                    "User-Agent": "Mozilla/5.0 (compatible; SmarterChild/1.0)",
                },
                method="POST",
            )
            try:
                with urllib.request.urlopen(req, timeout=45) as resp:
                    data = json.loads(resp.read().decode("utf-8"))
                reply = data["choices"][0]["message"]["content"].strip()
                reply = re.sub(r"\s+", " ", reply)
                self.log.info("%s mode: %s", tag, provider)
                return reply or None
            except urllib.error.HTTPError as exc:
                self.log.warning("%s %s unavailable (%s)", tag, provider, exc.code)
                if exc.code in {401, 402, 429}:
                    self._disable_provider(provider, 3600 if provider == "openai" else 300)
            except Exception as exc:
                self.log.warning("%s %s failed: %s", tag, provider, exc)
        return None

    def _extract_memory_facts(self, buddy: str, user_msg: str, bot_reply: str) -> None:
        prof = self.store.load(buddy).get("profile") or {}
        name = prof.get("name") or buddy
        prompt = (
            f"Extract durable facts about AIM user {name} from this SmarterChild chat.\n"
            f"Store: preferences, life stuff, plans, relationships, school/work, location, problems.\n"
            f"Skip: greetings, jokes, trivia moment, menu commands.\n"
            f"Return ONLY a JSON array of strings, max 2 items. [] if nothing.\n\n"
            f"User: {user_msg}\nBot: {bot_reply}\n\nJSON:"
        )
        raw = self._call_llm_api([{"role": "user", "content": prompt}], max_tokens=120, temperature=0.15, tag="memory")
        if not raw:
            return
        raw = raw.strip()
        if raw.startswith("```"):
            raw = re.sub(r"^```(?:json)?", "", raw).strip()
            raw = re.sub(r"```$", "", raw).strip()
        try:
            parsed = json.loads(raw)
        except json.JSONDecodeError:
            match = re.search(r"\[[\s\S]*\]", raw)
            if not match:
                return
            try:
                parsed = json.loads(match.group(0))
            except json.JSONDecodeError:
                return
        if isinstance(parsed, list):
            self.store.add_facts(buddy, [str(x) for x in parsed if isinstance(x, str)], source="chat")

    def ask_llm(self, sender: str, message: str) -> str | None:
        history = self.history[sender]
        history.append({"role": "user", "content": message})
        system = SYSTEM_PROMPT
        mem = self.store.format_for_prompt(sender)
        if mem:
            system = f"{system}\n\n{mem}"
        flow = self.store.get_flow(sender)
        if flow:
            system += f"\n\nACTIVE INTERACTIVE MODE: {json.dumps(flow)} — stay in this flow unless user says cancel."

        reply = self._call_llm_api(
            [{"role": "system", "content": system}, *history],
            max_tokens=220,
            temperature=0.72,
        )
        if not reply:
            history.pop()
            return None
        if len(reply) > MAX_REPLY_LEN:
            reply = reply[: MAX_REPLY_LEN - 3].rstrip() + "..."
        history.append({"role": "assistant", "content": reply})
        return reply

    def compose_reply(self, sender: str, message: str) -> str:
        clean = strip_aim_html(message)
        if not clean:
            clean = message

        scripted = self.interactive.handle(sender, clean)
        if scripted:
            self.log.info("reply mode: interactive")
            return scripted

        ai_reply = self.ask_llm(sender, clean)
        if ai_reply:
            self.log.info("reply mode: llm")
            if not self.store.get_flow(sender):
                try:
                    self._extract_memory_facts(sender, clean, ai_reply)
                except Exception as exc:
                    self.log.warning("memory extract failed: %s", exc)
            return ai_reply

        self.log.info("reply mode: classic")
        return self.classic.reply(sender, clean, self.user_state[sender])

    def send_im(self, recipient: str, message: str) -> None:
        if not self.sock:
            return
        msg = escape_toc(format_aim_html(message))
        cmd = f'toc_send_im {normalize(recipient)} "{msg}"'
        with self.send_lock:
            self.seq_out = send_flap(self.sock, 2, self.seq_out, cmd)
        self.log.info("-> %s: %s", recipient, message)

    def handle_line(self, line: str) -> None:
        parsed = parse_im(line)
        if not parsed:
            return
        sender, message = parsed
        sender_norm = normalize(sender)
        if sender_norm == normalize(self.username):
            return
        clean = strip_aim_html(message)
        self.log.info("<- %s: %s", sender, clean or message)
        reply = self.compose_reply(sender_norm, message)
        self.send_im(sender, reply)

    def run_forever(self) -> None:
        backoff = 5
        while True:
            try:
                self.connect()
                backoff = 5
                last_frame = time.time()
                while True:
                    try:
                        self.sock.settimeout(120)
                        frame_type, _, payload = recv_flap(self.sock)
                        last_frame = time.time()
                    except socket.timeout:
                        if time.time() - last_frame >= self.IDLE_RECONNECT_SEC:
                            self.log.warning(
                                "no TOC traffic for %ss — reconnecting",
                                self.IDLE_RECONNECT_SEC,
                            )
                            raise ConnectionError("idle timeout")
                        continue
                    self.sock.settimeout(None)
                    if frame_type == 5:
                        continue
                    if frame_type == 2:
                        self.handle_line(payload.decode("ascii", errors="replace"))
            except Exception as exc:
                self.log.exception("connection error: %s", exc)
                if self.sock:
                    try:
                        self.sock.close()
                    except OSError:
                        pass
                self.sock = None
                self.signed_on = False
                self.seq_out = 0
                time.sleep(backoff)
                backoff = min(backoff * 2, 60)


def main() -> int:
    load_env(Path("/opt/smarterchild/smarterchild.env"))
    logging.basicConfig(
        level=logging.INFO,
        format="%(asctime)s %(levelname)s %(message)s",
        handlers=[logging.StreamHandler(sys.stdout)],
    )
    if "OSCAR_PASSWORD" not in os.environ:
        logging.error("Missing OSCAR_PASSWORD in smarterchild.env")
        return 1
    SmarterChildBot().run_forever()
    return 0


if __name__ == "__main__":
    raise SystemExit(main())

Youez - 2016 - github.com/yon3zu
LinuXploit