kora / app.py
Ramanjit's picture
chore: update dependencies and add streamlit-autorefresh
664d27e
Raw History Blame Contribute Delete
5.38 kB
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")