154 lines
3.2 KiB
Go
154 lines
3.2 KiB
Go
package public
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"net/http"
|
|
"time"
|
|
|
|
"velox-bot/internal/commands/fun/shared"
|
|
|
|
"github.com/bwmarrin/discordgo"
|
|
)
|
|
|
|
var Joke = &discordgo.ApplicationCommand{
|
|
Name: "joke",
|
|
Description: "Get a random joke",
|
|
Contexts: &[]discordgo.InteractionContextType{
|
|
discordgo.InteractionContextGuild,
|
|
discordgo.InteractionContextBotDM,
|
|
discordgo.InteractionContextPrivateChannel,
|
|
},
|
|
Options: []*discordgo.ApplicationCommandOption{
|
|
{
|
|
Type: discordgo.ApplicationCommandOptionString,
|
|
Name: "type",
|
|
Description: "The type of joke to get",
|
|
Required: false,
|
|
Choices: []*discordgo.ApplicationCommandOptionChoice{
|
|
{
|
|
Name: "Programming",
|
|
Value: "Programming",
|
|
},
|
|
{
|
|
Name: "Misc",
|
|
Value: "Miscellaneous",
|
|
},
|
|
{
|
|
Name: "Dark",
|
|
Value: "Dark",
|
|
},
|
|
{
|
|
Name: "Pun",
|
|
Value: "Pun",
|
|
},
|
|
{
|
|
Name: "Spooky",
|
|
Value: "Spooky",
|
|
},
|
|
{
|
|
Name: "Christmas",
|
|
Value: "Christmas",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
func JokeHandler(s *discordgo.Session, i *discordgo.InteractionCreate) {
|
|
jokeType := "Any"
|
|
if opts := i.ApplicationCommandData().Options; len(opts) > 0 {
|
|
if v := opts[0].StringValue(); v != "" {
|
|
jokeType = v
|
|
}
|
|
}
|
|
if !isValidJokeType(jokeType) {
|
|
jokeType = "Any"
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 6*time.Second)
|
|
defer cancel()
|
|
|
|
content, err := fetchJoke(ctx, jokeType)
|
|
if err != nil {
|
|
if i.GuildID != "" {
|
|
shared.RespondEphemeral(s, i, "Failed to get joke.")
|
|
} else {
|
|
shared.Respond(s, i, "Failed to get joke.")
|
|
}
|
|
return
|
|
}
|
|
|
|
shared.Respond(s, i, content)
|
|
}
|
|
|
|
func isValidJokeType(t string) bool {
|
|
switch t {
|
|
case "Any", "Programming", "Misc", "Dark", "Pun", "Spooky", "Christmas":
|
|
return true
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
type jokeAPIResponse struct {
|
|
Error bool `json:"error"`
|
|
Message string `json:"message"`
|
|
Type string `json:"type"`
|
|
Joke string `json:"joke"`
|
|
Setup string `json:"setup"`
|
|
Delivery string `json:"delivery"`
|
|
}
|
|
|
|
func fetchJoke(ctx context.Context, jokeType string) (string, error) {
|
|
const baseURL = "https://v2.jokeapi.dev/joke"
|
|
req, err := http.NewRequestWithContext(ctx, http.MethodGet, fmt.Sprintf("%s/%s", baseURL, jokeType), nil)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode < 200 || resp.StatusCode >= 300 {
|
|
return "", fmt.Errorf("joke api status: %s", resp.Status)
|
|
}
|
|
|
|
var data jokeAPIResponse
|
|
if err := json.NewDecoder(resp.Body).Decode(&data); err != nil {
|
|
return "", err
|
|
}
|
|
if data.Error {
|
|
if data.Message != "" {
|
|
return "", errors.New(data.Message)
|
|
}
|
|
return "", errors.New("joke api returned error")
|
|
}
|
|
|
|
switch data.Type {
|
|
case "single":
|
|
if data.Joke == "" {
|
|
return "", errors.New("empty joke")
|
|
}
|
|
return data.Joke, nil
|
|
case "twopart":
|
|
if data.Setup == "" && data.Delivery == "" {
|
|
return "", errors.New("empty joke")
|
|
}
|
|
if data.Setup == "" {
|
|
return data.Delivery, nil
|
|
}
|
|
if data.Delivery == "" {
|
|
return data.Setup, nil
|
|
}
|
|
return data.Setup + "\n" + data.Delivery, nil
|
|
default:
|
|
return "", fmt.Errorf("unknown joke type: %q", data.Type)
|
|
}
|
|
}
|