diff options
| -rw-r--r-- | cmd/bot/main.go | 15 | ||||
| -rw-r--r-- | pkg/bot/bot.go | 25 | ||||
| -rw-r--r-- | pkg/discord/discord.go | 68 | ||||
| -rw-r--r-- | pkg/discord/entities.go | 8 |
4 files changed, 106 insertions, 10 deletions
diff --git a/cmd/bot/main.go b/cmd/bot/main.go index 51661e8..0f241c9 100644 --- a/cmd/bot/main.go +++ b/cmd/bot/main.go @@ -4,6 +4,8 @@ import ( "jinx/pkg/bot" "log" "os" + "os/signal" + "syscall" ) func main() { @@ -12,7 +14,18 @@ func main() { log.Fatal("`BOT_TOKEN` is not set.") } - if err := bot.Start(token); err != nil { + b, err := bot.Start(token) + if err != nil { + panic(err) + } + + c := make(chan os.Signal, 2) + signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) + + s := <-c + log.Printf("received signal: %s! stopping...", s) + + if err := b.Stop(); err != nil { panic(err) } } diff --git a/pkg/bot/bot.go b/pkg/bot/bot.go index 71eb0e9..091e1be 100644 --- a/pkg/bot/bot.go +++ b/pkg/bot/bot.go @@ -6,24 +6,33 @@ import ( "jinx/pkg/discord" ) -func Start(token string) error { +type Bot struct { + Client *discord.Discord + cancelContext context.CancelFunc +} + +func Start(token string) (*Bot, error) { fmt.Println("hi..!") client := discord.NewClient(token) ctx, cancel := context.WithCancel(context.Background()) - defer cancel() fmt.Println("connecting..") if err := client.Connect(ctx); err != nil { - return err + cancel() + return nil, err } fmt.Println("connected..") - if err := client.Disconnect(); err != nil { - return err - } + return &Bot{ + Client: client, + cancelContext: cancel, + }, nil +} - return nil -} \ No newline at end of file +func (b *Bot) Stop() error { + b.cancelContext() + return b.Client.Disconnect() +} diff --git a/pkg/discord/discord.go b/pkg/discord/discord.go index 1fefe6c..c5e7d67 100644 --- a/pkg/discord/discord.go +++ b/pkg/discord/discord.go @@ -60,6 +60,8 @@ func (d *Discord) Connect(ctx context.Context) error { return err } + go d.listen(ctx) + return nil } @@ -141,11 +143,38 @@ func (d *Discord) startHeartbeat(ctx context.Context, interval uint64) { } } +func (d *Discord) listen(ctx context.Context) { + for { + var msg GatewayPayload[any] + if err := d.Conn.ReadJSON(&msg); err != nil { + log.Fatalf("error reading message: %s\n", err) + } + + select { + case <-ctx.Done(): + return + default: + fmt.Printf("received message: %+v\n", msg) + + if msg.EventName == "MESSAGE_CREATE" { + event := msg.Data.(map[string]interface{}) + if event["content"] == "ping" { + fmt.Println("got ping, sending pong...") + if err := d.sendMessage(Snowflake(event["channel_id"].(string)), "pong"); err != nil { + log.Fatalf("error sending message: %s\n", err) + } + } + } + } + } +} + func (d *Discord) identify() error { msg := GatewayPayload[GatewayIdentifyMsg]{ Op: GATEWAY_OP_IDENTIFY, Data: GatewayIdentifyMsg{ - Token: d.Token, + Token: d.Token, + Intents: 13991, Properties: GatewayIdentifyProperties{ OS: "linux", Browser: "jinx", @@ -176,3 +205,40 @@ func (d *Discord) identify() error { return nil } + +func (d *Discord) sendMessage(channelID Snowflake, content string) error { + url := DISCORD_URl + "channels/" + string(channelID) + "/messages" + + msg := struct { + Content string `json:"content"` + }{ + Content: content, + } + + raw, err := json.Marshal(msg) + if err != nil { + return err + } + + req, err := http.NewRequest("POST", url, bytes.NewBuffer(raw)) + if err != nil { + return err + } + + req.Header.Set("Authorization", "Bot "+d.Token) + req.Header.Set("Content-Type", "application/json") + req.Header.Set("User-Agent", USER_AGENT) + + res, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + + switch res.StatusCode { + case 200: + default: + return errors.New("unexpected status code after sending message: " + res.Status) + } + + return nil +} diff --git a/pkg/discord/entities.go b/pkg/discord/entities.go index 85965bf..8a62fc6 100644 --- a/pkg/discord/entities.go +++ b/pkg/discord/entities.go @@ -13,3 +13,11 @@ type Guild struct { Name string `json:"name"` Unavailable bool `json:"unavailable"` } + +type Message struct { + ID Snowflake `json:"id"` + ChannelID Snowflake `json:"channel_id"` + GuildID Snowflake `json:"guild_id"` + Author User `json:"author"` + Content string `json:"content"` +} |
