Files
grepo-remote/db.py
2026-05-02 00:08:43 +03:00

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]