main.go aktualisiert
Some checks failed
release-tag / release-image (push) Failing after 52s

This commit is contained in:
2025-08-10 19:44:42 +00:00
parent 04025565ff
commit 396ee0398d

203
main.go
View File

@@ -1,7 +1,7 @@
package main
import (
"encoding/json"
"database/sql"
"fmt"
"log"
"os"
@@ -11,6 +11,7 @@ import (
"time"
"github.com/bwmarrin/discordgo"
_ "github.com/mattn/go-sqlite3" // SQLite3-Treiber importieren
)
// ===== Defaults / Names (pro Guild per Commands konfigurierbar) =====
@@ -20,53 +21,21 @@ const (
defaultCategory = "Private Räume"
)
// Pfad zur SQLite-Datenbank
var dbPath = func() string {
if v := os.Getenv("DB_PATH"); v != "" {
return v
}
return "guild_config.db"
}()
// Pfad zur Persistenz-Datei (überschreibbar via CONFIG_PATH)
var configPath = func() string {
/*var configPath = func() string {
if v := os.Getenv("CONFIG_PATH"); v != "" {
return v
}
return "guild_config.json"
}()
// Persistenz der Guild-Konfiguration
func loadGuildCfgs() error {
f, err := os.Open(configPath)
if err != nil {
return err
}
defer f.Close()
var m map[string]*GuildConfig
if err := json.NewDecoder(f).Decode(&m); err != nil {
return err
}
cfgMu.Lock()
for k, v := range m {
guildCfgs[k] = v
}
cfgMu.Unlock()
return nil
}
func saveGuildCfgs() error {
tmp := configPath + ".tmp"
f, err := os.Create(tmp)
if err != nil {
return err
}
enc := json.NewEncoder(f)
enc.SetIndent("", " ")
cfgMu.RLock()
err = enc.Encode(guildCfgs)
cfgMu.RUnlock()
_ = f.Close()
if err != nil {
return err
}
return os.Rename(tmp, configPath)
}
}()*/
// ===== Per-Guild Config (in-memory) =====
type GuildConfig struct {
@@ -75,29 +44,121 @@ type GuildConfig struct {
TimeoutMin int `json:"timeout_min"`
}
var db *sql.DB
// Initialize DB
func initDB() {
var err error
db, err = sql.Open("sqlite3", dbPath)
if err != nil {
log.Fatalf("Datenbank-Fehler: %v", err)
}
// Tabelle erstellen, falls sie noch nicht existiert
createTableSQL := `CREATE TABLE IF NOT EXISTS guild_config (
guild_id TEXT PRIMARY KEY,
lobby_name TEXT,
category_name TEXT,
timeout_min INTEGER
);`
_, err = db.Exec(createTableSQL)
if err != nil {
log.Fatalf("Fehler beim Erstellen der Tabelle: %v", err)
}
}
// Close DB connection
func closeDB() {
if err := db.Close(); err != nil {
log.Fatalf("Fehler beim Schließen der DB: %v", err)
}
}
// Laden der Guild-Konfiguration aus der Datenbank
func loadGuildCfgs() error {
rows, err := db.Query("SELECT guild_id, lobby_name, category_name, timeout_min FROM guild_config")
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
var guildID, lobbyName, categoryName string
var timeoutMin int
if err := rows.Scan(&guildID, &lobbyName, &categoryName, &timeoutMin); err != nil {
return err
}
guildCfgs[guildID] = &GuildConfig{
LobbyName: lobbyName,
CategoryName: categoryName,
TimeoutMin: timeoutMin,
}
}
return nil
}
// Speichern der Guild-Konfiguration in die Datenbank
func saveGuildCfgs() error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
for guildID, cfg := range guildCfgs {
// UPDATE oder INSERT, je nachdem, ob es bereits eine Konfiguration gibt
_, err := tx.Exec(`
INSERT INTO guild_config (guild_id, lobby_name, category_name, timeout_min)
VALUES (?, ?, ?, ?)
ON CONFLICT(guild_id)
DO UPDATE SET
lobby_name = excluded.lobby_name,
category_name = excluded.category_name,
timeout_min = excluded.timeout_min
`, guildID, cfg.LobbyName, cfg.CategoryName, cfg.TimeoutMin)
if err != nil {
return err
}
}
// Transaktion abschließen
return tx.Commit()
}
var (
cfgMu sync.RWMutex
guildCfgs = map[string]*GuildConfig{}
createdCmds = map[string][]*discordgo.ApplicationCommand{} // guildID -> cmds
registerOnce sync.Once
cfgMu sync.Mutex
guildCfgs = map[string]*GuildConfig{}
createdCmds = map[string][]*discordgo.ApplicationCommand{} // guildID -> cmds
)
func getCfg(guildID string) *GuildConfig {
cfgMu.RLock()
cfgMu.Lock()
c, ok := guildCfgs[guildID]
cfgMu.RUnlock()
cfgMu.Unlock()
if ok {
return c
}
cfgMu.Lock()
defer cfgMu.Unlock()
c = &GuildConfig{
LobbyName: defaultLobbyName,
CategoryName: defaultCategory,
TimeoutMin: envTimeoutDefault(60),
// Falls nicht vorhanden, Daten aus DB laden
var guildCfg GuildConfig
err := db.QueryRow("SELECT lobby_name, category_name, timeout_min FROM guild_config WHERE guild_id = ?", guildID).Scan(&guildCfg.LobbyName, &guildCfg.CategoryName, &guildCfg.TimeoutMin)
if err != nil {
if err != sql.ErrNoRows {
log.Printf("Fehler beim Abrufen der Guild-Konfiguration: %v", err)
}
// Fallback-Werte, falls die Guild nicht in der DB existiert
guildCfg = GuildConfig{
LobbyName: defaultLobbyName,
CategoryName: defaultCategory,
TimeoutMin: envTimeoutDefault(1),
}
}
guildCfgs[guildID] = c
return c
cfgMu.Lock()
guildCfgs[guildID] = &guildCfg
cfgMu.Unlock()
return &guildCfg
}
func envTimeoutDefault(def int) int {
@@ -541,8 +602,8 @@ func onInteractionCreate(_ string) func(s *discordgo.Session, i *discordgo.Inter
})
case "settimeout":
// Admin-Check zuerst
if !isGuildAdmin(s, guildID, i.User, i.Member) {
log.Println("User is not an admin")
_ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
Data: &discordgo.InteractionResponseData{
@@ -553,7 +614,6 @@ func onInteractionCreate(_ string) func(s *discordgo.Session, i *discordgo.Inter
return
}
// minutes lesen
minutes := int64(getCfg(guildID).TimeoutMin)
for _, o := range data.Options {
if o.Name == "minutes" {
@@ -564,9 +624,12 @@ func onInteractionCreate(_ string) func(s *discordgo.Session, i *discordgo.Inter
minutes = 1
}
log.Printf("Setting timeout for %d minutes", minutes)
// speichern
cfgMu.Lock()
getCfg(guildID).TimeoutMin = int(minutes)
log.Println("1-0815")
cfgMu.Unlock()
if err := saveGuildCfgs(); err != nil {
log.Printf("saveGuildCfgs failed: %v", err)
@@ -580,6 +643,8 @@ func onInteractionCreate(_ string) func(s *discordgo.Session, i *discordgo.Inter
return
}
log.Println("2-0815")
// Antwort <= 3s
_ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{
Type: discordgo.InteractionResponseChannelMessageWithSource,
@@ -698,6 +763,7 @@ func onGuildCreate(s *discordgo.Session, g *discordgo.GuildCreate) {
cfgMu.Lock()
createdCmds[g.ID] = append(createdCmds[g.ID], c)
cfgMu.Unlock()
log.Printf("Command-Registrierung in %s", g.Name)
}
}
@@ -753,7 +819,7 @@ var (
}
)
func registerCommandsForGuild(s *discordgo.Session, guildID string) {
/*func registerCommandsForGuild(s *discordgo.Session, guildID string) {
appID := s.State.User.ID
cmds, err := s.ApplicationCommandBulkOverwrite(appID, guildID, slashCommands)
if err != nil {
@@ -763,18 +829,21 @@ func registerCommandsForGuild(s *discordgo.Session, guildID string) {
cfgMu.Lock()
createdCmds[guildID] = cmds
cfgMu.Unlock()
}
//fmt.Println(createdCmds)
}*/
// ===== main: Multi-Guild, pro Guild registrieren =====
func main() {
initDB()
token := os.Getenv("DISCORD_TOKEN")
token = "MTQwMzg1MTM5NDQ1MjI5MTU4NA.GVi04l.qjraLIbFdi_N49UcSUv_BqK89ihb6xXY648J7A"
if token == "" {
log.Fatal("Bitte setze DISCORD_TOKEN")
}
// Persistente Konfiguration laden (optional)
if err := loadGuildCfgs(); err != nil {
log.Printf("Hinweis: Konnte %s nicht laden (%v). Starte mit Defaults.", configPath, err)
log.Printf("Hinweis: Konnte %s nicht laden (%v). Starte mit Defaults.", dbPath, err)
}
s, err := discordgo.New("Bot " + token)
@@ -786,16 +855,16 @@ func main() {
s.AddHandler(onVoiceStateUpdate)
s.AddHandler(onGuildCreate)
s.AddHandler(func(s *discordgo.Session, r *discordgo.Ready) {
/*s.AddHandler(func(s *discordgo.Session, r *discordgo.Ready) {
for _, g := range s.State.Guilds {
registerCommandsForGuild(s, g.ID)
}
})
s.AddHandler(func(s *discordgo.Session, g *discordgo.GuildCreate) {
registerCommandsForGuild(s, g.ID)
})
})*/
s.AddHandler(onInteractionCreate(""))
s.AddHandler(func(s *discordgo.Session, r *discordgo.Ready) {
/*s.AddHandler(func(s *discordgo.Session, r *discordgo.Ready) {
log.Printf("Eingeloggt als %s", r.User.Username)
registerOnce.Do(func() {
appID := s.State.User.ID
@@ -812,7 +881,7 @@ func main() {
}
log.Printf("Defaults → Lobby: %q | Kategorie: %q | Timeout: %d min", defaultLobbyName, defaultCategory, envTimeoutDefault(60))
})
})
})*/
if err := s.Open(); err != nil {
log.Fatalf("Gateway-Start fehlgeschlagen: %v", err)
@@ -829,6 +898,8 @@ func main() {
for _, c := range cmds {
if delErr := s.ApplicationCommandDelete(appID, guildID, c.ID); delErr != nil {
log.Printf("Cmd-Delete (%s/%s) fehlgeschlagen: %v", guildID, c.Name, delErr)
} else {
log.Printf("Cmd-Delete (%s/%s) ok", guildID, c.Name)
}
}
}