refactor: modularize chat backend, update docs for .m4s segments

This commit is contained in:
zwitschi committed 2026-08-07 13:16:44 +02:00
1 parent 46e878bef6
commit b3a10ba3ef
24 files changed
+3771 -2781

No files matched your search

+82
View File
@@ -0,0 +1,82 @@
package db
import (
"context"
"log"
"strings"
"time"
"gorm.io/driver/postgres"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// DBClient wraps gorm.DB for testability.
type DBClient struct {
*gorm.DB
}
// InitDB initializes configured SQL storage for chat, moderation, and admin metadata (ADR-006).
// Returns the client and the driver name.
func InitDB(databaseURL string) (*DBClient, string, error) {
var (
gormDB *gorm.DB
err error
driver = "sqlite"
)
switch {
case databaseURL == "":
gormDB, err = gorm.Open(sqlite.Open("chat.db"), &gorm.Config{})
case strings.HasPrefix(databaseURL, "sqlite://"):
sqlitePath := strings.TrimPrefix(databaseURL, "sqlite://")
if sqlitePath == "" {
sqlitePath = "chat.db"
}
gormDB, err = gorm.Open(sqlite.Open(sqlitePath), &gorm.Config{})
case strings.HasPrefix(databaseURL, "postgres://") || strings.HasPrefix(databaseURL, "postgresql://"):
driver = "postgres"
gormDB, err = gorm.Open(postgres.Open(databaseURL), &gorm.Config{})
default:
log.Fatalf("Unsupported DATABASE_URL scheme: %s", databaseURL)
}
if err != nil {
return nil, driver, err
}
gormDB.AutoMigrate(&Message{}, &ModerationLog{}, &Media{}, &ScheduleOverride{})
log.Printf("%s database initialized (chat history, moderation log, media metadata)", strings.Title(driver))
return &DBClient{DB: gormDB}, driver, nil
}
// RedisClient wraps the Redis client for testability.
// Interface defined for mocking in tests.
type RedisClient interface {
Ping(ctx context.Context) error
Set(ctx context.Context, key string, value interface{}, expiration time.Duration) error
Get(ctx context.Context, key string) (string, error)
Del(ctx context.Context, keys ...string) error
Incr(ctx context.Context, key string) (int64, error)
Decr(ctx context.Context, key string) (int64, error)
Expire(ctx context.Context, key string, expiration time.Duration) error
Exists(ctx context.Context, keys ...string) (int64, error)
Publish(ctx context.Context, channel string, message interface{}) error
PSubscribe(ctx context.Context, channels ...string) PubSub
Scan(ctx context.Context, cursor uint64, match string, count int64) ([]string, uint64, error)
Info(ctx context.Context, sections ...string) (string, error)
Close() error
}
// PubSub wraps Redis pub/sub subscription.
type PubSub interface {
ReceiveMessage(ctx context.Context) (*PubSubMessage, error)
Close() error
}
// PubSubMessage represents a received pub/sub message.
type PubSubMessage struct {
Channel string
Payload string
}