181 lines
6.6 KiB
Python
181 lines
6.6 KiB
Python
import sqlite3
|
|
import os
|
|
import secrets
|
|
|
|
DB_PATH = os.path.join(os.path.dirname(__file__), 'grepo.db')
|
|
|
|
|
|
def get_db():
|
|
conn = sqlite3.connect(DB_PATH)
|
|
conn.row_factory = sqlite3.Row
|
|
return conn
|
|
|
|
|
|
def init_db():
|
|
conn = get_db()
|
|
c = conn.cursor()
|
|
|
|
# Commands queue — sent from dashboard, consumed by Tampermonkey
|
|
c.execute('''
|
|
CREATE TABLE IF NOT EXISTS commands (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
town_id TEXT NOT NULL,
|
|
town_name TEXT,
|
|
type TEXT NOT NULL, -- 'build' | 'recruit'
|
|
payload TEXT NOT NULL, -- JSON string
|
|
status TEXT NOT NULL DEFAULT 'pending', -- pending | executing | done | failed
|
|
result_msg TEXT,
|
|
position INTEGER, -- manual sort order for build queue (lower = first)
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)
|
|
''')
|
|
|
|
# Town state — pushed by Tampermonkey every poll cycle
|
|
c.execute('''
|
|
CREATE TABLE IF NOT EXISTS town_state (
|
|
town_id TEXT PRIMARY KEY,
|
|
town_name TEXT,
|
|
player TEXT,
|
|
player_id TEXT,
|
|
alliance_id TEXT,
|
|
world_id TEXT,
|
|
x REAL,
|
|
y REAL,
|
|
sea INTEGER,
|
|
data TEXT NOT NULL, -- full JSON snapshot
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)
|
|
''')
|
|
|
|
# Key-value store — generic flags (e.g. captcha_active)
|
|
c.execute('''
|
|
CREATE TABLE IF NOT EXISTS kv_store (
|
|
key TEXT PRIMARY KEY,
|
|
value TEXT,
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)
|
|
''')
|
|
|
|
# Farm settings — per-player auto-farm configuration
|
|
c.execute('''
|
|
CREATE TABLE IF NOT EXISTS farm_settings (
|
|
player_id TEXT PRIMARY KEY,
|
|
enabled INTEGER NOT NULL DEFAULT 0,
|
|
bandit_camp_enabled INTEGER NOT NULL DEFAULT 0,
|
|
loot_option INTEGER NOT NULL DEFAULT 1, -- 1=5min, 2=20min, 3=90min, 4=4h
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)
|
|
''')
|
|
|
|
# Bot settings — per-player config for bootcamp & rural-trade auto-loops
|
|
c.execute('''
|
|
CREATE TABLE IF NOT EXISTS bot_settings (
|
|
player_id TEXT PRIMARY KEY,
|
|
bootcamp_enabled INTEGER NOT NULL DEFAULT 0,
|
|
bootcamp_use_def INTEGER NOT NULL DEFAULT 0,
|
|
rural_trade_enabled INTEGER NOT NULL DEFAULT 0,
|
|
rural_trade_ratio INTEGER NOT NULL DEFAULT 3, -- 1=0.25 2=0.5 3=0.75 4=1.0 5=1.25
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)
|
|
''')
|
|
|
|
# Bot logs — ring buffer of last 50 entries per player per feature
|
|
c.execute('''
|
|
CREATE TABLE IF NOT EXISTS bot_logs (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
player_id TEXT NOT NULL,
|
|
feature TEXT NOT NULL, -- 'bootcamp' | 'rural_trade'
|
|
message TEXT NOT NULL,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)
|
|
''')
|
|
c.execute('CREATE INDEX IF NOT EXISTS idx_bot_logs_player_feature ON bot_logs(player_id, feature)')
|
|
|
|
# Blueprints - assigns a blueprint to a specific town
|
|
c.execute('''
|
|
CREATE TABLE IF NOT EXISTS town_blueprints (
|
|
town_id TEXT PRIMARY KEY,
|
|
blueprint_name TEXT NOT NULL,
|
|
is_active INTEGER NOT NULL DEFAULT 1,
|
|
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)
|
|
''')
|
|
|
|
# Migration: add new columns if upgrading an existing database
|
|
for _col in [
|
|
'ALTER TABLE town_state ADD COLUMN player_id TEXT',
|
|
'ALTER TABLE town_state ADD COLUMN alliance_id TEXT',
|
|
'ALTER TABLE town_state ADD COLUMN x REAL',
|
|
'ALTER TABLE town_state ADD COLUMN y REAL',
|
|
'ALTER TABLE town_state ADD COLUMN sea INTEGER',
|
|
'ALTER TABLE commands ADD COLUMN player_id TEXT',
|
|
'ALTER TABLE commands ADD COLUMN position INTEGER',
|
|
'ALTER TABLE farm_settings ADD COLUMN bandit_camp_enabled INTEGER NOT NULL DEFAULT 0',
|
|
"ALTER TABLE clan_members ADD COLUMN features TEXT NOT NULL DEFAULT 'farm,admin'",
|
|
'ALTER TABLE users ADD COLUMN clan_id INTEGER REFERENCES clans(id)',
|
|
]:
|
|
try:
|
|
c.execute(_col)
|
|
except Exception:
|
|
pass # column already exists
|
|
|
|
# Back-fill position for existing rows that have NULL position
|
|
try:
|
|
c.execute('UPDATE commands SET position = id WHERE position IS NULL')
|
|
except Exception:
|
|
pass
|
|
|
|
# Users — website admin accounts
|
|
c.execute('''
|
|
CREATE TABLE IF NOT EXISTS users (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
username TEXT NOT NULL UNIQUE,
|
|
password_hash TEXT NOT NULL,
|
|
clan_id INTEGER REFERENCES clans(id),
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)
|
|
''')
|
|
|
|
# Clans — groups owned by a user, identified by a unique clan_key
|
|
c.execute('''
|
|
CREATE TABLE IF NOT EXISTS clans (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
owner_id INTEGER NOT NULL REFERENCES users(id),
|
|
name TEXT NOT NULL,
|
|
clan_key TEXT NOT NULL UNIQUE,
|
|
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
)
|
|
''')
|
|
|
|
# Clan members — links Grepolis player_ids to a clan
|
|
c.execute('''
|
|
CREATE TABLE IF NOT EXISTS clan_members (
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
clan_id INTEGER NOT NULL REFERENCES clans(id),
|
|
player_id TEXT NOT NULL,
|
|
player_name TEXT,
|
|
features TEXT NOT NULL DEFAULT 'farm,admin',
|
|
joined_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
UNIQUE(clan_id, player_id)
|
|
)
|
|
''')
|
|
|
|
# Migration: Auto-assign existing users to their clan_id if they are the owner
|
|
try:
|
|
c.execute('''
|
|
UPDATE users
|
|
SET clan_id = (SELECT id FROM clans WHERE owner_id = users.id)
|
|
WHERE clan_id IS NULL AND EXISTS (SELECT 1 FROM clans WHERE owner_id = users.id)
|
|
''')
|
|
except Exception:
|
|
pass
|
|
|
|
conn.commit()
|
|
conn.close()
|
|
|
|
|
|
def generate_clan_key():
|
|
"""Generate a short, unique, human-readable clan key."""
|
|
return secrets.token_urlsafe(8).upper()[:10]
|