From 344176063bfabb585a8471e15aa0223c18c1b7e6 Mon Sep 17 00:00:00 2001 From: Penguin-71630 Date: Fri, 12 Dec 2025 23:25:05 +0800 Subject: [PATCH] added slash web --- README.md | 10 ++++++++++ api/client.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ bot/bot.go | 36 +++++++++++++++++++++++++++++++++--- bot/commands.go | 30 ++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 6815b10..81523ec 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,13 @@ https://hackmd.io/@penguin71630/go-final-project Note: - View API document: `make viewapi` + \ No newline at end of file diff --git a/api/client.go b/api/client.go index a6d9bc5..1a2b7ef 100644 --- a/api/client.go +++ b/api/client.go @@ -31,6 +31,14 @@ type AliasesResponse struct { Aliases []string `json:"aliases"` } +type GenLoginURLRequest struct { + UserID string `json:"userId"` +} + +type GenLoginURLResponse struct { + LoginURL string `json:"loginUrl"` +} + func NewClient(baseURL string) *Client { return &Client{ baseURL: baseURL, @@ -216,3 +224,41 @@ func (c *Client) GetImageFile(id string) ([]byte, error) { return io.ReadAll(resp.Body) } + +func (c *Client) GenerateLoginURL(userID string) (string, error) { + url := fmt.Sprintf("%s/auth/gen-login-url", c.baseURL) + + reqBody := GenLoginURLRequest{UserID: userID} + jsonBody, err := json.Marshal(reqBody) + if err != nil { + return "", err + } + + req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonBody)) + if err != nil { + return "", err + } + + req.Header.Set("Content-Type", "application/json") + + // TODO: Set preshared key authorization + req.Header.Set("Authorization", "Bearer poop") + + resp, err := c.httpClient.Do(req) + if err != nil { + return "", err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + body, _ := io.ReadAll(resp.Body) + return "", fmt.Errorf("API returned status %d: %s", resp.StatusCode, string(body)) + } + + var result GenLoginURLResponse + if err := json.NewDecoder(resp.Body).Decode(&result); err != nil { + return "", err + } + + return result.LoginURL, nil +} diff --git a/bot/bot.go b/bot/bot.go index ea93c6d..c0f8c67 100644 --- a/bot/bot.go +++ b/bot/bot.go @@ -48,7 +48,7 @@ func New(cfg *config.Config) (*Bot, error) { return bot, nil } -func (b *Bot) registerSlashCommands() error { +func (b *Bot) registerSlashCommands(guildID string) error { commands := []*discordgo.ApplicationCommand{ { Name: "ping", @@ -70,10 +70,14 @@ func (b *Bot) registerSlashCommands() error { }, }, }, + { + Name: "web", + Description: "Get a login link to the web interface", + }, } for _, cmd := range commands { - _, err := b.session.ApplicationCommandCreate(b.session.State.User.ID, "", cmd) + _, err := b.session.ApplicationCommandCreate(b.session.State.User.ID, guildID, cmd) if err != nil { return fmt.Errorf("cannot create command %s: %w", cmd.Name, err) } @@ -82,6 +86,21 @@ func (b *Bot) registerSlashCommands() error { return nil } +func (b *Bot) clearSlashCommands(guildID string) error { + commands, err := b.session.ApplicationCommands(b.session.State.User.ID, guildID) + if err != nil { + return err + } + + for _, cmd := range commands { + err := b.session.ApplicationCommandDelete(b.session.State.User.ID, guildID, cmd.ID) + if err != nil { + log.Printf("Failed to delete command %s: %v", cmd.Name, err) + } + } + return nil +} + func (b *Bot) registerHandlers() { b.session.AddHandler(b.onReady) b.session.AddHandler(b.onMessageCreate) @@ -91,8 +110,17 @@ func (b *Bot) registerHandlers() { func (b *Bot) onReady(s *discordgo.Session, event *discordgo.Ready) { log.Printf("Logged in as: %v#%v", s.State.User.Username, s.State.User.Discriminator) + // For development: set your guild ID here for instant updates + // For production: use "" for global commands + guildID := "1377176828833169468" // Replace with your Discord server ID for faster testing + + // clear slash commands + if err := b.clearSlashCommands(guildID); err != nil { + log.Printf("Error clearing slash commands: %v", err) + } + // Register slash commands - if err := b.registerSlashCommands(); err != nil { + if err := b.registerSlashCommands(guildID); err != nil { log.Printf("Error registering slash commands: %v", err) } @@ -115,6 +143,8 @@ func (b *Bot) onInteractionCreate(s *discordgo.Session, i *discordgo.Interaction b.handleSlashGreet(s, i) case "echo": b.handleSlashEcho(s, i) + case "web": + b.handleSlashWeb(s, i) } } diff --git a/bot/commands.go b/bot/commands.go index 38f3331..74d3912 100644 --- a/bot/commands.go +++ b/bot/commands.go @@ -69,3 +69,33 @@ func (b *Bot) handleSlashEcho(s *discordgo.Session, i *discordgo.InteractionCrea }, }) } + +func (b *Bot) handleSlashWeb(s *discordgo.Session, i *discordgo.InteractionCreate) { + var userID string + if i.Member != nil { + userID = i.Member.User.ID + } else if i.User != nil { + userID = i.User.ID + } + + // Call backend API + loginURL, err := b.apiClient.GenerateLoginURL(userID) + if err != nil { + s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: "❌ Failed to generate login URL: " + err.Error(), + Flags: discordgo.MessageFlagsEphemeral, + }, + }) + return + } + + s.InteractionRespond(i.Interaction, &discordgo.InteractionResponse{ + Type: discordgo.InteractionResponseChannelMessageWithSource, + Data: &discordgo.InteractionResponseData{ + Content: fmt.Sprintf("🔗 **Click here to access the web page:**\n%s\n\n", loginURL), + Flags: discordgo.MessageFlagsEphemeral, + }, + }) +}