File size: 5,376 Bytes
1058e3e ee310ff 1058e3e 664d27e 1058e3e ee310ff 1058e3e ee310ff 1058e3e ee310ff 1058e3e 664d27e 1058e3e 664d27e 1058e3e 664d27e 1058e3e ee310ff 1058e3e ee310ff 1058e3e ee310ff 1058e3e c54772b ee310ff 1058e3e 664d27e 1058e3e 664d27e e80d7b7 664d27e 056b4f0 664d27e e80d7b7 664d27e e80d7b7 664d27e e80d7b7 664d27e e80d7b7 664d27e e80d7b7 664d27e e80d7b7 664d27e 2bbf3ba 664d27e 6dbb93e 664d27e 6dbb93e 664d27e 6dbb93e 664d27e 1058e3e 664d27e 1058e3e ee310ff 1058e3e 664d27e 1058e3e ee310ff 1058e3e 664d27e 1058e3e 664d27e 1058e3e 664d27e ee310ff 664d27e |
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 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
import logging
import os
import sqlite3
import threading
import urllib.parse
from http.server import BaseHTTPRequestHandler, HTTPServer
import plivo
import streamlit as st
from streamlit_autorefresh import st_autorefresh
from dotenv import load_dotenv
# --- Setup logging ---
logging.basicConfig(level=logging.INFO)
# --- Load environment variables ---
load_dotenv()
# --- Setup plivo ---
try:
PLIVO_AUTH_ID = os.getenv("PLIVO_AUTH_ID")
PLIVO_AUTH_TOKEN = os.getenv("PLIVO_AUTH_TOKEN")
KORA_PHONE_NUMBER = os.getenv("KORA_PHONE_NUMBER")
client = plivo.RestClient(auth_id=PLIVO_AUTH_ID, auth_token=PLIVO_AUTH_TOKEN)
except Exception as e:
st.error(f"Error setting up Plivo: {e}")
# --- Thread lock for SQLite access ---
db_lock = threading.Lock()
# --- Setup SQLite ---
try:
conn = sqlite3.connect("chat.db", check_same_thread=False)
c = conn.cursor()
with db_lock:
c.execute(
"""
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sender TEXT,
text TEXT,
timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
)
"""
)
conn.commit()
except sqlite3.Error as e:
st.error(f"Error setting up SQLite: {e}")
# --- Webhook Server (for receiving SMS) ---
class SMSWebhookHandler(BaseHTTPRequestHandler):
def do_POST(self):
try:
length = int(self.headers["Content-Length"])
post_data = self.rfile.read(length)
data = urllib.parse.parse_qs(post_data.decode("utf-8"))
logging.info(f"Webhook received: {data}")
message_text = data.get("Text", [""])[0]
if message_text:
with db_lock:
c.execute(
"INSERT INTO messages (sender, text) VALUES (?, ?)",
(KORA_PHONE_NUMBER, message_text),
)
conn.commit()
self.send_response(200)
self.end_headers()
self.wfile.write(
b"<?xml version='1.0'?><Response><Message>Got it!</Message></Response>"
)
except Exception as e:
logging.error(f"Webhook error: {e}")
self.send_response(500)
self.end_headers()
self.wfile.write(b"Error processing request")
# --- Run webhook server in background ---
def run_webhook_server():
try:
server = HTTPServer(("", 8502), SMSWebhookHandler)
logging.info("Webhook server started on port 8502")
server.serve_forever()
except Exception as e:
logging.error(f"Error starting webhook server: {e}")
# --- Start webhook server thread ---
if not hasattr(st.session_state, "webhook_server_started"):
threading.Thread(target=run_webhook_server, daemon=True).start()
st.session_state.webhook_server_started = True
# --- Streamlit UI ---
st.title("📲 Chat with KORA")
# Initialize session state variables
if "show_confirmation" not in st.session_state:
st.session_state.show_confirmation = False
if "last_message_count" not in st.session_state:
st.session_state.last_message_count = 0
# Phone input
PLIVO_PHONE_NUMBER = st.text_input(
"Enter your phone number to chat with KORA", value="+13602304837", max_chars=15
)
# --- Clear Chat UI ---
if not st.session_state.show_confirmation:
if st.button("Clear Chat"):
st.session_state.show_confirmation = True
st.rerun()
else:
col1, col2 = st.columns(2)
if col1.button("Yes, clear chat"):
try:
with db_lock:
c.execute("DELETE FROM messages")
conn.commit()
st.success("Chat history cleared.")
st.session_state.show_confirmation = False
st.session_state.last_message_count = 0
st.rerun()
except sqlite3.Error as e:
st.error(f"Error clearing chat history: {e}")
elif col2.button("Cancel"):
st.session_state.show_confirmation = False
st.rerun()
# --- Display Chat Messages ---
try:
with db_lock:
messages = c.execute(
"SELECT sender, text FROM messages WHERE sender IN (?, ?) ORDER BY timestamp ASC",
(PLIVO_PHONE_NUMBER, KORA_PHONE_NUMBER),
).fetchall()
except sqlite3.Error as e:
messages = []
st.error(f"Error fetching messages: {e}")
# Display messages
for sender, text in messages:
role = "user" if sender == PLIVO_PHONE_NUMBER else "assistant"
st.chat_message(role).write(text)
st.session_state.last_message_count = len(messages)
# --- Chat Input ---
if prompt := st.chat_input("Type your message..."):
try:
# Save message to DB
with db_lock:
c.execute(
"INSERT INTO messages (sender, text) VALUES (?, ?)",
(PLIVO_PHONE_NUMBER, prompt),
)
conn.commit()
# Send message via Plivo
client.messages.create(
text=prompt, src=PLIVO_PHONE_NUMBER, dst=KORA_PHONE_NUMBER
)
st.rerun() # Refresh to show new message immediately
except sqlite3.Error as e:
st.error(f"Error saving message: {e}")
except Exception as e:
st.error(f"Error sending message via Plivo: {e}")
st_autorefresh(interval=1000, key="auto_refresh") |