mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-21 23:22:34 +01:00
Add zero-dependency SQLite mode so users can run Erupe without
PostgreSQL. A transparent db.DB wrapper auto-translates PostgreSQL
SQL ($N placeholders, now(), ::casts, ILIKE, public. prefix,
TRUNCATE) for SQLite at runtime — all 28 repo files use the wrapper
with no per-query changes needed.
Setup wizard gains two new steps: quest file detection with download
link, and gameplay presets (solo/small/community/rebalanced). The API
server gets a /dashboard endpoint with auto-refreshing stats.
CI release workflow now builds and pushes Docker images to GHCR
alongside binary artifacts on tag push.
Key changes:
- common/db: DB/Tx wrapper with 6 SQL translation rules
- server/migrations/sqlite: full SQLite schema (0001-0005)
- config: Database.Driver field ("postgres" or "sqlite")
- main.go: SQLite connection with WAL mode, single writer
- server/setup: quest check + preset selection steps
- server/api: /dashboard with live stats
- .github/workflows: Docker in release, deduplicate docker.yml
80 lines
2.7 KiB
Go
80 lines
2.7 KiB
Go
package channelserver
|
|
|
|
import (
|
|
dbutil "erupe-ce/common/db"
|
|
)
|
|
|
|
// DistributionRepository centralizes all database access for the distribution,
|
|
// distribution_items, and distributions_accepted tables.
|
|
type DistributionRepository struct {
|
|
db *dbutil.DB
|
|
}
|
|
|
|
// NewDistributionRepository creates a new DistributionRepository.
|
|
func NewDistributionRepository(db *dbutil.DB) *DistributionRepository {
|
|
return &DistributionRepository{db: db}
|
|
}
|
|
|
|
// List returns all distributions matching the given character and type.
|
|
func (r *DistributionRepository) List(charID uint32, distType uint8) ([]Distribution, error) {
|
|
rows, err := r.db.Queryx(`
|
|
SELECT d.id, event_name, description, COALESCE(rights, 0) AS rights, COALESCE(selection, false) AS selection, times_acceptable,
|
|
COALESCE(min_hr, -1) AS min_hr, COALESCE(max_hr, -1) AS max_hr,
|
|
COALESCE(min_sr, -1) AS min_sr, COALESCE(max_sr, -1) AS max_sr,
|
|
COALESCE(min_gr, -1) AS min_gr, COALESCE(max_gr, -1) AS max_gr,
|
|
(
|
|
SELECT count(*) FROM distributions_accepted da
|
|
WHERE d.id = da.distribution_id AND da.character_id = $1
|
|
) AS times_accepted,
|
|
COALESCE(deadline, TO_TIMESTAMP(0)) AS deadline
|
|
FROM distribution d
|
|
WHERE character_id = $1 AND type = $2 OR character_id IS NULL AND type = $2 ORDER BY id DESC
|
|
`, charID, distType)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer func() { _ = rows.Close() }()
|
|
|
|
var dists []Distribution
|
|
for rows.Next() {
|
|
var d Distribution
|
|
if err := rows.StructScan(&d); err != nil {
|
|
continue
|
|
}
|
|
dists = append(dists, d)
|
|
}
|
|
return dists, nil
|
|
}
|
|
|
|
// GetItems returns all items for a given distribution.
|
|
func (r *DistributionRepository) GetItems(distributionID uint32) ([]DistributionItem, error) {
|
|
rows, err := r.db.Queryx(`SELECT id, item_type, COALESCE(item_id, 0) AS item_id, COALESCE(quantity, 0) AS quantity FROM distribution_items WHERE distribution_id=$1`, distributionID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer func() { _ = rows.Close() }()
|
|
|
|
var items []DistributionItem
|
|
for rows.Next() {
|
|
var item DistributionItem
|
|
if err := rows.StructScan(&item); err != nil {
|
|
continue
|
|
}
|
|
items = append(items, item)
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
// RecordAccepted records that a character has accepted a distribution.
|
|
func (r *DistributionRepository) RecordAccepted(distributionID, charID uint32) error {
|
|
_, err := r.db.Exec(`INSERT INTO public.distributions_accepted VALUES ($1, $2)`, distributionID, charID)
|
|
return err
|
|
}
|
|
|
|
// GetDescription returns the description text for a distribution.
|
|
func (r *DistributionRepository) GetDescription(distributionID uint32) (string, error) {
|
|
var desc string
|
|
err := r.db.QueryRow("SELECT description FROM distribution WHERE id = $1", distributionID).Scan(&desc)
|
|
return desc, err
|
|
}
|