modified: .env
new file: __debug_bin.exe modified: bot.db modified: db/db.go modified: go.mod new file: handlers/auth.go modified: handlers/dashboard.go new file: handlers/saas.go modified: handlers/webhook.go modified: main.go new file: saas_bot.db modified: services/openrouter.go new file: services/types.go modified: services/whatsapp.go new file: static/style.css modified: templates/dashboard.html new file: templates/landing.html new file: templates/login.html new file: templates/register.html deleted: types/types.go
This commit is contained in:
118
db/db.go
118
db/db.go
@@ -2,6 +2,7 @@ package db
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
_ "modernc.org/sqlite"
|
||||
)
|
||||
@@ -10,64 +11,93 @@ var Conn *sql.DB
|
||||
|
||||
func Init() {
|
||||
var err error
|
||||
Conn, err = sql.Open("sqlite", "./bot.db")
|
||||
Conn, err = sql.Open("sqlite", "./saas_bot.db")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
schema := `
|
||||
CREATE TABLE IF NOT EXISTS clients (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT,
|
||||
tier TEXT,
|
||||
msg_count INTEGER DEFAULT 0
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
email TEXT UNIQUE,
|
||||
password_hash TEXT,
|
||||
subscription_tier TEXT DEFAULT 'free',
|
||||
stripe_customer_id TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS bot_configs (
|
||||
user_id INTEGER PRIMARY KEY,
|
||||
whatsapp_phone_id TEXT UNIQUE,
|
||||
whatsapp_token TEXT,
|
||||
bot_name TEXT DEFAULT 'My Assistant',
|
||||
system_prompt TEXT DEFAULT 'You are a helpful assistant.',
|
||||
availability_hours TEXT DEFAULT 'Mon-Fri 09:00-17:00',
|
||||
FOREIGN KEY(user_id) REFERENCES users(id)
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS appointments (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
client_id TEXT,
|
||||
user_id INTEGER,
|
||||
customer_phone TEXT,
|
||||
appointment_date TEXT,
|
||||
status TEXT DEFAULT 'confirmed'
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS chats (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
title TEXT DEFAULT 'New Chat',
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
||||
appointment_time DATETIME,
|
||||
status TEXT DEFAULT 'confirmed',
|
||||
FOREIGN KEY(user_id) REFERENCES users(id)
|
||||
);
|
||||
`
|
||||
_, err = Conn.Exec(schema)
|
||||
if err != nil {
|
||||
log.Fatal("Migration Error:", err)
|
||||
}
|
||||
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
chat_id INTEGER,
|
||||
role TEXT, -- 'user' or 'assistant'
|
||||
content TEXT,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY(chat_id) REFERENCES chats(id)
|
||||
);`
|
||||
Conn.Exec(schema)
|
||||
seedUser()
|
||||
}
|
||||
|
||||
func SaveAppointment(phone string, date string) error {
|
||||
_, err := Conn.Exec(
|
||||
"INSERT INTO appointments (customer_phone, appointment_date, status) VALUES (?, ?, ?)",
|
||||
phone, date, "confirmed",
|
||||
)
|
||||
// seedUser creates a default user so you can test the dashboard immediately
|
||||
func seedUser() {
|
||||
var count int
|
||||
Conn.QueryRow("SELECT COUNT(*) FROM users").Scan(&count)
|
||||
if count == 0 {
|
||||
log.Println("🌱 Seeding default user (ID: 1)...")
|
||||
_, _ = Conn.Exec("INSERT INTO users (email, subscription_tier) VALUES ('admin@sekibot.com', 'pro')")
|
||||
// Insert default bot config for User 1
|
||||
// NOTE: You must update these values in the Dashboard or DB to match your real Meta credentials!
|
||||
_, _ = Conn.Exec(`INSERT INTO bot_configs (user_id, whatsapp_phone_id, whatsapp_token, bot_name)
|
||||
VALUES (1, '986583417873961', 'EAATqIU03y9YBQ1DnscXkt0QQ8lfhWQbI8TT0wRNdB9ZAGLWEdPhN3761E0XBXBdzJiZA3uiPEugjhIS1TjrUZCu979aiiSYFvjbDjFRFYGVsGfqIZCB13H6AaviQHlBNksil9JlkefZAy4ZBFqZCkAcYGjGNtZBWHaXZCaMYTMmfn7rOAx4IUt6eHjfiVkXVquOoqDQY8oVOs5HAekLWNZBqsxm2w2J34AacAzsUwzem6kmsYcKs9CDQ9wIJBRw9FDaKkbV64waI1FdEI7ZALkZCKZBEWUFeA', 'Seki Bot')`)
|
||||
}
|
||||
}
|
||||
|
||||
// --- HELPERS ---
|
||||
|
||||
type BotContext struct {
|
||||
UserID int
|
||||
SystemPrompt string
|
||||
Availability string
|
||||
Token string
|
||||
PhoneID string
|
||||
}
|
||||
|
||||
func GetBotByPhoneID(phoneID string) (*BotContext, error) {
|
||||
var b BotContext
|
||||
err := Conn.QueryRow(`
|
||||
SELECT user_id, system_prompt, availability_hours, whatsapp_token, whatsapp_phone_id
|
||||
FROM bot_configs WHERE whatsapp_phone_id = ?`, phoneID).Scan(&b.UserID, &b.SystemPrompt, &b.Availability, &b.Token, &b.PhoneID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &b, nil
|
||||
}
|
||||
|
||||
// UpdateBotConfig saves settings from the dashboard
|
||||
func UpdateBotConfig(userID int, name, prompt, avail string) error {
|
||||
_, err := Conn.Exec(`
|
||||
UPDATE bot_configs
|
||||
SET bot_name=?, system_prompt=?, availability_hours=?
|
||||
WHERE user_id=?`, name, prompt, avail, userID)
|
||||
return err
|
||||
}
|
||||
|
||||
// GetOrCreateChatByPhone finds a chat for this phone number or creates one
|
||||
func GetOrCreateChatByPhone(phone string) int {
|
||||
// 1. Check if we already have a chat for this phone
|
||||
// (Note: You might want to add a 'phone' column to 'chats' table if you haven't yet.
|
||||
// For now, I'll cheat and put the phone in the title if it's new)
|
||||
var id int
|
||||
err := Conn.QueryRow("SELECT id FROM chats WHERE title = ?", phone).Scan(&id)
|
||||
|
||||
if err == nil {
|
||||
return id
|
||||
}
|
||||
|
||||
// 2. If not found, create one
|
||||
res, _ := Conn.Exec("INSERT INTO chats (title) VALUES (?)", phone)
|
||||
newId, _ := res.LastInsertId()
|
||||
return int(newId)
|
||||
// SaveAppointment now requires a userID to know WHO the appointment is for
|
||||
func SaveAppointment(userID int, phone, date string) error {
|
||||
_, err := Conn.Exec("INSERT INTO appointments (user_id, customer_phone, appointment_time) VALUES (?, ?, ?)", userID, phone, date)
|
||||
return err
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user