about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--cmd/bot/main.go15
-rw-r--r--pkg/bot/bot.go25
-rw-r--r--pkg/discord/discord.go68
-rw-r--r--pkg/discord/entities.go8
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"`
+}