diff --git a/main.go b/main.go index 7c4eb3d..a790e3e 100644 --- a/main.go +++ b/main.go @@ -29,6 +29,9 @@ var dbPath = func() string { return GetENV("DB_PATH", "guild_config.db") }() +// irgendwo global +var presenceGuildID = GetENV("DB_PATH", "") + // ===== Per-Guild Config (in-memory) ===== type GuildConfig struct { LobbyName string `json:"lobby_name"` @@ -1131,10 +1134,154 @@ func onInteractionCreate(_ string) func(s *discordgo.Session, i *discordgo.Inter Data: &discordgo.InteractionResponseData{Content: b.String(), Flags: discordgo.MessageFlagsEphemeral}, }) + case "setpresence": + // nur erlaubte Guild + if presenceGuildID == "" || i.GuildID != presenceGuildID { + _ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "❌ This command is only available on the owner guild.", + Flags: discordgo.MessageFlagsEphemeral, + }, + }) + return + } + // zusätzlich Admin-Check + if !isGuildAdmin(s, i.GuildID, i.User, i.Member) { + _ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "❌ Admins only.", + Flags: discordgo.MessageFlagsEphemeral, + }, + }) + return + } + + // Options lesen + var mode, text, status, url string + for _, o := range i.ApplicationCommandData().Options { + switch o.Name { + case "mode": + mode = strings.ToLower(o.StringValue()) + case "text": + text = o.StringValue() + case "status": + status = strings.ToLower(o.StringValue()) + case "url": + url = o.StringValue() + } + } + if text == "" { + _ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "Please provide activity text.", + Flags: discordgo.MessageFlagsEphemeral, + }, + }) + return + } + + // Mapping Mode → ActivityType + var at discordgo.ActivityType + switch mode { + case "playing": + at = discordgo.ActivityTypeGame + case "listening": + at = discordgo.ActivityTypeListening + case "watching": + at = discordgo.ActivityTypeWatching + case "streaming": + at = discordgo.ActivityTypeStreaming + case "competing": + at = discordgo.ActivityTypeCompeting + default: + at = discordgo.ActivityTypeGame + } + + // Status normalisieren + switch status { + case "online", "idle", "dnd", "invisible": + // ok + default: + status = "online" + } + + // Presence setzen + err := s.UpdateStatusComplex(discordgo.UpdateStatusData{ + Status: status, // "online" | "idle" | "dnd" | "invisible" + Activities: []*discordgo.Activity{ + { + Name: text, + Type: at, + URL: func() string { + if at == discordgo.ActivityTypeStreaming { + return url + } + return "" + }(), + }, + }, + AFK: false, + }) + if err != nil { + _ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "⚠️ Failed to update presence: " + err.Error(), + Flags: discordgo.MessageFlagsEphemeral, + }, + }) + return + } + + _ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "✅ Presence updated.", + Flags: discordgo.MessageFlagsEphemeral, + }, + }) } } } +// zusätzliches privates Kommando +var privateCommands = []*discordgo.ApplicationCommand{ + { + Name: "setpresence", + Description: "Set bot presence (owner guild only)", + DefaultMemberPermissions: &adminPerm, // nur Admins deiner Guild + Options: []*discordgo.ApplicationCommandOption{ + { + Type: discordgo.ApplicationCommandOptionString, + Name: "mode", + Description: "Activity type", + Required: true, + Choices: []*discordgo.ApplicationCommandOptionChoice{ + {Name: "playing", Value: "playing"}, + {Name: "listening", Value: "listening"}, + {Name: "watching", Value: "watching"}, + {Name: "streaming", Value: "streaming"}, + {Name: "competing", Value: "competing"}, + }, + }, + {Type: discordgo.ApplicationCommandOptionString, Name: "text", Description: "Activity text", Required: true}, + { + Type: discordgo.ApplicationCommandOptionString, Name: "status", Description: "online/idle/dnd/invisible", Required: false, + Choices: []*discordgo.ApplicationCommandOptionChoice{ + {Name: "online", Value: "online"}, + {Name: "idle", Value: "idle"}, + {Name: "dnd", Value: "dnd"}, + {Name: "invisible", Value: "invisible"}, + }, + }, + {Type: discordgo.ApplicationCommandOptionString, Name: "url", Description: "Streaming URL (only for streaming)", Required: false}, + }, + }, +} + // Handler: Commands registrieren, wenn Bot auf neuen Server kommt func onGuildCreate(s *discordgo.Session, g *discordgo.GuildCreate) { appID := s.State.User.ID @@ -1154,6 +1301,20 @@ func onGuildCreate(s *discordgo.Session, g *discordgo.GuildCreate) { log.Printf("Registriere Command %s in Guild %s", cmd.Name, g.Name) } + guildID := g.ID + // Privates Kommando nur für die Presence-Guild + if presenceGuildID != "" && guildID == presenceGuildID { + for _, pc := range privateCommands { + if c, err := s.ApplicationCommandCreate(appID, guildID, pc); err != nil { + log.Printf("private cmd %s in %s failed: %v", pc.Name, guildID, err) + } else { + // an bestehende Liste anhängen + if v, ok := createdCmds.Load(guildID); ok { + createdCmds.Store(guildID, append(v.([]*discordgo.ApplicationCommand), c)) + } + } + } + } } // ===== Commands Definition ===== @@ -1298,6 +1459,8 @@ func main() { } log.Println("Bot online. Ctrl+C zum Beenden.") + _ = s.UpdateGameStatus(0, "creating private VCs") + stop := make(chan os.Signal, 1) signal.Notify(stop, os.Interrupt, syscall.SIGTERM) <-stop