diff options
| -rw-r--r-- | .gitignore | 3 | ||||
| -rw-r--r-- | cmd/bot/main.go | 39 | ||||
| -rw-r--r-- | go.mod | 5 | ||||
| -rw-r--r-- | go.sum | 32 | ||||
| -rw-r--r-- | log/.gitkeep | 0 | ||||
| -rw-r--r-- | pkg/bot/bot.go | 57 | ||||
| -rw-r--r-- | pkg/discord/discord.go | 20 |
7 files changed, 118 insertions, 38 deletions
diff --git a/.gitignore b/.gitignore index 286f9e9..f1f93af 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,7 @@ .DS_STORE /build/ +/log/* .env + +!*.gitkeep \ No newline at end of file diff --git a/cmd/bot/main.go b/cmd/bot/main.go index 0f241c9..512b60b 100644 --- a/cmd/bot/main.go +++ b/cmd/bot/main.go @@ -1,31 +1,56 @@ package main import ( + "fmt" "jinx/pkg/bot" - "log" "os" "os/signal" "syscall" + "time" + + "github.com/rs/zerolog" ) func main() { + logger, err := createLogger() + if err != nil { + panic(err) + } + token := os.Getenv("BOT_TOKEN") if token == "" { - log.Fatal("`BOT_TOKEN` is not set.") + logger.Fatal().Msg("`BOT_TOKEN` is not set.") } - b, err := bot.Start(token) - if err != nil { - panic(err) + logger.Info().Msg("starting jinx!") + + b := bot.NewBot(token, logger) + + if err := b.Start(); err != nil { + logger.Fatal().Err(err).Msg("error starting jinx") } c := make(chan os.Signal, 2) signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) s := <-c - log.Printf("received signal: %s! stopping...", s) + logger.Info().Msgf("received signal: %s! stopping...", s) if err := b.Stop(); err != nil { - panic(err) + logger.Fatal().Err(err).Msg("error stopping jinx") + } +} + +func createLogger() (*zerolog.Logger, error) { + timestamp := time.Now().Format(time.RFC3339) + logFileName := fmt.Sprintf("log/jinx-%s.log", timestamp) + logFile, err := os.OpenFile(logFileName, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) + if err != nil { + return nil, err } + + stdout := zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339} + + logger := zerolog.New(zerolog.MultiLevelWriter(stdout, logFile)).With().Timestamp().Logger() + return &logger, nil } diff --git a/go.mod b/go.mod index 3e15bef..e4906d7 100644 --- a/go.mod +++ b/go.mod @@ -2,4 +2,7 @@ module jinx go 1.18 -require github.com/gorilla/websocket v1.5.0 +require ( + github.com/gorilla/websocket v1.5.0 + github.com/rs/zerolog v1.26.1 +) diff --git a/go.sum b/go.sum index e5a03d4..5532888 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,34 @@ +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= +github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/log/.gitkeep b/log/.gitkeep new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/log/.gitkeep diff --git a/pkg/bot/bot.go b/pkg/bot/bot.go index 9095d7c..add3e56 100644 --- a/pkg/bot/bot.go +++ b/pkg/bot/bot.go @@ -2,49 +2,64 @@ package bot import ( "context" - "fmt" + "errors" "jinx/pkg/discord" - "log" + + "github.com/rs/zerolog" ) type Bot struct { - Client *discord.Discord + client *discord.Discord + logger *zerolog.Logger cancelContext context.CancelFunc } -func Start(token string) (*Bot, error) { - fmt.Println("hi..!") +func NewBot(token string, logger *zerolog.Logger) *Bot { + return &Bot{ + client: discord.NewClient(token, logger), + logger: logger, + cancelContext: nil, + } +} - client := discord.NewClient(token) +func (b *Bot) Start() error { + var err error + ctx, cancel := context.WithCancel(context.Background()) + b.cancelContext = cancel - client.AddEventHandler(discord.DISCORD_EVENT_READY, func(_ any) { - log.Println("bot is ready!") + defer func() { + if err != nil { + cancel() + } + }() + + b.client.AddEventHandler(discord.DISCORD_EVENT_READY, func(_ any) { + b.logger.Info().Msg("ready!") }) - client.AddEventHandler(discord.DISCORD_EVENT_MESSAGE, func(m any) { + b.client.AddEventHandler(discord.DISCORD_EVENT_MESSAGE, func(m any) { msg := m.(discord.GatewayMessageCreateEvent) - log.Printf("message: %s", msg.Content) + b.logger.Debug().Msgf("message: %s", msg.Content) if msg.Content == "ping" { - if err := client.SendMessage(msg.ChannelID, "pong"); err != nil { - log.Printf("error sending message: %s", err) + if err := b.client.SendMessage(msg.ChannelID, "pong"); err != nil { + b.logger.Error().Err(err).Msg("error sending message") } } }) - ctx, cancel := context.WithCancel(context.Background()) - if err := client.Connect(ctx); err != nil { - cancel() - return nil, err + if err := b.client.Connect(ctx); err != nil { + return err } - return &Bot{ - Client: client, - cancelContext: cancel, - }, nil + return nil } func (b *Bot) Stop() error { + if b.cancelContext == nil { + return errors.New("bot has no context") + } + b.cancelContext() - return b.Client.Disconnect() + return b.client.Disconnect() } diff --git a/pkg/discord/discord.go b/pkg/discord/discord.go index fd60edd..bd8a7f7 100644 --- a/pkg/discord/discord.go +++ b/pkg/discord/discord.go @@ -5,26 +5,28 @@ import ( "encoding/json" "errors" "fmt" - "log" "math/rand" "net/http" "time" "github.com/gorilla/websocket" + "github.com/rs/zerolog" ) type Discord struct { token string + logger *zerolog.Logger conn *websocket.Conn eventHandler *EventHandlerImpl rest REST } -func NewClient(token string) *Discord { +func NewClient(token string, logger *zerolog.Logger) *Discord { token = "Bot " + token return &Discord{ token: token, + logger: logger, conn: nil, eventHandler: NewEventHandler(), rest: NewREST(token), @@ -87,14 +89,14 @@ func (d *Discord) heartbeat(ctx context.Context, interval uint64) { case <-ctx.Done(): return case <-ticker.C: - fmt.Println("sending heartbeat.") + d.logger.Debug().Msg("sending heartbeat") msg := GatewayPayload[any]{ Op: GATEWAY_OP_HEARTBEAT, } if err := d.conn.WriteJSON(msg); err != nil { - log.Fatalf("error sending heartbeat: %s\n", err) + d.logger.Error().Err(err).Msg("error sending heartbeat") } } } @@ -124,7 +126,7 @@ func (d *Discord) identify() error { return err } - fmt.Printf("identify response payload: %+v\n", res) + d.logger.Debug().Msgf("identify response payload: %+v", res) if res.Op != GATEWAY_OP_DISPATCH { return fmt.Errorf("expected opcode %d, got %d", GATEWAY_OP_DISPATCH, res.Op) @@ -141,7 +143,7 @@ func (d *Discord) listen(ctx context.Context) { for { var msg GatewayPayload[json.RawMessage] if err := d.conn.ReadJSON(&msg); err != nil { - log.Fatalf("error reading message: %s\n", err) + d.logger.Error().Err(err).Msg("error reading message") } select { @@ -156,13 +158,13 @@ func (d *Discord) listen(ctx context.Context) { func (d *Discord) onEvent(msg GatewayPayload[json.RawMessage]) error { switch msg.Op { case GATEWAY_OP_HEARTBEAT_ACK: - fmt.Println("received heartbeat ack.") + d.logger.Debug().Msg("received heartbeat ack.") case GATEWAY_OP_HEARTBEAT: return errors.New("on demand heartbeat not implemented") case GATEWAY_OP_DISPATCH: return d.onDispatch(msg.EventName, msg.Data) default: - fmt.Printf("received unknown opcode: %d\n", msg.Op) + d.logger.Warn().Msgf("received unknown opcode: %d", msg.Op) } return nil @@ -178,7 +180,7 @@ func (d *Discord) onDispatch(eventName string, body json.RawMessage) error { d.eventHandler.Fire(DISCORD_EVENT_MESSAGE, payload) default: - fmt.Println("received unknown event:", eventName) + d.logger.Warn().Msgf("received unknown event: %s", eventName) } return nil |
