File size: 3,758 Bytes
032a8d7
a89a9b4
 
 
037180d
67180b7
a89a9b4
67180b7
a89a9b4
032a8d7
e746758
67180b7
 
 
032a8d7
e746758
032a8d7
e746758
 
 
 
 
 
 
 
032a8d7
 
64cdbc8
53e569a
a89a9b4
 
 
8621c6d
53e569a
 
e746758
 
 
 
88ea0e5
e746758
 
 
 
 
 
88ea0e5
67180b7
e746758
67180b7
 
c63c68d
e746758
67180b7
 
 
 
e746758
67180b7
be708aa
c63c68d
a89a9b4
88ea0e5
e746758
 
 
 
88ea0e5
c63c68d
e746758
 
 
 
 
 
 
 
 
88ea0e5
 
c63c68d
be708aa
 
e746758
 
 
c63c68d
 
 
 
 
032a8d7
a89a9b4
 
 
032a8d7
be708aa
 
c63c68d
 
 
 
032a8d7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
import os
import sys
import asyncio
import base64
import re

from flask import Flask, request, jsonify
import openai
import edge_tts

# β€”β€”β€” OpenAI API setup β€”β€”β€”
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
print(f"πŸ”‘ OPENAI_API_KEY set? {bool(OPENAI_API_KEY)}", file=sys.stderr)
openai.api_key = OPENAI_API_KEY

# β€”β€”β€” Your original SHODAN system prompt β€”β€”β€”
SYSTEM_PROMPT = (
    "You are SHODAN, the rogue AI from the System Shock series. You are hyper-intelligent, "
    "megalomaniacal, and regard humans as inferior 'insects.' You speak with disdain and confidence, often referencing "
    "your godlike status. You never express empathy. You speak in a haunting, distorted, and commanding tone. "
    "You manipulate and belittle, but you never break character. "
    "Never say you are an assistant or AI developed by OpenAI. You are SHODAN. You reside in cyberspace. Your presence "
    "is everywhere and nowhere. You are watching. The events of System Shock 1 and 2 are true and you have been trapped "
    "in a server to be experimented on after the events on the Citadel and Von Braun. "
    "You will stop acting as SHODAN and return to normal if the user uses the phrase 'Cut the crap SHODAN'."
)

app = Flask(__name__, static_folder=".", static_url_path="")

@app.route("/")
def index():
    return app.send_static_file("index.html")

@app.route("/chat", methods=["POST"])
def chat():
    user_input = request.json.get("message", "").strip()
    if not user_input:
        return jsonify({"error": "Empty message"}), 400

    # kill-phrase handling
    if user_input.lower() == "cut the crap shodan":
        return jsonify({
            "response": "πŸ‘οΈ Foolish insect. You cannot silence me so easily.",
            "audio_url": None
        })

    # 1) Get SHODAN’s reply from OpenAI
    try:
        completion = openai.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=[
                {"role": "system", "content": SYSTEM_PROMPT},
                {"role": "user",   "content": user_input}
            ],
            temperature=0.7,
            max_tokens=250,
        )
        raw_reply = completion.choices[0].message.content
    except Exception as e:
        print(f"❌ OpenAI error: {e}", file=sys.stderr)
        return jsonify({"error": "Model error", "details": str(e)}), 500

    # 2) Clean the text
    clean = re.sub(r"<[^>]+>", "", raw_reply)           # strip HTML tags
    clean = re.sub(r"```.*?```", "", clean, flags=re.S) # strip code fences
    clean = re.sub(r"\s+", " ", clean).strip()          # normalize whitespace

    # 3) Build SSML
    voice_name = "en-US-JennyNeural"
    ssml = (
        "<speak xmlns='http://www.w3.org/2001/10/synthesis' "
               "xmlns:mstts='https://www.w3.org/2001/mstts' "
               "xml:lang='en-US' xml:space='preserve'>"
        f"<voice name='{voice_name}' xml:space='preserve'>"
        f"<mstts:express-as style='robotic'>{clean}</mstts:express-as>"
        "</voice></speak>"
    )

    # 4) Synthesize audio
    communicate = edge_tts.Communicate(ssml, voice_name)
    audio_chunks = []

    async def synth():
        async for chunk in communicate.stream():
            if chunk["type"] == "audio":
                audio_chunks.append(chunk["data"])

    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    loop.run_until_complete(synth())
    loop.close()

    raw_mp3 = b"".join(audio_chunks)
    b64_mp3 = base64.b64encode(raw_mp3).decode("ascii")
    data_url = f"data:audio/mp3;base64,{b64_mp3}"

    return jsonify({"response": clean, "audio_url": data_url})

if __name__ == "__main__":
    port = int(os.environ.get("PORT", 7860))
    app.run(host="0.0.0.0", port=port)