package interactions import ( "crypto/ed25519" "fmt" "log" "net/http" "github.com/gofiber/fiber/v3" "git.sapphic.engineer/roleypoly/v4/discord" "git.sapphic.engineer/roleypoly/v4/types" "git.sapphic.engineer/roleypoly/v4/utils" ) type Interactions struct { PublicKey ed25519.PublicKey PublicBaseURL string Guilds *discord.GuildService Router *InteractionRouter // if interactions are able to be used OK bool commandsMap []InteractionCommand commandsMentions map[string]string } func NewInteractions(publicKey string, publicBaseURL string, guildsService *discord.GuildService) *Interactions { return &Interactions{ PublicKey: ed25519.PublicKey(publicKey), PublicBaseURL: publicBaseURL, Guilds: guildsService, Router: NewInteractionRouter(), OK: len(publicKey) != 0, } } func (i *Interactions) Routes(r fiber.Router) { r.Post("/", i.PostHandler) i.Router.Add("hello-world", i.CmdHelloWorld) } func (i *Interactions) PostHandler(c fiber.Ctx) error { if !i.OK { return types.NewAPIError(http.StatusUnauthorized, "interactions not enabled").Send(c) } signature := c.Get("X-Signature-Ed25519") timestamp := c.Get("X-Signature-Timestamp") err := i.Verify(signature, timestamp, c.BodyRaw()) if err != nil { log.Println("interactions: verification failed, ", err) return types.NewAPIError(http.StatusUnauthorized, "verification failed").Send(c) } ix := Interaction{} err = c.Bind().JSON(&ix) if err != nil { log.Println("interactions: json body parse failed, ", err) return types.NewAPIError(http.StatusBadRequest, "bad request").Send(c) } if ix.Type == TypePing { return c.JSON(InteractionResponse{ Type: ResponsePong, }) } if ix.Type == TypeApplicationCommand { return i.Router.Handle(c, ix) } return types.NewAPIError(http.StatusNotImplemented, "not implemented").Send(c) } func (i *Interactions) CommandsMap() map[string]string { if i.commandsMentions != nil { return i.commandsMentions } dc := i.Guilds.Client() req := discord.NewRequest("GET", utils.J("applications", i.Guilds.Client().GetClientID(), "commands")) dc.BotAuth(req) resp, err := dc.Do(req) if err != nil { log.Println("interactions: commands map fetch failed") return nil } i.commandsMap = []InteractionCommand{} err = discord.OutputResponse(resp, &i.commandsMap) if err != nil { log.Println("interactions: commands map parse failed") return nil } i.commandsMentions = map[string]string{} for _, command := range i.commandsMap { i.commandsMentions[command.Name] = fmt.Sprintf("", command.ID, command.Name) } return i.commandsMentions }