eq2go/internal/chat/database.go

200 lines
5.6 KiB
Go

package chat
import (
"context"
"fmt"
"eq2emu/internal/database"
)
// DatabaseChannelManager implements ChannelDatabase interface using the correct database wrapper
type DatabaseChannelManager struct {
db *database.DB
}
// NewDatabaseChannelManager creates a new database channel manager using the correct wrapper
func NewDatabaseChannelManager(db *database.DB) *DatabaseChannelManager {
return &DatabaseChannelManager{
db: db,
}
}
// LoadWorldChannels retrieves all persistent world channels from database
func (dcm *DatabaseChannelManager) LoadWorldChannels(ctx context.Context) ([]ChatChannelData, error) {
query := "SELECT `name`, `password`, `level_restriction`, `classes`, `races` FROM `channels`"
var channels []ChatChannelData
err := dcm.db.Query(query, func(row *database.Row) error {
var channel ChatChannelData
channel.Name = row.Text(0)
if !row.IsNull(1) {
channel.Password = row.Text(1)
}
channel.LevelRestriction = int32(row.Int64(2))
channel.ClassRestriction = int32(row.Int64(3))
channel.RaceRestriction = int32(row.Int64(4))
channels = append(channels, channel)
return nil
})
if err != nil {
return nil, fmt.Errorf("failed to query channels: %w", err)
}
return channels, nil
}
// SaveChannel persists a channel to database (world channels only)
func (dcm *DatabaseChannelManager) SaveChannel(ctx context.Context, channel ChatChannelData) error {
// Insert or update channel
query := `
INSERT OR REPLACE INTO channels
(name, password, level_restriction, classes, races)
VALUES (?, ?, ?, ?, ?)`
var password *string
if channel.Password != "" {
password = &channel.Password
}
err := dcm.db.Exec(query,
channel.Name,
password,
channel.LevelRestriction,
channel.ClassRestriction,
channel.RaceRestriction,
)
if err != nil {
return fmt.Errorf("failed to save channel %s: %w", channel.Name, err)
}
return nil
}
// DeleteChannel removes a channel from database
func (dcm *DatabaseChannelManager) DeleteChannel(ctx context.Context, channelName string) error {
query := "DELETE FROM channels WHERE name = ?"
err := dcm.db.Exec(query, channelName)
if err != nil {
return fmt.Errorf("failed to delete channel %s: %w", channelName, err)
}
return nil
}
// EnsureChannelsTable creates the channels table if it doesn't exist
func (dcm *DatabaseChannelManager) EnsureChannelsTable(ctx context.Context) error {
query := `
CREATE TABLE IF NOT EXISTS channels (
name TEXT PRIMARY KEY,
password TEXT,
level_restriction INTEGER NOT NULL DEFAULT 0,
classes INTEGER NOT NULL DEFAULT 0,
races INTEGER NOT NULL DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
)`
err := dcm.db.Exec(query)
if err != nil {
return fmt.Errorf("failed to create channels table: %w", err)
}
return nil
}
// GetChannelCount returns the total number of channels in the database
func (dcm *DatabaseChannelManager) GetChannelCount(ctx context.Context) (int, error) {
query := "SELECT COUNT(*) FROM channels"
row, err := dcm.db.QueryRow(query)
if err != nil {
return 0, fmt.Errorf("failed to query channel count: %w", err)
}
if row == nil {
return 0, nil
}
defer row.Close()
count := row.Int(0)
return count, nil
}
// GetChannelByName retrieves a specific channel by name
func (dcm *DatabaseChannelManager) GetChannelByName(ctx context.Context, channelName string) (*ChatChannelData, error) {
query := "SELECT `name`, `password`, `level_restriction`, `classes`, `races` FROM `channels` WHERE `name` = ?"
row, err := dcm.db.QueryRow(query, channelName)
if err != nil {
return nil, fmt.Errorf("failed to query channel %s: %w", channelName, err)
}
if row == nil {
return nil, fmt.Errorf("channel %s not found", channelName)
}
defer row.Close()
var channel ChatChannelData
channel.Name = row.Text(0)
if !row.IsNull(1) {
channel.Password = row.Text(1)
}
channel.LevelRestriction = int32(row.Int64(2))
channel.ClassRestriction = int32(row.Int64(3))
channel.RaceRestriction = int32(row.Int64(4))
return &channel, nil
}
// ListChannelNames returns a list of all channel names in the database
func (dcm *DatabaseChannelManager) ListChannelNames(ctx context.Context) ([]string, error) {
query := "SELECT name FROM channels ORDER BY name"
var names []string
err := dcm.db.Query(query, func(row *database.Row) error {
name := row.Text(0)
names = append(names, name)
return nil
})
if err != nil {
return nil, fmt.Errorf("failed to query channel names: %w", err)
}
return names, nil
}
// UpdateChannelPassword updates just the password for a channel
func (dcm *DatabaseChannelManager) UpdateChannelPassword(ctx context.Context, channelName, password string) error {
query := "UPDATE channels SET password = ?, updated_at = CURRENT_TIMESTAMP WHERE name = ?"
var passwordParam *string
if password != "" {
passwordParam = &password
}
err := dcm.db.Exec(query, passwordParam, channelName)
if err != nil {
return fmt.Errorf("failed to update password for channel %s: %w", channelName, err)
}
return nil
}
// UpdateChannelRestrictions updates the level, race, and class restrictions for a channel
func (dcm *DatabaseChannelManager) UpdateChannelRestrictions(ctx context.Context, channelName string, levelRestriction, classRestriction, raceRestriction int32) error {
query := "UPDATE channels SET level_restriction = ?, classes = ?, races = ?, updated_at = CURRENT_TIMESTAMP WHERE name = ?"
err := dcm.db.Exec(query, levelRestriction, classRestriction, raceRestriction, channelName)
if err != nil {
return fmt.Errorf("failed to update restrictions for channel %s: %w", channelName, err)
}
return nil
}