// Package betacmd is the /beta command: it shows how beta access is set up. // It exists only in the beta server (see commands.BetaCommands), is hidden // from everyone but administrators in Discord's command picker, and only the // bot's owner can actually run it (the owner is looked up from the Discord // application, so there's nothing to configure). package betacmd import ( "fmt" "sync" "velox-bot/internal/beta" "github.com/bwmarrin/discordgo" ) var ( noDM = false noPerms = int64(0) // hides the command from everyone but administrators ownerIDs sync.Map // user ID -> struct{}, filled once from the application loadOnce sync.Mutex loaded bool ) var Beta = &discordgo.ApplicationCommand{ Name: "beta", Description: "Show how beta access is set up (bot owner only)", DMPermission: &noDM, DefaultMemberPermissions: &noPerms, } // isOwner reports whether the user owns the bot's Discord application (or is // on its team). If the application can't be read, nobody is the owner. func isOwner(s *discordgo.Session, userID string) bool { if userID == "" { return false } loadOnce.Lock() if !loaded { app, err := s.Application("@me") if err == nil && app != nil { if app.Owner != nil { ownerIDs.Store(app.Owner.ID, struct{}{}) } if app.Team != nil { ownerIDs.Store(app.Team.OwnerID, struct{}{}) for _, m := range app.Team.Members { if m != nil && m.User != nil { ownerIDs.Store(m.User.ID, struct{}{}) } } } loaded = true } } loadOnce.Unlock() _, ok := ownerIDs.Load(userID) return ok } func Handler(s *discordgo.Session, i *discordgo.InteractionCreate) { var userID string if i.Member != nil && i.Member.User != nil { userID = i.Member.User.ID } var msg string st := beta.StatusOf(i.GuildID, i.Member) switch { case !isOwner(s, userID): msg = "Only the bot's owner can use this command." case !st.ServerEnabled: msg = "Beta features are off in this server." case !st.RoleConfigured: msg = "No Beta Tester role is set up, so beta features are locked for everyone." case st.HasRole: msg = fmt.Sprintf("You're a beta tester. Beta features are on in this server, and in %d other server(s) that opted in.", len(beta.Servers())) default: msg = "You don't have the Beta Tester role, so beta features are locked for you." } _ = s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ Type: discordgo.InteractionResponseChannelMessageWithSource, Data: &discordgo.InteractionResponseData{ Content: msg, Flags: discordgo.MessageFlagsEphemeral, AllowedMentions: &discordgo.MessageAllowedMentions{}, }, }) }