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
123 lines
3.0 KiB
Go
123 lines
3.0 KiB
Go
package channelserver
|
|
|
|
import (
|
|
dbutil "erupe-ce/common/db"
|
|
)
|
|
|
|
// MailRepository centralizes all database access for the mail table.
|
|
type MailRepository struct {
|
|
db *dbutil.DB
|
|
}
|
|
|
|
// NewMailRepository creates a new MailRepository.
|
|
func NewMailRepository(db *dbutil.DB) *MailRepository {
|
|
return &MailRepository{db: db}
|
|
}
|
|
|
|
const mailInsertQuery = `
|
|
INSERT INTO mail (sender_id, recipient_id, subject, body, attached_item, attached_item_amount, is_guild_invite, is_sys_message)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
`
|
|
|
|
// SendMail inserts a new mail row.
|
|
func (r *MailRepository) SendMail(senderID, recipientID uint32, subject, body string, itemID, itemAmount uint16, isGuildInvite, isSystemMessage bool) error {
|
|
_, err := r.db.Exec(mailInsertQuery, senderID, recipientID, subject, body, itemID, itemAmount, isGuildInvite, isSystemMessage)
|
|
return err
|
|
}
|
|
|
|
// GetListForCharacter loads all non-deleted mail for a character (max 32).
|
|
func (r *MailRepository) GetListForCharacter(charID uint32) ([]Mail, error) {
|
|
rows, err := r.db.Queryx(`
|
|
SELECT
|
|
m.id,
|
|
m.sender_id,
|
|
m.recipient_id,
|
|
m.subject,
|
|
m.read,
|
|
m.attached_item_received,
|
|
m.attached_item,
|
|
m.attached_item_amount,
|
|
m.created_at,
|
|
m.is_guild_invite,
|
|
m.is_sys_message,
|
|
m.deleted,
|
|
m.locked,
|
|
c.name as sender_name
|
|
FROM mail m
|
|
JOIN characters c ON c.id = m.sender_id
|
|
WHERE recipient_id = $1 AND m.deleted = false
|
|
ORDER BY m.created_at DESC, id DESC
|
|
LIMIT 32
|
|
`, charID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer func() { _ = rows.Close() }()
|
|
|
|
var allMail []Mail
|
|
for rows.Next() {
|
|
var mail Mail
|
|
if err := rows.StructScan(&mail); err != nil {
|
|
return nil, err
|
|
}
|
|
allMail = append(allMail, mail)
|
|
}
|
|
return allMail, nil
|
|
}
|
|
|
|
// GetByID loads a single mail by ID.
|
|
func (r *MailRepository) GetByID(id int) (*Mail, error) {
|
|
row := r.db.QueryRowx(`
|
|
SELECT
|
|
m.id,
|
|
m.sender_id,
|
|
m.recipient_id,
|
|
m.subject,
|
|
m.read,
|
|
m.body,
|
|
m.attached_item_received,
|
|
m.attached_item,
|
|
m.attached_item_amount,
|
|
m.created_at,
|
|
m.is_guild_invite,
|
|
m.is_sys_message,
|
|
m.deleted,
|
|
m.locked,
|
|
c.name as sender_name
|
|
FROM mail m
|
|
JOIN characters c ON c.id = m.sender_id
|
|
WHERE m.id = $1
|
|
LIMIT 1
|
|
`, id)
|
|
|
|
mail := &Mail{}
|
|
if err := row.StructScan(mail); err != nil {
|
|
return nil, err
|
|
}
|
|
return mail, nil
|
|
}
|
|
|
|
// MarkRead marks a mail as read.
|
|
func (r *MailRepository) MarkRead(id int) error {
|
|
_, err := r.db.Exec(`UPDATE mail SET read = true WHERE id = $1`, id)
|
|
return err
|
|
}
|
|
|
|
// MarkDeleted marks a mail as deleted.
|
|
func (r *MailRepository) MarkDeleted(id int) error {
|
|
_, err := r.db.Exec(`UPDATE mail SET deleted = true WHERE id = $1`, id)
|
|
return err
|
|
}
|
|
|
|
// SetLocked sets the locked state of a mail.
|
|
func (r *MailRepository) SetLocked(id int, locked bool) error {
|
|
_, err := r.db.Exec(`UPDATE mail SET locked = $1 WHERE id = $2`, locked, id)
|
|
return err
|
|
}
|
|
|
|
// MarkItemReceived marks a mail's attached item as received.
|
|
func (r *MailRepository) MarkItemReceived(id int) error {
|
|
_, err := r.db.Exec(`UPDATE mail SET attached_item_received = TRUE WHERE id = $1`, id)
|
|
return err
|
|
}
|