🚀 Initial commit: BSN Chatbot — Multi-Channel Intake System

WhatsApp webhook, admin dashboard, public frontend, media handling, LLM auto-summarize, hall/stand detection, iOS-style backend
This commit is contained in:
Hermes Agent
2026-06-17 13:22:19 +02:00
commit bbefb8807b
6 changed files with 2191 additions and 0 deletions
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env python3
"""Initialize the BSN Intake SQLite database with schema + sample data."""
import sqlite3
import os
DB_PATH = os.path.join(os.path.dirname(__file__), "bsn_intake.db")
SCHEMA = """
-- Incoming submissions from all channels
CREATE TABLE IF NOT EXISTS submissions (
id INTEGER PRIMARY KEY AUTOINCREMENT,
channel TEXT NOT NULL, -- 'whatsapp', 'telegram', 'web_form'
sender_id TEXT NOT NULL, -- phone number, telegram ID, email
type TEXT NOT NULL, -- 'text', 'image', 'voice', 'video'
content TEXT, -- transcribed text or message body
media_path TEXT, -- local path to saved media file
status TEXT DEFAULT 'new', -- 'new', 'processing', 'done', 'flagged'
category TEXT, -- Hermes-classified category
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Knowledge base for the query chatbot
CREATE TABLE IF NOT EXISTS knowledge (
id INTEGER PRIMARY KEY AUTOINCREMENT,
key TEXT UNIQUE NOT NULL, -- lookup key (e.g. 'autor_uwe_rosenberg')
question_pattern TEXT, -- "Where is Uwe Rosenberg?"
answer TEXT NOT NULL, -- "Hall 3, Booth B12, 10am-6pm"
category TEXT,
tags TEXT, -- comma-separated
valid_from DATE,
valid_until DATE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- Indexes for fast lookups
CREATE INDEX IF NOT EXISTS idx_submissions_status ON submissions(status);
CREATE INDEX IF NOT EXISTS idx_submissions_channel ON submissions(channel);
CREATE INDEX IF NOT EXISTS idx_submissions_category ON submissions(category);
CREATE INDEX IF NOT EXISTS idx_knowledge_key ON knowledge(key);
CREATE INDEX IF NOT EXISTS idx_knowledge_category ON knowledge(category);
"""
SAMPLE_SUBMISSIONS = [
("whatsapp", "+491234567890", "text", "Wo ist der Stand von Feuerland? Hallo?", "new", None),
("whatsapp", "+491234567891", "text", "Catan ist ausverkauft in Halle 5!", "new", "ausverkauft"),
("telegram", "8520780873", "text", "Habe eben gesehen: Kosmos Halle 3, Stand A42 hat noch Restbestände von Die Crew", "new", "restbestände"),
("web_form", "besucher@example.com", "text", "Warum gibt es keine barrierefreien Zugänge in Halle 8?", "flagged", "kritik"),
]
SAMPLE_KNOWLEDGE = [
("feuerland_stand", "Wo ist Feuerland?", "Feuerland Spiele findest du in Halle 3, Stand C17. Geöffnet von 1018 Uhr.", "verlage", "feuerland, stand, messe", "2026-10-01", "2026-10-04"),
("catan_verfuegbar", "Ist Catan noch verfügbar?", "Catan war Stand 12.06.2026 in Halle 5 ausverkauft. Kosmos meldet Nachschub für Morgen früh.", "verlage", "catan, kosmos, ausverkauft", "2026-10-01", "2026-10-04"),
("oeffnungszeiten", "Wann öffnet die Messe?", "Die Spiel Essen 2026 öffnet Donnerstag bis Samstag von 1018 Uhr, Sonntag von 1017 Uhr.", "messe", "öffnungszeiten, messe, essen", None, None),
]
def init():
conn = sqlite3.connect(DB_PATH)
conn.executescript(SCHEMA)
# Check if data already exists
count = conn.execute("SELECT COUNT(*) FROM submissions").fetchone()[0]
if count == 0:
conn.executemany(
"INSERT INTO submissions (channel, sender_id, type, content, status, category) VALUES (?,?,?,?,?,?)",
SAMPLE_SUBMISSIONS,
)
print(f"Inserted {len(SAMPLE_SUBMISSIONS)} sample submissions")
count = conn.execute("SELECT COUNT(*) FROM knowledge").fetchone()[0]
if count == 0:
conn.executemany(
"INSERT INTO knowledge (key, question_pattern, answer, category, tags, valid_from, valid_until) VALUES (?,?,?,?,?,?,?)",
SAMPLE_KNOWLEDGE,
)
print(f"Inserted {len(SAMPLE_KNOWLEDGE)} sample knowledge entries")
conn.commit()
conn.close()
print(f"Database initialized: {DB_PATH}")
if __name__ == "__main__":
init()