diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index aaefa106..911a37f3 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -14,7 +14,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.17 + go-version: 1.18 - name: go build run: go build -v ./... @@ -30,7 +30,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.17 + go-version: 1.18 - name: go vet run: go vet -v ./... @@ -46,7 +46,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.17 + go-version: 1.18 - name: go test env: @@ -56,7 +56,8 @@ jobs: gostaticcheck: # We want to run on external PRs, but not on our own internal PRs as they'll be run # by the push to the branch. - if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + # if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name != github.repository + if: ${{ false }} # disable for now as staticcheck does not working with go 1.18 runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 @@ -64,7 +65,7 @@ jobs: - name: Set up Go uses: actions/setup-go@v2 with: - go-version: 1.17 + go-version: 1.18 - name: go staticcheck uses: dominikh/staticcheck-action@v1.1.0 diff --git a/README.md b/README.md index 10902b7c..1b770f89 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,15 @@ -[![Go Reference](https://pkg.go.dev/badge/github.com/DisgoOrg/disgo.svg)](https://pkg.go.dev/github.com/DisgoOrg/disgo) -[![Go Report](https://goreportcard.com/badge/github.com/DisgoOrg/disgo)](https://goreportcard.com/report/github.com/DisgoOrg/disgo) -[![Go Version](https://img.shields.io/github/go-mod/go-version/DisgoOrg/disgo)](https://golang.org/doc/devel/release.html) -[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/DisgoOrg/disgo/blob/master/LICENSE) -[![Disgo Version](https://img.shields.io/github/v/tag/DisgoOrg/disgo?label=release)](https://github.com/DisgoOrg/disgo/releases/latest) +[![Go Reference](https://pkg.go.dev/badge/github.com/disgoorg/disgo.svg)](https://pkg.go.dev/github.com/disgoorg/disgo) +[![Go Report](https://goreportcard.com/badge/github.com/disgoorg/disgo)](https://goreportcard.com/report/github.com/disgoorg/disgo) +[![Go Version](https://img.shields.io/github/go-mod/go-version/disgoorg/disgo)](https://golang.org/doc/devel/release.html) +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/disgoorg/disgo/blob/master/LICENSE) +[![Disgo Version](https://img.shields.io/github/v/tag/disgoorg/disgo?label=release)](https://github.com/disgoorg/disgo/releases/latest) [![Disgo Discord](https://discord.com/api/guilds/817327181659111454/widget.png)](https://discord.gg/TewhTfDpvW) discord gopher -# disgo +# DisGo -disgo is a [Discord](https://discord.com) API wrapper written in [Go](https://golang.org/) aimed to be consistent, modular, customizable and easy to use +DisGo is a [Discord](https://discord.com) API wrapper written in [GoLang](https://golang.org/) aimed to be consistent, modular, customizable and higher level than other Discord API wrappers. ## Summary @@ -19,7 +19,7 @@ disgo is a [Discord](https://discord.com) API wrapper written in [Go](https://go 4. [Documentation](#documentation) 5. [Examples](#examples) 6. [Related Projects](#related-projects) -7. [Why another library?](#why-another-library) +7. [Other GoLang Discord Libraries](#other-golang-discord-libraries) 8. [Troubleshooting](#troubleshooting) 9. [Contributing](#contributing) 10. [License](#license) @@ -32,6 +32,7 @@ disgo is a [Discord](https://discord.com) API wrapper written in [Go](https://go * [HTTP Interactions](https://discord.com/developers/docs/interactions/slash-commands#receiving-an-interaction) * [Application Commands](https://discord.com/developers/docs/interactions/application-commands) * [Message Components](https://discord.com/developers/docs/interactions/message-components) +* [Modals](https://discord.com/developers/docs/interactions/receiving-and-responding#interaction-response-object-modal) * [Stage Instance](https://discord.com/developers/docs/resources/stage-instance) * [Guild Template](https://discord.com/developers/docs/resources/guild-template) * [Sticker](https://discord.com/developers/docs/resources/sticker) @@ -51,7 +52,7 @@ disgo is a [Discord](https://discord.com) API wrapper written in [Go](https://go ### Installing ```sh -go get github.com/DisgoOrg/disgo +go get github.com/disgoorg/disgo ``` ### Building a Disgo Instance @@ -60,14 +61,15 @@ go get github.com/DisgoOrg/disgo package main import ( - "github.com/DisgoOrg/disgo/core/bot" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/gateway" ) func main() { - disgo, err := bot.New("token", - bot.WithGatewayOpts( + client, err := disgo.New("token", + bot.WithGatewayConfigOpts( gateway.WithGatewayIntents( discord.GatewayIntentGuilds, discord.GatewayIntentGuildMessages, @@ -84,28 +86,28 @@ func main() { package main import ( + "context" "os" "os/signal" "syscall" - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/bot" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/cache" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/log" ) func main() { - disgo, err := bot.New(os.Getenv("token"), - bot.WithGatewayOpts( + client, err := disgo.New(os.Getenv("token"), + bot.WithGatewayConfigOpts( gateway.WithGatewayIntents( - discord.GatewayIntentGuilds, - discord.GatewayIntentGuildMessages, - discord.GatewayIntentDirectMessages, + discord.GatewayIntentsNone, ), ), - bot.WithCacheOpts(core.WithCacheFlags(core.CacheFlagsNone)), + bot.WithCacheConfigOpts(cache.WithCacheFlags(cache.FlagsDefault)), bot.WithEventListeners(&events.ListenerAdapter{ OnMessageCreate: onMessageCreate, }), @@ -114,9 +116,9 @@ func main() { log.Fatal("error while building disgo: ", err) } - defer disgo.Close() + defer client.Close(context.TODO()) - if err = disgo.ConnectGateway(); err != nil { + if err = client.ConnectGateway(context.TODO()); err != nil { log.Fatal("errors while connecting to gateway: ", err) } @@ -134,60 +136,60 @@ func onMessageCreate(event *events.MessageCreateEvent) { message = "ping" } if message != "" { - _, _ = event.Message.Reply(discord.NewMessageCreateBuilder().SetContent(message).Build()) + _, _ = event.Client().Rest().ChannelService().CreateMessage(event.ChannelID, discord.NewMessageCreateBuilder().SetContent(message).Build()) } } - ``` ### Logging -disgo uses our own small [logging lib](https://github.com/DisgoOrg/log) which provides an [interface](https://github.com/DisgoOrg/log/blob/master/logger.go) you can implement. This lib also comes with a default logger which is interchangeable and based on the standard log package. You can read more about it [here](https://github.com/DisgoOrg/log) +disgo uses our own small [logging lib](https://github.com/disgoorg/log) which provides an [interface](https://github.com/disgoorg/log/blob/master/logger.go) you can implement. This lib also comes with a default logger which is interchangeable and based on the standard log package. You can read more about it [here](https://github.com/disgoorg/log) ## Documentation Documentation is wip and can be found under -* [![Go Reference](https://pkg.go.dev/badge/github.com/DisgoOrg/disgo.svg)](https://pkg.go.dev/github.com/DisgoOrg/disgo) +* [![Go Reference](https://pkg.go.dev/badge/github.com/disgoorg/disgo.svg)](https://pkg.go.dev/github.com/disgoorg/disgo) * [![Discord Documentation](https://img.shields.io/badge/Discord%20Documentation-blue.svg)](https://discord.com/developers/docs) Wiki is currently under construction ## Examples -You can find examples under [_examples](https://github.com/DisgoOrg/disgo/tree/master/_examples) +You can find examples under [_examples](https://github.com/disgoorg/disgo/tree/master/_examples) + +There is also a bot template with commands & db [here](https://github.com/disgoorg/bot-template) or in these projects: -* [disgo-butler](https://github.com/DisgoOrg/disgo-butler) +* [disgo-butler](https://github.com/disgoorg/disgo-butler) * [BansBot](https://github.com/Skye-31/BansBot) * [Reddit-Discord-Bot](https://github.com/TopiSenpai/Reddit-Discord-Bot) * [Kitsune-Bot](https://github.com/TopiSenpai/Kitsune-Bot) -* [Uno-Bot](https://github.com/TopiSenpai/Uno-Bot) +* [KittyBot](https://github.com/KittyBot-Org/KittyBotGo) ## Related Projects ### [Lavalink](https://github.com/freyacodes/Lavalink) -Standalone audio sending node based on Lavaplayer and JDA-Audio. Allows for sending audio without it ever reaching any of your shards. +is a standalone audio sending node based on [Lavaplayer](https://github.com/sedmelluq/lavaplayer) and JDA-Audio. Allows for sending audio without it ever reaching any of your shards. Being used in production by FredBoat, Dyno, LewdBot, and more. -### [disgolink](https://github.com/DisgoOrg/disgolink) - -[Lavalink Client](https://github.com/freyacodes/Lavalink) which can be used to communicate with LavaLink to play/search tracks +### [disgolink](https://github.com/disgoorg/disgolink) -### [dislog](https://github.com/DisgoOrg/dislog) +is a [Lavalink Client](https://github.com/freyacodes/Lavalink) which can be used to communicate with LavaLink to play/search tracks -Discord webhook logger integration for [logrus](https://github.com/sirupsen/logrus) +### [dislog](https://github.com/disgoorg/dislog) -## Why another library? +is a discord webhook logger hook for [logrus](https://github.com/sirupsen/logrus) -[discordgo](https://github.com/bwmarrin/discordgo) is a great library, but it's super low level and pain -[disgord](https://github.com/andersfylling/disgord) I don't like code gen magic -[arikawa](https://github.com/diamondburned/arikawa) v3 rewrite looks promising but when I started with disgo v2 looked kinda bad +## Other GoLang Discord Libraries -disgo aims to be a high level library that is modular and not a pain to use. +* [discordgo](https://github.com/bwmarrin/discordgo) +* [disgord](https://github.com/andersfylling/disgord) +* [arikawa](https://github.com/diamondburned/arikawa) +* [corde](https://github.com/Karitham/corde) ## Troubleshooting @@ -199,7 +201,7 @@ Contributions are welcomed but for bigger changes please first reach out via [Di ## License -Distributed under the [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/DisgoOrg/disgo/blob/master/LICENSE) +Distributed under the [![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/disgoorg/disgo/blob/master/LICENSE) . See LICENSE for more information. diff --git a/_examples/application_commands/gateway/example.go b/_examples/application_commands/gateway/example.go index 7c0f4934..b235b477 100644 --- a/_examples/application_commands/gateway/example.go +++ b/_examples/application_commands/gateway/example.go @@ -6,15 +6,14 @@ import ( "os/signal" "syscall" - "github.com/DisgoOrg/disgo/core/bot" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/snowflake" - - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/disgo/info" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/cache" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/log" + "github.com/disgoorg/snowflake" ) var ( @@ -43,13 +42,13 @@ var ( ) func main() { - log.SetLevel(log.LevelDebug) + log.SetLevel(log.LevelTrace) log.Info("starting example...") - log.Infof("disgo version: %s", info.Version) + log.Infof("disgo version: %s", disgo.Version) - disgo, err := bot.New(token, - bot.WithGatewayOpts(gateway.WithGatewayIntents(discord.GatewayIntentsNone)), - bot.WithCacheOpts(core.WithCacheFlags(core.CacheFlagsDefault)), + client, err := disgo.New(token, + bot.WithGatewayConfigOpts(gateway.WithGatewayIntents(discord.GatewayIntentsNone)), + bot.WithCacheConfigOpts(cache.WithCacheFlags(cache.FlagsDefault)), bot.WithEventListeners(&events.ListenerAdapter{ OnApplicationCommandInteraction: commandListener, }), @@ -59,13 +58,13 @@ func main() { return } - defer disgo.Close(context.TODO()) + defer client.Close(context.TODO()) - if _, err = disgo.SetGuildCommands(guildID, commands); err != nil { + if _, err = client.Rest().Applications().SetGuildCommands(client.ApplicationID(), guildID, commands); err != nil { log.Fatal("error while registering commands: ", err) } - if err = disgo.ConnectGateway(context.TODO()); err != nil { + if err = client.ConnectGateway(context.TODO()); err != nil { log.Fatal("error while connecting to gateway: ", err) } @@ -77,14 +76,14 @@ func main() { func commandListener(event *events.ApplicationCommandInteractionEvent) { data := event.SlashCommandInteractionData() - if data.CommandName == "say" { + if data.CommandName() == "say" { err := event.CreateMessage(discord.NewMessageCreateBuilder(). - SetContent(*data.Options.String("message")). - SetEphemeral(*data.Options.Bool("ephemeral")). + SetContent(data.String("message")). + SetEphemeral(data.Bool("ephemeral")). Build(), ) if err != nil { - event.Bot().Logger.Error("error on sending response: ", err) + event.Client().Logger().Error("error on sending response: ", err) } } } diff --git a/_examples/application_commands/gateway/go.mod b/_examples/application_commands/gateway/go.mod deleted file mode 100644 index c475335b..00000000 --- a/_examples/application_commands/gateway/go.mod +++ /dev/null @@ -1,20 +0,0 @@ -module github.com/DisgoOrg/disgo/_examples/application_commands/gateway - -go 1.17 - -replace github.com/DisgoOrg/disgo => ../../../ - -require ( - github.com/DisgoOrg/disgo v0.5.6 - github.com/DisgoOrg/log v1.1.3 - github.com/DisgoOrg/snowflake v1.0.4 -) - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/google/go-cmp v0.5.7 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect -) diff --git a/_examples/application_commands/gateway/go.sum b/_examples/application_commands/gateway/go.sum deleted file mode 100644 index 94ac585e..00000000 --- a/_examples/application_commands/gateway/go.sum +++ /dev/null @@ -1,26 +0,0 @@ -github.com/DisgoOrg/log v1.1.3 h1:UN0ZfmPZ7yhCCDQ7iVvIedvZ2zEexNS5Ek76GBuffOE= -github.com/DisgoOrg/log v1.1.3/go.mod h1:tSMofXaNhQNvzLRoL4tAiCG9yGY1ES5DLvduh7e9GRU= -github.com/DisgoOrg/snowflake v1.0.4 h1:hgeXSaXRDVdoNJ0rfHXyVsgxQMzctP346S5WXlBmoOU= -github.com/DisgoOrg/snowflake v1.0.4/go.mod h1:jIQVlVmElm2OGt6v52ITf/71ODaU09chUCflxt8+3yM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/application_commands/http/example.go b/_examples/application_commands/http/example.go index d384fdcf..6926942c 100644 --- a/_examples/application_commands/http/example.go +++ b/_examples/application_commands/http/example.go @@ -6,13 +6,13 @@ import ( "os/signal" "syscall" - "github.com/DisgoOrg/disgo/core/bot" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/httpserver" - "github.com/DisgoOrg/disgo/info" - "github.com/DisgoOrg/log" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/disgo/httpserver" + "github.com/disgoorg/log" + "github.com/disgoorg/snowflake" "github.com/oasisprotocol/curve25519-voi/primitives/ed25519" ) @@ -45,17 +45,17 @@ var ( func main() { log.SetLevel(log.LevelDebug) log.Info("starting example...") - log.Info("disgo version: ", info.Version) + log.Info("disgo version: ", disgo.Version) // use custom ed25519 verify implementation httpserver.Verify = func(publicKey httpserver.PublicKey, message, sig []byte) bool { return ed25519.Verify(publicKey, message, sig) } - disgo, err := bot.New(token, - bot.WithHTTPServerOpts( + client, err := disgo.New(token, + bot.WithHTTPServerConfigOpts( httpserver.WithURL("/interactions/callback"), - httpserver.WithPort(":80"), + httpserver.WithAddress(":80"), httpserver.WithPublicKey(publicKey), ), bot.WithEventListeners(&events.ListenerAdapter{ @@ -67,13 +67,13 @@ func main() { return } - defer disgo.Close(context.TODO()) + defer client.Close(context.TODO()) - if _, err = disgo.SetGuildCommands(guildID, commands); err != nil { + if _, err = client.Rest().ApplicationService().SetGuildCommands(client.ApplicationID(), guildID, commands); err != nil { log.Fatal("error while registering commands: ", err) } - if err = disgo.StartHTTPServer(); err != nil { + if err = client.StartHTTPServer(); err != nil { log.Fatal("error while starting http server: ", err) } @@ -85,14 +85,14 @@ func main() { func commandListener(event *events.ApplicationCommandInteractionEvent) { data := event.SlashCommandInteractionData() - if data.CommandName == "say" { + if data.CommandName() == "say" { err := event.CreateMessage(discord.NewMessageCreateBuilder(). - SetContent(*data.Options.String("message")). - SetEphemeral(*data.Options.Bool("ephemeral")). + SetContent(data.String("message")). + SetEphemeral(data.Bool("ephemeral")). Build(), ) if err != nil { - event.Bot().Logger.Error("error on sending response: ", err) + event.Client().Logger().Error("error on sending response: ", err) } } } diff --git a/_examples/application_commands/http/go.mod b/_examples/application_commands/http/go.mod index bcdd5209..50d3e32a 100644 --- a/_examples/application_commands/http/go.mod +++ b/_examples/application_commands/http/go.mod @@ -1,23 +1,20 @@ -module github.com/DisgoOrg/disgo/_examples/application_commands/http +module github.com/disgoorg/disgo/_examples/application_commands/http -go 1.17 +go 1.18 -replace github.com/DisgoOrg/disgo => ../../../ +replace github.com/disgoorg/disgo => ../../../ require ( - github.com/DisgoOrg/disgo v0.5.6 - github.com/DisgoOrg/log v1.1.3 - github.com/DisgoOrg/snowflake v1.0.4 - github.com/oasisprotocol/curve25519-voi v0.0.0-20220203144524-0945b39ce060 + github.com/disgoorg/disgo v0.7.4 + github.com/disgoorg/log v1.2.0 + github.com/disgoorg/snowflake v1.1.0 + github.com/oasisprotocol/curve25519-voi v0.0.0-20220317090546-adb2f9614b17 ) require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/google/go-cmp v0.5.7 // indirect github.com/gorilla/websocket v1.5.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e // indirect golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect ) diff --git a/_examples/application_commands/http/go.sum b/_examples/application_commands/http/go.sum index 5adaa29f..de5d3738 100644 --- a/_examples/application_commands/http/go.sum +++ b/_examples/application_commands/http/go.sum @@ -1,25 +1,18 @@ -github.com/DisgoOrg/log v1.1.3 h1:UN0ZfmPZ7yhCCDQ7iVvIedvZ2zEexNS5Ek76GBuffOE= -github.com/DisgoOrg/log v1.1.3/go.mod h1:tSMofXaNhQNvzLRoL4tAiCG9yGY1ES5DLvduh7e9GRU= -github.com/DisgoOrg/snowflake v1.0.4 h1:hgeXSaXRDVdoNJ0rfHXyVsgxQMzctP346S5WXlBmoOU= -github.com/DisgoOrg/snowflake v1.0.4/go.mod h1:jIQVlVmElm2OGt6v52ITf/71ODaU09chUCflxt8+3yM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/disgoorg/log v1.2.0 h1:sqlXnu/ZKAlIlHV9IO+dbMto7/hCQ474vlIdMWk8QKo= +github.com/disgoorg/log v1.2.0/go.mod h1:3x1KDG6DI1CE2pDwi3qlwT3wlXpeHW/5rVay+1qDqOo= +github.com/disgoorg/snowflake v1.1.0 h1:uVF9QqI31uqo0kzbZahwvjaYQxn40SUfFK5pCNzfjYQ= +github.com/disgoorg/snowflake v1.1.0/go.mod h1:wUUTKWS1jSV0gIb3TSPsdJORNF8BcjKTjVeyrULEhr8= 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/oasisprotocol/curve25519-voi v0.0.0-20220203144524-0945b39ce060 h1:5lhZml8BWBdc9x+41kVFS1foepozE/YT5RxZi4OO3o0= -github.com/oasisprotocol/curve25519-voi v0.0.0-20220203144524-0945b39ce060/go.mod h1:WUcXjUd98qaCVFb6j8Xc87MsKeMCXDu9Nk8JRJ9SeC8= +github.com/oasisprotocol/curve25519-voi v0.0.0-20220317090546-adb2f9614b17 h1:pxR+aWfo+famermIZvD+SiDQ3qmF7Iy2VPZuEsKTMtA= +github.com/oasisprotocol/curve25519-voi v0.0.0-20220317090546-adb2f9614b17/go.mod h1:WUcXjUd98qaCVFb6j8Xc87MsKeMCXDu9Nk8JRJ9SeC8= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE= github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e h1:VvfwVmMH40bpMeizC9/K7ipM5Qjucuu16RWfneFPyhQ= golang.org/x/crypto v0.0.0-20210813211128-0a44fdfbc16e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -29,9 +22,4 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/_examples/application_commands/localization/example.go b/_examples/application_commands/localization/example.go new file mode 100644 index 00000000..1ef231d8 --- /dev/null +++ b/_examples/application_commands/localization/example.go @@ -0,0 +1,113 @@ +package main + +import ( + "context" + "os" + "os/signal" + "syscall" + + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/cache" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/log" + "github.com/disgoorg/snowflake" +) + +var ( + token = os.Getenv("disgo_token") + guildID = snowflake.GetSnowflakeEnv("disgo_guild_id") + + commands = []discord.ApplicationCommandCreate{ + discord.SlashCommandCreate{ + CommandName: "say", + CommandNameLocalizations: map[discord.Locale]string{ + discord.LocaleEnglishGB: "say", + discord.LocaleGerman: "sagen", + }, + Description: "says what you say", + DescriptionLocalizations: map[discord.Locale]string{ + discord.LocaleEnglishGB: "says what you say", + discord.LocaleGerman: "sagt was du sagst", + }, + DefaultPermission: true, + Options: []discord.ApplicationCommandOption{ + discord.ApplicationCommandOptionString{ + Name: "message", + NameLocalizations: map[discord.Locale]string{ + discord.LocaleEnglishGB: "message", + discord.LocaleGerman: "nachricht", + }, + Description: "What to say", + DescriptionLocalizations: map[discord.Locale]string{ + discord.LocaleEnglishGB: "What to say", + discord.LocaleGerman: "Was soll ich sagen?", + }, + Required: true, + }, + discord.ApplicationCommandOptionBool{ + Name: "ephemeral", + NameLocalizations: map[discord.Locale]string{ + discord.LocaleEnglishGB: "ephemeral", + discord.LocaleGerman: "kurzlebig", + }, + Description: "If the response should only be visible to you", + DescriptionLocalizations: map[discord.Locale]string{ + discord.LocaleEnglishGB: "If the response should only be visible to you", + discord.LocaleGerman: "Wenn die Antwort nur dir sichtbar sein soll", + }, + Required: true, + }, + }, + }, + } +) + +func main() { + log.SetLevel(log.LevelTrace) + log.Info("starting example...") + log.Infof("disgo version: %s", disgo.Version) + + client, err := disgo.New(token, + bot.WithGatewayConfigOpts(gateway.WithGatewayIntents(discord.GatewayIntentsNone)), + bot.WithCacheConfigOpts(cache.WithCacheFlags(cache.FlagsDefault)), + bot.WithEventListeners(&events.ListenerAdapter{ + OnApplicationCommandInteraction: commandListener, + }), + ) + if err != nil { + log.Fatal("error while building disgo instance: ", err) + return + } + + defer client.Close(context.TODO()) + + if _, err = client.Rest().Applications().SetGuildCommands(client.ApplicationID(), guildID, commands); err != nil { + log.Fatal("error while registering commands: ", err) + } + + if err = client.ConnectGateway(context.TODO()); err != nil { + log.Fatal("error while connecting to gateway: ", err) + } + + log.Infof("example is now running. Press CTRL-C to exit.") + s := make(chan os.Signal, 1) + signal.Notify(s, syscall.SIGINT, syscall.SIGTERM, os.Interrupt, os.Kill) + <-s +} + +func commandListener(event *events.ApplicationCommandInteractionEvent) { + data := event.SlashCommandInteractionData() + if data.CommandName() == "say" { + err := event.CreateMessage(discord.NewMessageCreateBuilder(). + SetContent(data.String("message")). + SetEphemeral(data.Bool("ephemeral")). + Build(), + ) + if err != nil { + event.Client().Logger().Error("error on sending response: ", err) + } + } +} diff --git a/_examples/components/example.go b/_examples/components/example.go index e0350bea..380fefff 100644 --- a/_examples/components/example.go +++ b/_examples/components/example.go @@ -6,13 +6,13 @@ import ( "os/signal" "syscall" - "github.com/DisgoOrg/disgo/core/bot" - "github.com/DisgoOrg/disgo/core/events" + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/disgo/info" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/log" ) var ( @@ -22,24 +22,25 @@ var ( func main() { log.SetLevel(log.LevelDebug) log.Info("starting example...") - log.Infof("disgo version: %s", info.Version) + log.Infof("disgo version: %s", disgo.Version) - disgo, err := bot.New(token, - bot.WithGatewayOpts(gateway.WithGatewayIntents(discord.GatewayIntentGuilds, discord.GatewayIntentGuildMessages, discord.GatewayIntentDirectMessages)), + client, err := disgo.New(token, + bot.WithGatewayConfigOpts(gateway.WithGatewayIntents(discord.GatewayIntentGuilds, discord.GatewayIntentGuildMessages, discord.GatewayIntentDirectMessages)), bot.WithEventListeners(&events.ListenerAdapter{ OnMessageCreate: func(event *events.MessageCreateEvent) { if event.Message.Author.BotUser || event.Message.Author.System { return } if event.Message.Content == "test" { - _, _ = event.Message.Reply(discord.NewMessageCreateBuilder(). + _, _ = event.Client().Rest().Channels().CreateMessage(event.ChannelID, discord.NewMessageCreateBuilder(). AddActionRow(discord.NewDangerButton("danger", "danger")). + SetMessageReferenceByID(event.Message.ID). Build(), ) } }, OnComponentInteraction: func(event *events.ComponentInteractionEvent) { - if event.ButtonInteractionData().CustomID == "danger" { + if event.ButtonInteractionData().CustomID() == "danger" { _ = event.CreateMessage(discord.NewMessageCreateBuilder().SetEphemeral(true).SetContent("Ey that was danger").Build()) } }, @@ -49,9 +50,9 @@ func main() { log.Fatal("error while building bot: ", err) } - defer disgo.Close(context.TODO()) + defer client.Close(context.TODO()) - if err = disgo.ConnectGateway(context.TODO()); err != nil { + if err = client.ConnectGateway(context.TODO()); err != nil { log.Fatal("error while connecting to gateway: ", err) } diff --git a/_examples/components/go.mod b/_examples/components/go.mod deleted file mode 100644 index b321a661..00000000 --- a/_examples/components/go.mod +++ /dev/null @@ -1,20 +0,0 @@ -module github.com/DisgoOrg/disgo/_examples/components - -go 1.17 - -replace github.com/DisgoOrg/disgo => ../../ - -require ( - github.com/DisgoOrg/disgo v0.5.6 - github.com/DisgoOrg/log v1.1.3 -) - -require ( - github.com/DisgoOrg/snowflake v1.0.4 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/google/go-cmp v0.5.7 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect -) diff --git a/_examples/components/go.sum b/_examples/components/go.sum deleted file mode 100644 index 94ac585e..00000000 --- a/_examples/components/go.sum +++ /dev/null @@ -1,26 +0,0 @@ -github.com/DisgoOrg/log v1.1.3 h1:UN0ZfmPZ7yhCCDQ7iVvIedvZ2zEexNS5Ek76GBuffOE= -github.com/DisgoOrg/log v1.1.3/go.mod h1:tSMofXaNhQNvzLRoL4tAiCG9yGY1ES5DLvduh7e9GRU= -github.com/DisgoOrg/snowflake v1.0.4 h1:hgeXSaXRDVdoNJ0rfHXyVsgxQMzctP346S5WXlBmoOU= -github.com/DisgoOrg/snowflake v1.0.4/go.mod h1:jIQVlVmElm2OGt6v52ITf/71ODaU09chUCflxt8+3yM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/guild_scheduled_events/example.go b/_examples/guild_scheduled_events/example.go index bfa179fa..41b32093 100644 --- a/_examples/guild_scheduled_events/example.go +++ b/_examples/guild_scheduled_events/example.go @@ -7,12 +7,13 @@ import ( "syscall" "time" - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/bot" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/cache" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/log" ) var ( @@ -24,15 +25,15 @@ func main() { log.SetLevel(log.LevelDebug) log.Info("starting example...") - disgo, err := bot.New(token, - bot.WithGatewayOpts( + client, err := disgo.New(token, + bot.WithGatewayConfigOpts( gateway.WithGatewayIntents(discord.GatewayIntentGuildScheduledEvents|discord.GatewayIntentGuilds|discord.GatewayIntentGuildMessages), ), - bot.WithCacheOpts( - core.WithCacheFlags(core.CacheFlagsAll), - core.WithMemberCachePolicy(core.MemberCachePolicyAll), + bot.WithCacheConfigOpts( + cache.WithCacheFlags(cache.FlagsAll), + cache.WithMemberCachePolicy(cache.MemberCachePolicyAll), ), - bot.WithMemberChunkingFilter(core.MemberChunkingFilterNone), + bot.WithMemberChunkingFilter(bot.MemberChunkingFilterNone), bot.WithEventListeners(&events.ListenerAdapter{ OnGuildScheduledEventCreate: func(event *events.GuildScheduledEventCreateEvent) { log.Infof("%T\n", event) @@ -54,7 +55,7 @@ func main() { if event.Message.Content != "test" { return } - gse, _ := event.Guild().CreateGuildScheduledEvent(discord.GuildScheduledEventCreate{ + gse, _ := event.Client().Rest().GuildScheduledEvents().CreateGuildScheduledEvent(*event.GuildID, discord.GuildScheduledEventCreate{ ChannelID: "885677988916641802", Name: "test", PrivacyLevel: discord.ScheduledEventPrivacyLevelGuildOnly, @@ -66,7 +67,7 @@ func main() { }) status := discord.ScheduledEventStatusActive - gse, _ = gse.Update(discord.GuildScheduledEventUpdate{ + gse, _ = event.Client().Rest().GuildScheduledEvents().UpdateGuildScheduledEvent(gse.GuildID, gse.ID, discord.GuildScheduledEventUpdate{ Status: &status, }) //_ = gse.AudioChannel().Connect() @@ -74,10 +75,10 @@ func main() { time.Sleep(time.Second * 10) status = discord.ScheduledEventStatusCompleted - gse, _ = gse.Update(discord.GuildScheduledEventUpdate{ + gse, _ = event.Client().Rest().GuildScheduledEvents().UpdateGuildScheduledEvent(gse.GuildID, gse.ID, discord.GuildScheduledEventUpdate{ Status: &status, }) - //_ = gse.Guild().Disconnect() + //_ = gse.Guilds().Disconnect() }, }), ) @@ -86,7 +87,7 @@ func main() { return } - if err = disgo.ConnectGateway(context.TODO()); err != nil { + if err = client.ConnectGateway(context.TODO()); err != nil { log.Fatal("error while connecting to discord: ", err) } diff --git a/_examples/guild_scheduled_events/go.mod b/_examples/guild_scheduled_events/go.mod deleted file mode 100644 index d56e8480..00000000 --- a/_examples/guild_scheduled_events/go.mod +++ /dev/null @@ -1,20 +0,0 @@ -module github.com/DisgoOrg/disgo/_examples/guild_scheduled_events - -go 1.17 - -replace github.com/DisgoOrg/disgo => ../../ - -require ( - github.com/DisgoOrg/disgo v0.5.6 - github.com/DisgoOrg/log v1.1.3 -) - -require ( - github.com/DisgoOrg/snowflake v1.0.4 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/google/go-cmp v0.5.7 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect -) diff --git a/_examples/guild_scheduled_events/go.sum b/_examples/guild_scheduled_events/go.sum deleted file mode 100644 index 94ac585e..00000000 --- a/_examples/guild_scheduled_events/go.sum +++ /dev/null @@ -1,26 +0,0 @@ -github.com/DisgoOrg/log v1.1.3 h1:UN0ZfmPZ7yhCCDQ7iVvIedvZ2zEexNS5Ek76GBuffOE= -github.com/DisgoOrg/log v1.1.3/go.mod h1:tSMofXaNhQNvzLRoL4tAiCG9yGY1ES5DLvduh7e9GRU= -github.com/DisgoOrg/snowflake v1.0.4 h1:hgeXSaXRDVdoNJ0rfHXyVsgxQMzctP346S5WXlBmoOU= -github.com/DisgoOrg/snowflake v1.0.4/go.mod h1:jIQVlVmElm2OGt6v52ITf/71ODaU09chUCflxt8+3yM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/message_collector/example.go b/_examples/message_collector/example.go index 938f38f4..59b0e390 100644 --- a/_examples/message_collector/example.go +++ b/_examples/message_collector/example.go @@ -8,13 +8,13 @@ import ( "syscall" "time" - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/bot" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/disgo/info" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/bot" + + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/log" ) var ( @@ -24,10 +24,10 @@ var ( func main() { log.SetLevel(log.LevelDebug) log.Info("starting example...") - log.Infof("disgo version: %s", info.Version) + log.Infof("disgo version: %s", disgo.Version) - disgo, err := bot.New(token, - bot.WithGatewayOpts(gateway.WithGatewayIntents(discord.GatewayIntentGuilds, discord.GatewayIntentGuildMessages, discord.GatewayIntentDirectMessages)), + client, err := disgo.New(token, + bot.WithGatewayConfigOpts(gateway.WithGatewayIntents(discord.GatewayIntentGuilds, discord.GatewayIntentGuildMessages, discord.GatewayIntentDirectMessages)), bot.WithEventListeners(&events.ListenerAdapter{ OnMessageCreate: onMessageCreate, }), @@ -36,9 +36,9 @@ func main() { log.Fatal("error while building bot: ", err) } - defer disgo.Close(context.TODO()) + defer client.Close(context.TODO()) - if err = disgo.ConnectGateway(context.TODO()); err != nil { + if err = client.ConnectGateway(context.TODO()); err != nil { log.Fatal("error while connecting to gateway: ", err) } @@ -54,8 +54,8 @@ func onMessageCreate(event *events.MessageCreateEvent) { } if event.Message.Content == "start" { go func() { - ch, cls := event.Bot().Collectors.NewMessageCollector(func(message *core.Message) bool { - return message.ChannelID == event.ChannelID && message.Author.ID == event.Message.Author.ID && message.Content != "" + ch, cls := bot.NewEventCollector(event.Client(), func(event *events.MessageCreateEvent) bool { + return event.ChannelID == event.ChannelID && event.Message.Author.ID == event.Message.Author.ID && event.Message.Content != "" }) i := 1 str := ">>> " @@ -64,15 +64,15 @@ func onMessageCreate(event *events.MessageCreateEvent) { for { select { case <-ctx.Done(): - _, _ = event.Channel().CreateMessage(discord.NewMessageCreateBuilder().SetContent("cancelled").Build()) + _, _ = event.Client().Rest().Channels().CreateMessage(event.ChannelID, discord.NewMessageCreateBuilder().SetContent("cancelled").Build()) return - case message := <-ch: - str += strconv.Itoa(i) + ". " + message.Content + "\n\n" + case messageEvent := <-ch: + str += strconv.Itoa(i) + ". " + messageEvent.Message.Content + "\n\n" if i == 3 { cls() - _, _ = message.Channel().CreateMessage(discord.NewMessageCreateBuilder().SetContent(str).Build()) + _, _ = event.Client().Rest().Channels().CreateMessage(messageEvent.ChannelID, discord.NewMessageCreateBuilder().SetContent(str).Build()) } i++ } diff --git a/_examples/message_collector/go.mod b/_examples/message_collector/go.mod deleted file mode 100644 index 58925f50..00000000 --- a/_examples/message_collector/go.mod +++ /dev/null @@ -1,20 +0,0 @@ -module github.com/DisgoOrg/disgo/_examples/message_collector - -go 1.17 - -replace github.com/DisgoOrg/disgo => ../../ - -require ( - github.com/DisgoOrg/disgo v0.5.6 - github.com/DisgoOrg/log v1.1.3 -) - -require ( - github.com/DisgoOrg/snowflake v1.0.4 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/google/go-cmp v0.5.7 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect -) diff --git a/_examples/message_collector/go.sum b/_examples/message_collector/go.sum deleted file mode 100644 index 94ac585e..00000000 --- a/_examples/message_collector/go.sum +++ /dev/null @@ -1,26 +0,0 @@ -github.com/DisgoOrg/log v1.1.3 h1:UN0ZfmPZ7yhCCDQ7iVvIedvZ2zEexNS5Ek76GBuffOE= -github.com/DisgoOrg/log v1.1.3/go.mod h1:tSMofXaNhQNvzLRoL4tAiCG9yGY1ES5DLvduh7e9GRU= -github.com/DisgoOrg/snowflake v1.0.4 h1:hgeXSaXRDVdoNJ0rfHXyVsgxQMzctP346S5WXlBmoOU= -github.com/DisgoOrg/snowflake v1.0.4/go.mod h1:jIQVlVmElm2OGt6v52ITf/71ODaU09chUCflxt8+3yM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/oauth2/example.go b/_examples/oauth2/example.go index cdfbb17b..13e8c881 100644 --- a/_examples/oauth2/example.go +++ b/_examples/oauth2/example.go @@ -7,13 +7,13 @@ import ( "os" "time" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/info" - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/disgo/oauth2" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/log" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/disgo/oauth2" + "github.com/disgoorg/disgo/rest" + "github.com/disgoorg/log" + "github.com/disgoorg/snowflake" ) var ( @@ -23,7 +23,7 @@ var ( baseURL = os.Getenv("base_url") logger = log.Default() httpClient = http.DefaultClient - client *oauth2.Client + client oauth2.Client ) func main() { @@ -31,7 +31,7 @@ func main() { logger.SetLevel(log.LevelDebug) logger.Info("starting example...") - logger.Infof("disgo %s", info.Version) + logger.Infof("disgo %s", disgo.Version) client = oauth2.New(clientID, clientSecret, oauth2.WithLogger(logger), oauth2.WithRestClientConfigOpts(rest.WithHTTPClient(httpClient))) @@ -46,7 +46,7 @@ func handleRoot(w http.ResponseWriter, r *http.Request) { var body string cookie, err := r.Cookie("token") if err == nil { - session := client.SessionController.GetSession(cookie.Value) + session := client.SessionController().GetSession(cookie.Value) if session != nil { var user *discord.OAuth2User user, err = client.GetUser(session) diff --git a/_examples/oauth2/go.mod b/_examples/oauth2/go.mod deleted file mode 100644 index 4cda0108..00000000 --- a/_examples/oauth2/go.mod +++ /dev/null @@ -1,19 +0,0 @@ -module github.com/DisgoOrg/disgo/_examples/oauth2 - -go 1.17 - -replace github.com/DisgoOrg/disgo => ../../ - -require ( - github.com/DisgoOrg/disgo v0.5.6 - github.com/DisgoOrg/log v1.1.3 - github.com/DisgoOrg/snowflake v1.0.4 -) - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect -) diff --git a/_examples/oauth2/go.sum b/_examples/oauth2/go.sum deleted file mode 100644 index 51a80fc3..00000000 --- a/_examples/oauth2/go.sum +++ /dev/null @@ -1,24 +0,0 @@ -github.com/DisgoOrg/log v1.1.3 h1:UN0ZfmPZ7yhCCDQ7iVvIedvZ2zEexNS5Ek76GBuffOE= -github.com/DisgoOrg/log v1.1.3/go.mod h1:tSMofXaNhQNvzLRoL4tAiCG9yGY1ES5DLvduh7e9GRU= -github.com/DisgoOrg/snowflake v1.0.4 h1:hgeXSaXRDVdoNJ0rfHXyVsgxQMzctP346S5WXlBmoOU= -github.com/DisgoOrg/snowflake v1.0.4/go.mod h1:jIQVlVmElm2OGt6v52ITf/71ODaU09chUCflxt8+3yM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/ping_pong/example.go b/_examples/ping_pong/example.go index cc1f2053..603cfa3f 100644 --- a/_examples/ping_pong/example.go +++ b/_examples/ping_pong/example.go @@ -6,25 +6,27 @@ import ( "os/signal" "syscall" - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/bot" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/cache" + + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/log" ) func main() { log.SetLevel(log.LevelDebug) log.SetFlags(log.LstdFlags | log.Lshortfile) - disgo, err := bot.New(os.Getenv("token"), - bot.WithGatewayOpts( + client, err := disgo.New(os.Getenv("token"), + bot.WithGatewayConfigOpts( gateway.WithGatewayIntents( discord.GatewayIntentsNone, ), ), - bot.WithCacheOpts(core.WithCacheFlags(core.CacheFlagsDefault)), + bot.WithCacheConfigOpts(cache.WithCacheFlags(cache.FlagsDefault)), bot.WithEventListeners(&events.ListenerAdapter{ OnMessageCreate: onMessageCreate, }), @@ -33,9 +35,9 @@ func main() { log.Fatal("error while building disgo: ", err) } - defer disgo.Close(context.TODO()) + defer client.Close(context.TODO()) - if err = disgo.ConnectGateway(context.TODO()); err != nil { + if err = client.ConnectGateway(context.TODO()); err != nil { log.Fatal("errors while connecting to gateway: ", err) } @@ -53,6 +55,6 @@ func onMessageCreate(event *events.MessageCreateEvent) { message = "ping" } if message != "" { - _, _ = event.Message.Reply(discord.NewMessageCreateBuilder().SetContent(message).Build()) + _, _ = event.Client().Rest().Channels().CreateMessage(event.ChannelID, discord.NewMessageCreateBuilder().SetContent(message).Build()) } } diff --git a/_examples/ping_pong/go.mod b/_examples/ping_pong/go.mod deleted file mode 100644 index 1626ace0..00000000 --- a/_examples/ping_pong/go.mod +++ /dev/null @@ -1,20 +0,0 @@ -module github.com/DisgoOrg/disgo/_examples/ping_pong - -go 1.17 - -replace github.com/DisgoOrg/disgo => ../../ - -require ( - github.com/DisgoOrg/disgo v0.5.6 - github.com/DisgoOrg/log v1.1.3 -) - -require ( - github.com/DisgoOrg/snowflake v1.0.4 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/google/go-cmp v0.5.7 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect -) diff --git a/_examples/ping_pong/go.sum b/_examples/ping_pong/go.sum deleted file mode 100644 index 94ac585e..00000000 --- a/_examples/ping_pong/go.sum +++ /dev/null @@ -1,26 +0,0 @@ -github.com/DisgoOrg/log v1.1.3 h1:UN0ZfmPZ7yhCCDQ7iVvIedvZ2zEexNS5Ek76GBuffOE= -github.com/DisgoOrg/log v1.1.3/go.mod h1:tSMofXaNhQNvzLRoL4tAiCG9yGY1ES5DLvduh7e9GRU= -github.com/DisgoOrg/snowflake v1.0.4 h1:hgeXSaXRDVdoNJ0rfHXyVsgxQMzctP346S5WXlBmoOU= -github.com/DisgoOrg/snowflake v1.0.4/go.mod h1:jIQVlVmElm2OGt6v52ITf/71ODaU09chUCflxt8+3yM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/sharding/example.go b/_examples/sharding/example.go index 41f968e4..32329e58 100644 --- a/_examples/sharding/example.go +++ b/_examples/sharding/example.go @@ -6,14 +6,15 @@ import ( "os/signal" "syscall" - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/bot" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/disgo/gateway/sharding" - "github.com/DisgoOrg/disgo/info" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/cache" + "github.com/disgoorg/disgo/sharding" + + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/log" ) var ( @@ -24,10 +25,10 @@ func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) log.SetLevel(log.LevelInfo) log.Info("starting example...") - log.Info("disgo version: ", info.Version) + log.Info("disgo version: ", disgo.Version) - disgo, err := bot.New(token, - bot.WithShardManagerOpts( + client, err := disgo.New(token, + bot.WithShardManagerConfigOpts( sharding.WithShards(0, 1, 2), sharding.WithShardCount(3), sharding.WithGatewayConfigOpts( @@ -35,7 +36,7 @@ func main() { gateway.WithCompress(true), ), ), - bot.WithCacheOpts(core.WithCacheFlags(core.CacheFlagsDefault)), + bot.WithCacheConfigOpts(cache.WithCacheFlags(cache.FlagsDefault)), bot.WithEventListeners(&events.ListenerAdapter{ OnMessageCreate: onMessageCreate, OnGuildReady: func(event *events.GuildReadyEvent) { @@ -50,9 +51,9 @@ func main() { log.Fatalf("error while building disgo: %s", err) } - defer disgo.Close(context.TODO()) + defer client.Close(context.TODO()) - if err = disgo.ConnectShardManager(context.TODO()); err != nil { + if err = client.ConnectShardManager(context.TODO()); err != nil { log.Fatal("error while connecting to gateway: ", err) } @@ -66,5 +67,5 @@ func onMessageCreate(event *events.MessageCreateEvent) { if event.Message.Author.BotUser { return } - _, _ = event.Message.Reply(discord.NewMessageCreateBuilder().SetContent(event.Message.Content).Build()) + _, _ = event.Client().Rest().Channels().CreateMessage(event.ChannelID, discord.NewMessageCreateBuilder().SetContent(event.Message.Content).Build()) } diff --git a/_examples/sharding/go.mod b/_examples/sharding/go.mod deleted file mode 100644 index 42cca5dd..00000000 --- a/_examples/sharding/go.mod +++ /dev/null @@ -1,20 +0,0 @@ -module github.com/DisgoOrg/disgo/_examples/sharding - -go 1.17 - -replace github.com/DisgoOrg/disgo => ../../ - -require ( - github.com/DisgoOrg/disgo v0.5.6 - github.com/DisgoOrg/log v1.1.3 -) - -require ( - github.com/DisgoOrg/snowflake v1.0.4 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/google/go-cmp v0.5.7 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect -) diff --git a/_examples/sharding/go.sum b/_examples/sharding/go.sum deleted file mode 100644 index 94ac585e..00000000 --- a/_examples/sharding/go.sum +++ /dev/null @@ -1,26 +0,0 @@ -github.com/DisgoOrg/log v1.1.3 h1:UN0ZfmPZ7yhCCDQ7iVvIedvZ2zEexNS5Ek76GBuffOE= -github.com/DisgoOrg/log v1.1.3/go.mod h1:tSMofXaNhQNvzLRoL4tAiCG9yGY1ES5DLvduh7e9GRU= -github.com/DisgoOrg/snowflake v1.0.4 h1:hgeXSaXRDVdoNJ0rfHXyVsgxQMzctP346S5WXlBmoOU= -github.com/DisgoOrg/snowflake v1.0.4/go.mod h1:jIQVlVmElm2OGt6v52ITf/71ODaU09chUCflxt8+3yM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/test/commands.go b/_examples/test/commands.go index d503f874..42acb6e4 100644 --- a/_examples/test/commands.go +++ b/_examples/test/commands.go @@ -1,9 +1,9 @@ package main import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/log" ) var commands = []discord.ApplicationCommandCreate{ @@ -36,8 +36,8 @@ var commands = []discord.ApplicationCommandCreate{ }, } -func registerCommands(bot *core.Bot) { - if _, err := bot.SetGuildCommands(guildID, commands); err != nil { +func registerCommands(client bot.Client) { + if _, err := client.Rest().Applications().SetGuildCommands(client.ApplicationID(), guildID, commands); err != nil { log.Fatalf("error while registering guild commands: %s", err) } } diff --git a/_examples/test/examplebot.go b/_examples/test/examplebot.go index b8346703..ed3f4772 100644 --- a/_examples/test/examplebot.go +++ b/_examples/test/examplebot.go @@ -7,13 +7,13 @@ import ( "os/signal" "syscall" - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/bot" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/disgo/info" - "github.com/DisgoOrg/log" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/cache" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/log" + "github.com/disgoorg/snowflake" ) var ( @@ -28,19 +28,19 @@ func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) log.SetLevel(log.LevelDebug) log.Info("starting example...") - log.Infof("bot version: %s", info.Version) + log.Infof("bot version: %s", disgo.Version) - disgo, err := bot.New(token, + client, err := disgo.New(token, //bot.WithRawEventsEnabled(), - bot.WithGatewayOpts( - gateway.WithGatewayIntents(discord.GatewayIntentsNonPrivileged), - gateway.WithPresence(core.NewListeningPresence("your bullshit", discord.OnlineStatusOnline, false)), + bot.WithGatewayConfigOpts( + gateway.WithGatewayIntents(discord.GatewayIntentsNonPrivileged, discord.GatewayIntentMessageContent), + gateway.WithPresence(discord.NewListeningPresence("your bullshit", discord.OnlineStatusOnline, false)), ), - bot.WithCacheOpts( - core.WithCacheFlags(core.CacheFlagsAll), - core.WithMemberCachePolicy(core.MemberCachePolicyAll), + bot.WithCacheConfigOpts( + cache.WithCacheFlags(cache.FlagsAll), + cache.WithMemberCachePolicy(cache.MemberCachePolicyAll), ), - bot.WithMemberChunkingFilter(core.MemberChunkingFilterNone), + bot.WithMemberChunkingFilter(bot.MemberChunkingFilterNone), bot.WithEventListeners(listener), ) if err != nil { @@ -48,13 +48,13 @@ func main() { return } - registerCommands(disgo) + registerCommands(client) - if err = disgo.ConnectGateway(context.TODO()); err != nil { + if err = client.ConnectGateway(context.TODO()); err != nil { log.Fatal("error while connecting to discord: ", err) } - defer disgo.Close(context.TODO()) + defer client.Close(context.TODO()) log.Info("ExampleBot is now running. Press CTRL-C to exit.") s := make(chan os.Signal, 1) diff --git a/_examples/test/go.mod b/_examples/test/go.mod deleted file mode 100644 index d1d2c42d..00000000 --- a/_examples/test/go.mod +++ /dev/null @@ -1,20 +0,0 @@ -module github.com/DisgoOrg/disgo/_examples/test - -go 1.17 - -replace github.com/DisgoOrg/disgo => ../../ - -require ( - github.com/DisgoOrg/disgo v0.5.6 - github.com/DisgoOrg/log v1.1.3 - github.com/DisgoOrg/snowflake v1.0.4 -) - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/google/go-cmp v0.5.7 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect -) diff --git a/_examples/test/go.sum b/_examples/test/go.sum deleted file mode 100644 index 94ac585e..00000000 --- a/_examples/test/go.sum +++ /dev/null @@ -1,26 +0,0 @@ -github.com/DisgoOrg/log v1.1.3 h1:UN0ZfmPZ7yhCCDQ7iVvIedvZ2zEexNS5Ek76GBuffOE= -github.com/DisgoOrg/log v1.1.3/go.mod h1:tSMofXaNhQNvzLRoL4tAiCG9yGY1ES5DLvduh7e9GRU= -github.com/DisgoOrg/snowflake v1.0.4 h1:hgeXSaXRDVdoNJ0rfHXyVsgxQMzctP346S5WXlBmoOU= -github.com/DisgoOrg/snowflake v1.0.4/go.mod h1:jIQVlVmElm2OGt6v52ITf/71ODaU09chUCflxt8+3yM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/test/listeners.go b/_examples/test/listeners.go index 21ab086d..0b34cd81 100644 --- a/_examples/test/listeners.go +++ b/_examples/test/listeners.go @@ -5,10 +5,10 @@ import ( "strings" "time" - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/log" ) var listener = &events.ListenerAdapter{ @@ -21,19 +21,18 @@ var listener = &events.ListenerAdapter{ func modalListener(event *events.ModalSubmitInteractionEvent) { switch event.Data.CustomID { case "test1": - value := *event.Data.Components.Text("test_input") - _ = event.CreateMessage(discord.MessageCreate{Content: value}) + _ = event.CreateMessage(discord.MessageCreate{Content: event.Data.Text("test_input")}) case "test2": - value := *event.Data.Components.Text("test_input") + value := event.Data.Text("test_input") _ = event.DeferCreateMessage(false) go func() { time.Sleep(time.Second * 5) - _, _ = event.UpdateOriginalMessage(discord.MessageUpdate{Content: &value}) + _, _ = event.Client().Rest().Interactions().UpdateInteractionResponse(event.ApplicationID(), event.Token(), discord.MessageUpdate{Content: &value}) }() case "test3": - value := *event.Data.Components.Text("test_input") + value := event.Data.Text("test_input") _ = event.UpdateMessage(discord.MessageUpdate{Content: &value}) case "test4": @@ -43,8 +42,8 @@ func modalListener(event *events.ModalSubmitInteractionEvent) { func componentListener(event *events.ComponentInteractionEvent) { switch data := event.Data.(type) { - case core.ButtonInteractionData: - ids := strings.Split(data.CustomID.String(), ":") + case discord.ButtonInteractionData: + ids := strings.Split(data.CustomID().String(), ":") switch ids[0] { case "modal": _ = event.CreateModal(discord.ModalCreate{ @@ -66,7 +65,7 @@ func componentListener(event *events.ComponentInteractionEvent) { case "test1": _ = event.CreateMessage(discord.NewMessageCreateBuilder(). - SetContent(data.CustomID.String()). + SetContent(data.CustomID().String()). Build(), ) @@ -78,18 +77,18 @@ func componentListener(event *events.ComponentInteractionEvent) { case "test4": _ = event.UpdateMessage(discord.NewMessageUpdateBuilder(). - SetContent(data.CustomID.String()). + SetContent(data.CustomID().String()). Build(), ) } - case core.SelectMenuInteractionData: - switch data.CustomID { + case discord.SelectMenuInteractionData: + switch data.CustomID() { case "test3": if err := event.DeferUpdateMessage(); err != nil { log.Errorf("error sending interaction response: %s", err) } - _, _ = event.CreateFollowupMessage(discord.NewMessageCreateBuilder(). + _, _ = event.Client().Rest().Interactions().CreateFollowupMessage(event.ApplicationID(), event.Token(), discord.NewMessageCreateBuilder(). SetEphemeral(true). SetContentf("selected options: %s", data.Values). Build(), @@ -100,20 +99,20 @@ func componentListener(event *events.ComponentInteractionEvent) { func applicationCommandListener(event *events.ApplicationCommandInteractionEvent) { data := event.SlashCommandInteractionData() - switch data.CommandName { + switch data.CommandName() { case "locale": err := event.CreateMessage(discord.NewMessageCreateBuilder(). - SetContentf("Guild Locale: %s\nLocale: %s", event.GuildLocale, event.Locale). + SetContentf("Guild Locale: %s\nLocale: %s", event.GuildLocale(), event.Locale()). Build(), ) if err != nil { - event.Bot().Logger.Error("error on sending response: ", err) + event.Client().Logger().Error("error on sending response: ", err) } case "say": _ = event.CreateMessage(discord.NewMessageCreateBuilder(). - SetContent(*data.Options.String("message")). - SetEphemeral(*data.Options.Bool("ephemeral")). + SetContent(data.String("message")). + SetEphemeral(data.Bool("ephemeral")). ClearAllowedMentions(). Build(), ) @@ -139,23 +138,40 @@ func messageListener(event *events.GuildMessageCreateEvent) { switch event.Message.Content { case "gopher": - _, _ = event.Message.Reply(discord.NewMessageCreateBuilder().SetContent("gopher").AddFile("gopher.png", bytes.NewBuffer(gopher)).AddFile("gopher.png", bytes.NewBuffer(gopher)).Build()) + message, err := event.Client().Rest().Channels().CreateMessage(event.ChannelID, discord.NewMessageCreateBuilder(). + SetContent("gopher"). + AddFile("gopher.png", "this is a gopher", bytes.NewBuffer(gopher)). + AddFile("gopher.png", "", bytes.NewBuffer(gopher)). + Build(), + ) + if err != nil { + event.Client().Logger().Error("error on sending response: ", err) + } + time.Sleep(1 * time.Second) + _, err = event.Client().Rest().Channels().UpdateMessage(event.ChannelID, message.ID, discord.NewMessageUpdateBuilder(). + SetContent("edited gopher"). + RetainAttachments(message.Attachments[0]). + Build(), + ) + if err != nil { + event.Client().Logger().Error("error on updating response: ", err) + } case "panic": panic("panic in the disco") case "party": - _, _ = event.Message.Reply(discord.NewMessageCreateBuilder().AddStickers("886756806888673321").SetAllowedMentions(&discord.AllowedMentions{RepliedUser: false}).Build()) + _, _ = event.Client().Rest().Channels().CreateMessage(event.ChannelID, discord.NewMessageCreateBuilder().AddStickers("886756806888673321").SetAllowedMentions(&discord.AllowedMentions{RepliedUser: false}).Build()) case "ping": - _, _ = event.Message.Reply(discord.NewMessageCreateBuilder().SetContent("pong").SetAllowedMentions(&discord.AllowedMentions{RepliedUser: false}).Build()) + _, _ = event.Client().Rest().Channels().CreateMessage(event.ChannelID, discord.NewMessageCreateBuilder().SetContent("pong").SetAllowedMentions(&discord.AllowedMentions{RepliedUser: false}).Build()) case "pong": - _, _ = event.Message.Reply(discord.NewMessageCreateBuilder().SetContent("ping").SetAllowedMentions(&discord.AllowedMentions{RepliedUser: false}).Build()) + _, _ = event.Client().Rest().Channels().CreateMessage(event.ChannelID, discord.NewMessageCreateBuilder().SetContent("ping").SetAllowedMentions(&discord.AllowedMentions{RepliedUser: false}).Build()) case "test": go func() { - message, err := event.Channel().CreateMessage(discord.NewMessageCreateBuilder().SetContent("test").Build()) + message, err := event.Client().Rest().Channels().CreateMessage(event.ChannelID, discord.NewMessageCreateBuilder().SetContent("test").Build()) if err != nil { log.Errorf("error while sending file: %s", err) return @@ -163,32 +179,32 @@ func messageListener(event *events.GuildMessageCreateEvent) { time.Sleep(time.Second * 2) embed := discord.NewEmbedBuilder().SetDescription("edit").Build() - message, _ = message.Update(discord.NewMessageUpdateBuilder().SetContent("edit").SetEmbeds(embed, embed).Build()) + message, _ = event.Client().Rest().Channels().UpdateMessage(event.ChannelID, message.ID, discord.NewMessageUpdateBuilder().SetContent("edit").SetEmbeds(embed, embed).Build()) time.Sleep(time.Second * 2) - _, _ = message.Update(discord.NewMessageUpdateBuilder().SetContent("").SetEmbeds(discord.NewEmbedBuilder().SetDescription("edit2").Build()).Build()) + _, _ = event.Client().Rest().Channels().UpdateMessage(event.ChannelID, message.ID, discord.NewMessageUpdateBuilder().SetContent("").SetEmbeds(discord.NewEmbedBuilder().SetDescription("edit2").Build()).Build()) }() case "dm": go func() { - channel, err := event.Message.Author.OpenDMChannel() + channel, err := event.Client().Rest().Users().CreateDMChannel(event.Message.Author.ID) if err != nil { - _ = event.Message.AddReaction("❌") + _ = event.Client().Rest().Channels().AddReaction(channel.ID(), event.MessageID, "❌") return } - _, err = channel.CreateMessage(discord.NewMessageCreateBuilder().SetContent("helo").Build()) + _, err = event.Client().Rest().Channels().CreateMessage(channel.ID(), discord.NewMessageCreateBuilder().SetContent("helo").Build()) if err == nil { - _ = event.Message.AddReaction("✅") + _ = event.Client().Rest().Channels().AddReaction(channel.ID(), event.MessageID, "✅") } else { - _ = event.Message.AddReaction("❌") + _ = event.Client().Rest().Channels().AddReaction(channel.ID(), event.MessageID, "❌") } }() case "repeat": go func() { - ch, cls := event.Bot().Collectors.NewMessageCollector(func(m *core.Message) bool { - return !m.Author.BotUser && m.ChannelID == event.ChannelID + ch, cls := bot.NewEventCollector(event.Client(), func(event *events.MessageCreateEvent) bool { + return !event.Message.Author.BotUser && event.ChannelID == event.ChannelID }) var count = 0 @@ -198,14 +214,12 @@ func messageListener(event *events.GuildMessageCreateEvent) { cls() return } - - msg, ok := <-ch + messageEvent, ok := <-ch if !ok { return } - - _, _ = msg.Reply(discord.NewMessageCreateBuilder().SetContentf("Content: %s, Count: %v", msg.Content, count).Build()) + _, _ = messageEvent.Client().Rest().Channels().CreateMessage(event.ChannelID, discord.NewMessageCreateBuilder().SetContentf("Content: %s, Count: %v", messageEvent.Message.Content, count).SetMessageReferenceByID(event.MessageID).Build()) } }() diff --git a/_examples/threads/example.go b/_examples/threads/example.go index dafe3904..2006f257 100644 --- a/_examples/threads/example.go +++ b/_examples/threads/example.go @@ -6,13 +6,14 @@ import ( "os/signal" "syscall" - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/bot" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/disgo/info" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/cache" + + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/log" ) var ( @@ -24,21 +25,23 @@ func main() { log.SetFlags(log.LstdFlags | log.Lshortfile) log.SetLevel(log.LevelInfo) log.Info("starting example...") - log.Infof("bot version: %s", info.Version) + log.Infof("bot version: %s", disgo.Version) - disgo, err := bot.New(token, - bot.WithGatewayOpts( + client, err := disgo.New(token, + bot.WithGatewayConfigOpts( gateway.WithGatewayIntents(discord.GatewayIntentsAll), ), - bot.WithCacheOpts( - core.WithCacheFlags(core.CacheFlagsAll), - core.WithMemberCachePolicy(core.MemberCachePolicyAll), + bot.WithCacheConfigOpts( + cache.WithCacheFlags(cache.FlagsAll), + cache.WithMemberCachePolicy(cache.MemberCachePolicyAll), ), - bot.WithMemberChunkingFilter(core.MemberChunkingFilterAll), + bot.WithMemberChunkingFilter(bot.MemberChunkingFilterAll), bot.WithEventListeners(&events.ListenerAdapter{ OnMessageCreate: func(event *events.MessageCreateEvent) { - if _, ok := event.Channel().(core.GuildThread); ok { - println("MessageCreateEvent") + if channel, ok := event.Channel(); ok { + if _, ok = channel.(discord.GuildThread); ok { + println("MessageCreateEvent") + } } }, OnThreadCreate: func(event *events.ThreadCreateEvent) { @@ -72,9 +75,9 @@ func main() { return } - defer disgo.Close(context.TODO()) + defer client.Close(context.TODO()) - if err = disgo.ConnectGateway(context.TODO()); err != nil { + if err = client.ConnectGateway(context.TODO()); err != nil { log.Fatal("error while connecting to discord: ", err) } diff --git a/_examples/threads/go.mod b/_examples/threads/go.mod deleted file mode 100644 index 9ad89392..00000000 --- a/_examples/threads/go.mod +++ /dev/null @@ -1,20 +0,0 @@ -module github.com/DisgoOrg/disgo/_examples/threads - -go 1.17 - -replace github.com/DisgoOrg/disgo => ../../ - -require ( - github.com/DisgoOrg/disgo v0.5.6 - github.com/DisgoOrg/log v1.1.3 -) - -require ( - github.com/DisgoOrg/snowflake v1.0.4 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/google/go-cmp v0.5.7 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect -) diff --git a/_examples/threads/go.sum b/_examples/threads/go.sum deleted file mode 100644 index 94ac585e..00000000 --- a/_examples/threads/go.sum +++ /dev/null @@ -1,26 +0,0 @@ -github.com/DisgoOrg/log v1.1.3 h1:UN0ZfmPZ7yhCCDQ7iVvIedvZ2zEexNS5Ek76GBuffOE= -github.com/DisgoOrg/log v1.1.3/go.mod h1:tSMofXaNhQNvzLRoL4tAiCG9yGY1ES5DLvduh7e9GRU= -github.com/DisgoOrg/snowflake v1.0.4 h1:hgeXSaXRDVdoNJ0rfHXyVsgxQMzctP346S5WXlBmoOU= -github.com/DisgoOrg/snowflake v1.0.4/go.mod h1:jIQVlVmElm2OGt6v52ITf/71ODaU09chUCflxt8+3yM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/_examples/webhook/example.go b/_examples/webhook/example.go index 8219dcf1..92844a10 100644 --- a/_examples/webhook/example.go +++ b/_examples/webhook/example.go @@ -6,12 +6,12 @@ import ( "sync" "time" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/info" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/disgo/webhook" - "github.com/DisgoOrg/log" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest" + "github.com/disgoorg/disgo/webhook" + "github.com/disgoorg/log" + "github.com/disgoorg/snowflake" ) var ( @@ -22,7 +22,7 @@ var ( func main() { log.SetLevel(log.LevelDebug) log.Info("starting webhook example...") - log.Info("disgo version: ", info.Version) + log.Info("disgo version: ", disgo.Version) // construct new webhook client client := webhook.NewClient(webhookID, webhookToken) @@ -43,7 +43,7 @@ func main() { } // send(s) a message to the webhook -func send(wg *sync.WaitGroup, client *webhook.Client, i int) { +func send(wg *sync.WaitGroup, client webhook.Client, i int) { defer wg.Done() if _, err := client.CreateMessage(discord.NewWebhookMessageCreateBuilder(). diff --git a/_examples/webhook/go.mod b/_examples/webhook/go.mod deleted file mode 100644 index c086d6d4..00000000 --- a/_examples/webhook/go.mod +++ /dev/null @@ -1,19 +0,0 @@ -module github.com/DisgoOrg/disgo/_examples/webhook - -go 1.17 - -replace github.com/DisgoOrg/disgo => ../../ - -require ( - github.com/DisgoOrg/disgo v0.5.6 - github.com/DisgoOrg/log v1.1.3 - github.com/DisgoOrg/snowflake v1.0.4 -) - -require ( - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/gorilla/websocket v1.5.0 // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b // indirect - gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect -) diff --git a/_examples/webhook/go.sum b/_examples/webhook/go.sum deleted file mode 100644 index 51a80fc3..00000000 --- a/_examples/webhook/go.sum +++ /dev/null @@ -1,24 +0,0 @@ -github.com/DisgoOrg/log v1.1.3 h1:UN0ZfmPZ7yhCCDQ7iVvIedvZ2zEexNS5Ek76GBuffOE= -github.com/DisgoOrg/log v1.1.3/go.mod h1:tSMofXaNhQNvzLRoL4tAiCG9yGY1ES5DLvduh7e9GRU= -github.com/DisgoOrg/snowflake v1.0.4 h1:hgeXSaXRDVdoNJ0rfHXyVsgxQMzctP346S5WXlBmoOU= -github.com/DisgoOrg/snowflake v1.0.4/go.mod h1:jIQVlVmElm2OGt6v52ITf/71ODaU09chUCflxt8+3yM= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= -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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE= -github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3zsXKdjjAiUhB5CjuKib9KJGCaLvZwtxGC8U0s= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/bot/bot.go b/bot/bot.go new file mode 100644 index 00000000..a830b970 --- /dev/null +++ b/bot/bot.go @@ -0,0 +1,291 @@ +package bot + +import ( + "context" + + "github.com/disgoorg/disgo/cache" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/disgo/httpserver" + "github.com/disgoorg/disgo/rest" + "github.com/disgoorg/disgo/sharding" + "github.com/disgoorg/log" + "github.com/disgoorg/snowflake" +) + +var _ Client = (*clientImpl)(nil) + +type Client interface { + Logger() log.Logger + Close(ctx context.Context) + + Token() string + ApplicationID() snowflake.Snowflake + ID() snowflake.Snowflake + SelfUser() *discord.OAuth2User + SetSelfUser(user discord.OAuth2User) + SelfMember(guildID snowflake.Snowflake) *discord.Member + Caches() cache.Caches + Rest() rest.Rest + HandleReadyEvent(event discord.GatewayEventReady) + + AddEventListeners(listeners ...EventListener) + RemoveEventListeners(listeners ...EventListener) + EventManager() EventManager + + ConnectGateway(ctx context.Context) error + Gateway() gateway.Gateway + HasGateway() bool + + ConnectShardManager(ctx context.Context) error + ShardManager() sharding.ShardManager + HasShardManager() bool + Shard(guildID snowflake.Snowflake) (gateway.Gateway, error) + + Connect(ctx context.Context, guildID snowflake.Snowflake, channelID snowflake.Snowflake) error + Disconnect(ctx context.Context, guildID snowflake.Snowflake) error + + RequestMembers(ctx context.Context, guildID snowflake.Snowflake, presence bool, nonce string, userIDs ...snowflake.Snowflake) error + RequestMembersWithQuery(ctx context.Context, guildID snowflake.Snowflake, presence bool, nonce string, query string, limit int) error + + SetPresence(ctx context.Context, presenceUpdate discord.GatewayMessageDataPresenceUpdate) error + SetPresenceForShard(ctx context.Context, shardId int, presenceUpdate discord.GatewayMessageDataPresenceUpdate) error + + MemberChunkingManager() MemberChunkingManager + + StartHTTPServer() error + HTTPServer() httpserver.Server + HasHTTPServer() bool +} + +// clientImpl is the main discord client +type clientImpl struct { + token string + applicationID snowflake.Snowflake + clientID snowflake.Snowflake + selfUser *discord.OAuth2User + + logger log.Logger + + restServices rest.Rest + + eventManager EventManager + + shardManager sharding.ShardManager + gateway gateway.Gateway + + httpServer httpserver.Server + + caches cache.Caches + + memberChunkingManager MemberChunkingManager +} + +func (c *clientImpl) Logger() log.Logger { + return c.logger +} + +// Close will clean up all disgo internals and close the discord connection safely +func (c *clientImpl) Close(ctx context.Context) { + if c.restServices != nil { + c.restServices.Close(ctx) + } + if c.gateway != nil { + c.gateway.Close(ctx) + } + if c.shardManager != nil { + c.shardManager.Close(ctx) + } + if c.httpServer != nil { + c.httpServer.Close(ctx) + } +} + +func (c *clientImpl) Token() string { + return c.token +} +func (c *clientImpl) ApplicationID() snowflake.Snowflake { + return c.applicationID +} +func (c *clientImpl) ID() snowflake.Snowflake { + return c.clientID +} +func (c *clientImpl) SelfUser() *discord.OAuth2User { + return c.selfUser +} + +func (c *clientImpl) SetSelfUser(user discord.OAuth2User) { + c.selfUser = &user +} + +// SelfMember returns a core.OAuth2User for the client, if available +func (c *clientImpl) SelfMember(guildID snowflake.Snowflake) *discord.Member { + if member, ok := c.caches.Members().Get(guildID, c.clientID); ok { + return &member + } + return nil +} + +func (c *clientImpl) Caches() cache.Caches { + return c.caches +} + +func (c *clientImpl) Rest() rest.Rest { + return c.restServices +} + +func (c *clientImpl) HandleReadyEvent(event discord.GatewayEventReady) { + c.applicationID = event.Application.ID + c.clientID = event.User.ID + c.selfUser = &event.User +} + +// AddEventListeners adds one or more EventListener(s) to the EventManager +func (c *clientImpl) AddEventListeners(listeners ...EventListener) { + c.eventManager.AddEventListeners(listeners...) +} + +// RemoveEventListeners removes one or more EventListener(s) from the EventManager +func (c *clientImpl) RemoveEventListeners(listeners ...EventListener) { + c.eventManager.RemoveEventListeners(listeners...) +} + +func (c *clientImpl) EventManager() EventManager { + return c.eventManager +} + +// ConnectGateway opens the gateway connection to discord +func (c *clientImpl) ConnectGateway(ctx context.Context) error { + if c.gateway == nil { + return discord.ErrNoGateway + } + return c.gateway.Open(ctx) +} + +func (c *clientImpl) Gateway() gateway.Gateway { + return c.gateway +} + +// HasGateway returns whether this Client has an active gateway.Gateway connection +func (c *clientImpl) HasGateway() bool { + return c.gateway != nil +} + +// ConnectShardManager opens the gateway connection to discord +func (c *clientImpl) ConnectShardManager(ctx context.Context) error { + if c.shardManager == nil { + return discord.ErrNoShardManager + } + c.shardManager.Open(ctx) + return nil +} + +func (c *clientImpl) ShardManager() sharding.ShardManager { + return c.shardManager +} + +// HasShardManager returns whether this Client is sharded +func (c *clientImpl) HasShardManager() bool { + return c.shardManager != nil +} + +func (c *clientImpl) Shard(guildID snowflake.Snowflake) (gateway.Gateway, error) { + if c.HasGateway() { + return c.gateway, nil + } else if c.HasShardManager() { + if shard := c.shardManager.GetGuildShard(guildID); shard != nil { + return shard, nil + } + return nil, discord.ErrShardNotFound + } + return nil, discord.ErrNoGatewayOrShardManager +} + +func (c *clientImpl) Connect(ctx context.Context, guildID snowflake.Snowflake, channelID snowflake.Snowflake) error { + shard, err := c.Shard(guildID) + if err != nil { + return err + } + return shard.Send(ctx, discord.GatewayOpcodeVoiceStateUpdate, discord.GatewayMessageDataVoiceStateUpdate{ + GuildID: guildID, + ChannelID: &channelID, + }) +} + +func (c *clientImpl) Disconnect(ctx context.Context, guildID snowflake.Snowflake) error { + shard, err := c.Shard(guildID) + if err != nil { + return err + } + return shard.Send(ctx, discord.GatewayOpcodeVoiceStateUpdate, discord.GatewayMessageDataVoiceStateUpdate{ + GuildID: guildID, + ChannelID: nil, + }) +} + +func (c *clientImpl) RequestMembers(ctx context.Context, guildID snowflake.Snowflake, presence bool, nonce string, userIDs ...snowflake.Snowflake) error { + shard, err := c.Shard(guildID) + if err != nil { + return err + } + return shard.Send(ctx, discord.GatewayOpcodeRequestGuildMembers, discord.GatewayMessageDataRequestGuildMembers{ + GuildID: guildID, + Presences: presence, + UserIDs: userIDs, + Nonce: nonce, + }) +} +func (c *clientImpl) RequestMembersWithQuery(ctx context.Context, guildID snowflake.Snowflake, presence bool, nonce string, query string, limit int) error { + shard, err := c.Shard(guildID) + if err != nil { + return err + } + return shard.Send(ctx, discord.GatewayOpcodeRequestGuildMembers, discord.GatewayMessageDataRequestGuildMembers{ + GuildID: guildID, + Query: &query, + Limit: &limit, + Presences: presence, + Nonce: nonce, + }) +} + +func (c *clientImpl) SetPresence(ctx context.Context, presenceUpdate discord.GatewayMessageDataPresenceUpdate) error { + if !c.HasGateway() { + return discord.ErrNoGateway + } + return c.gateway.Send(ctx, discord.GatewayOpcodePresenceUpdate, presenceUpdate) +} + +// SetPresenceForShard sets the Presence of this Client for the provided shard +func (c *clientImpl) SetPresenceForShard(ctx context.Context, shardId int, presenceUpdate discord.GatewayMessageDataPresenceUpdate) error { + if !c.HasShardManager() { + return discord.ErrNoShardManager + } + shard := c.shardManager.Shard(shardId) + if shard == nil { + return discord.ErrShardNotFound + } + return shard.Send(ctx, discord.GatewayOpcodePresenceUpdate, presenceUpdate) +} + +func (c *clientImpl) MemberChunkingManager() MemberChunkingManager { + return c.memberChunkingManager +} + +// StartHTTPServer starts the interaction webhook server +func (c *clientImpl) StartHTTPServer() error { + if c.httpServer == nil { + return discord.ErrNoHTTPServer + } + c.httpServer.Start() + return nil +} + +func (c *clientImpl) HTTPServer() httpserver.Server { + return c.httpServer +} + +// HasHTTPServer returns whether Client has an active httpserver.Server +func (c *clientImpl) HasHTTPServer() bool { + return c.httpServer != nil +} diff --git a/bot/config.go b/bot/config.go new file mode 100644 index 00000000..8aa28693 --- /dev/null +++ b/bot/config.go @@ -0,0 +1,264 @@ +package bot + +import ( + "fmt" + + "github.com/disgoorg/disgo/cache" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/disgo/httpserver" + "github.com/disgoorg/disgo/internal/tokenhelper" + "github.com/disgoorg/disgo/rest" + "github.com/disgoorg/disgo/sharding" + "github.com/disgoorg/log" +) + +func DefaultConfig(gatewayHandlers map[discord.GatewayEventType]GatewayEventHandler, httpHandler HTTPServerEventHandler) *Config { + return &Config{ + Logger: log.Default(), + EventManagerConfigOpts: []EventManagerConfigOpt{WithGatewayHandlers(gatewayHandlers), WithHTTPServerHandler(httpHandler)}, + } +} + +// Config lets you configure your Client instance +// Config is the core.Client config used to configure everything +type Config struct { + Logger log.Logger + + RestClient rest.Client + RestClientConfigOpts []rest.ConfigOpt + Rest rest.Rest + + EventManager EventManager + EventManagerConfigOpts []EventManagerConfigOpt + + Gateway gateway.Gateway + GatewayConfigOpts []gateway.ConfigOpt + + ShardManager sharding.ShardManager + ShardManagerConfigOpts []sharding.ConfigOpt + + HTTPServer httpserver.Server + HTTPServerConfigOpts []httpserver.ConfigOpt + + Caches cache.Caches + CacheConfigOpts []cache.ConfigOpt + + MemberChunkingManager MemberChunkingManager + MemberChunkingFilter MemberChunkingFilter +} + +type ConfigOpt func(config *Config) + +func (c *Config) Apply(opts []ConfigOpt) { + for _, opt := range opts { + opt(c) + } +} + +// WithLogger lets you inject your own logger implementing log.Logger +func WithLogger(logger log.Logger) ConfigOpt { + return func(config *Config) { + config.Logger = logger + } +} + +func WithRestClient(restClient rest.Client) ConfigOpt { + return func(config *Config) { + config.RestClient = restClient + } +} + +func WithRestClientConfigOpts(opts ...rest.ConfigOpt) ConfigOpt { + return func(config *Config) { + config.RestClientConfigOpts = append(config.RestClientConfigOpts, opts...) + } +} + +func WithRest(rest rest.Rest) ConfigOpt { + return func(config *Config) { + config.Rest = rest + } +} + +func WithEventManager(eventManager EventManager) ConfigOpt { + return func(config *Config) { + config.EventManager = eventManager + } +} + +func WithEventManagerConfigOpts(opts ...EventManagerConfigOpt) ConfigOpt { + return func(config *Config) { + config.EventManagerConfigOpts = append(config.EventManagerConfigOpts, opts...) + } +} + +func WithEventListeners(eventListeners ...EventListener) ConfigOpt { + return func(config *Config) { + config.EventManagerConfigOpts = append(config.EventManagerConfigOpts, WithListeners(eventListeners...)) + } +} + +func WithGateway(gateway gateway.Gateway) ConfigOpt { + return func(config *Config) { + config.Gateway = gateway + } +} + +func WithGatewayConfigOpts(opts ...gateway.ConfigOpt) ConfigOpt { + return func(config *Config) { + config.GatewayConfigOpts = append(config.GatewayConfigOpts, opts...) + } +} + +func WithShardManager(shardManager sharding.ShardManager) ConfigOpt { + return func(config *Config) { + config.ShardManager = shardManager + } +} + +func WithShardManagerConfigOpts(opts ...sharding.ConfigOpt) ConfigOpt { + return func(config *Config) { + config.ShardManagerConfigOpts = append(config.ShardManagerConfigOpts, opts...) + } +} + +func WithHTTPServer(httpServer httpserver.Server) ConfigOpt { + return func(config *Config) { + config.HTTPServer = httpServer + } +} + +func WithHTTPServerConfigOpts(opts ...httpserver.ConfigOpt) ConfigOpt { + return func(config *Config) { + config.HTTPServerConfigOpts = append(config.HTTPServerConfigOpts, opts...) + } +} + +func WithCaches(caches cache.Caches) ConfigOpt { + return func(config *Config) { + config.Caches = caches + } +} + +func WithCacheConfigOpts(opts ...cache.ConfigOpt) ConfigOpt { + return func(config *Config) { + config.CacheConfigOpts = append(config.CacheConfigOpts, opts...) + } +} + +func WithMemberChunkingManager(memberChunkingManager MemberChunkingManager) ConfigOpt { + return func(config *Config) { + config.MemberChunkingManager = memberChunkingManager + } +} + +func WithMemberChunkingFilter(memberChunkingFilter MemberChunkingFilter) ConfigOpt { + return func(config *Config) { + config.MemberChunkingFilter = memberChunkingFilter + } +} + +func BuildClient(token string, config Config, gatewayEventHandlerFunc func(client Client) gateway.EventHandlerFunc, httpServerEventHandlerFunc func(client Client) httpserver.EventHandlerFunc, os string, name string, github string, version string) (Client, error) { + if token == "" { + return nil, discord.ErrNoBotToken + } + id, err := tokenhelper.IDFromToken(token) + if err != nil { + return nil, fmt.Errorf("error while getting application id from token: %w", err) + } + client := &clientImpl{ + token: token, + logger: config.Logger, + } + + // TODO: figure out how we handle different application & client ids + client.applicationID = *id + client.clientID = *id + + if config.RestClient == nil { + // prepend standard user-agent. this can be overridden as it's appended to the front of the slice + config.RestClientConfigOpts = append([]rest.ConfigOpt{ + rest.WithUserAgent(fmt.Sprintf("DiscordBot (%s, %s)", github, version)), + rest.WithLogger(client.logger), + }, config.RestClientConfigOpts...) + + config.RestClient = rest.NewClient(client.token, config.RestClientConfigOpts...) + } + + if config.Rest == nil { + config.Rest = rest.NewRest(config.RestClient) + } + client.restServices = config.Rest + + if config.EventManager == nil { + config.EventManager = NewEventManager(client, config.EventManagerConfigOpts...) + } + client.eventManager = config.EventManager + + if config.Gateway == nil && config.GatewayConfigOpts != nil { + var gatewayRs *discord.Gateway + gatewayRs, err = client.restServices.Gateway().GetGateway() + if err != nil { + return nil, err + } + + config.GatewayConfigOpts = append([]gateway.ConfigOpt{ + gateway.WithGatewayURL(gatewayRs.URL), + gateway.WithLogger(client.logger), + gateway.WithOS(os), + gateway.WithBrowser(name), + gateway.WithDevice(name), + }, config.GatewayConfigOpts...) + + config.Gateway = gateway.New(token, gatewayEventHandlerFunc(client), config.GatewayConfigOpts...) + } + client.gateway = config.Gateway + + if config.ShardManager == nil && config.ShardManagerConfigOpts != nil { + var gatewayBotRs *discord.GatewayBot + gatewayBotRs, err = client.restServices.Gateway().GetGatewayBot() + if err != nil { + return nil, err + } + + shardIDs := make([]int, gatewayBotRs.Shards-1) + for i := 0; i < gatewayBotRs.Shards-1; i++ { + shardIDs[i] = i + } + + config.ShardManagerConfigOpts = append([]sharding.ConfigOpt{ + sharding.WithShardCount(gatewayBotRs.Shards), + sharding.WithShards(shardIDs...), + sharding.WithGatewayConfigOpts( + gateway.WithGatewayURL(gatewayBotRs.URL), + gateway.WithLogger(client.logger), + ), + sharding.WithLogger(client.logger), + }, config.ShardManagerConfigOpts...) + + config.ShardManager = sharding.New(token, gatewayEventHandlerFunc(client), config.ShardManagerConfigOpts...) + } + client.shardManager = config.ShardManager + + if config.HTTPServer == nil && config.HTTPServerConfigOpts != nil { + config.HTTPServerConfigOpts = append([]httpserver.ConfigOpt{ + httpserver.WithLogger(client.logger), + }, config.HTTPServerConfigOpts...) + + config.HTTPServer = httpserver.New(httpServerEventHandlerFunc(client), config.HTTPServerConfigOpts...) + } + client.httpServer = config.HTTPServer + + if config.MemberChunkingManager == nil { + config.MemberChunkingManager = NewMemberChunkingManager(client, config.MemberChunkingFilter) + } + client.memberChunkingManager = config.MemberChunkingManager + + if config.Caches == nil { + config.Caches = cache.NewCaches(config.CacheConfigOpts...) + } + client.caches = config.Caches + + return client, nil +} diff --git a/bot/event_collector.go b/bot/event_collector.go new file mode 100644 index 00000000..eaac5617 --- /dev/null +++ b/bot/event_collector.go @@ -0,0 +1,31 @@ +package bot + +// NewEventCollector gives you a channel to receive on and a function to close the collector +func NewEventCollector[E Event](disgo Client, filterFunc func(e E) bool) (<-chan E, func()) { + ch := make(chan E) + + coll := &collector[E]{ + FilterFunc: filterFunc, + Chan: ch, + } + disgo.EventManager().AddEventListeners(coll) + + return ch, func() { + disgo.EventManager().RemoveEventListeners(coll) + close(ch) + } +} + +type collector[E Event] struct { + FilterFunc func(e E) bool + Chan chan<- E +} + +func (c *collector[E]) OnEvent(e Event) { + if event, ok := e.(E); ok { + if !c.FilterFunc(event) { + return + } + c.Chan <- event + } +} diff --git a/bot/event_manager.go b/bot/event_manager.go new file mode 100644 index 00000000..c22db59a --- /dev/null +++ b/bot/event_manager.go @@ -0,0 +1,142 @@ +package bot + +import ( + "io" + "runtime/debug" + "sync" + + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/json" +) + +var _ EventManager = (*eventManagerImpl)(nil) + +func NewEventManager(client Client, opts ...EventManagerConfigOpt) EventManager { + config := DefaultEventManagerConfig() + config.Apply(opts) + + return &eventManagerImpl{ + client: client, + config: *config, + } +} + +// EventManager lets you listen for specific events triggered by raw gateway events +type EventManager interface { + RawEventsEnabled() bool + + AddEventListeners(eventListeners ...EventListener) + RemoveEventListeners(eventListeners ...EventListener) + + HandleGatewayEvent(gatewayEventType discord.GatewayEventType, sequenceNumber int, payload io.Reader) + HandleHTTPEvent(responseChannel chan<- discord.InteractionResponse, payload io.Reader) + DispatchEvent(event Event) +} + +// EventListener is used to create new EventListener to listen to events +type EventListener interface { + OnEvent(event Event) +} + +// Event the basic interface each event implement +type Event interface { + Client() Client + SequenceNumber() int +} + +// GatewayEventHandler is used to handle Gateway Event(s) +type GatewayEventHandler interface { + EventType() discord.GatewayEventType + New() any + HandleGatewayEvent(client Client, sequenceNumber int, v any) +} + +// HTTPServerEventHandler is used to handle HTTP Event(s) +type HTTPServerEventHandler interface { + New() any + HandleHTTPEvent(client Client, responseChannel chan<- discord.InteractionResponse, v any) +} + +// eventManagerImpl is the implementation of core.EventManager +type eventManagerImpl struct { + client Client + eventListenerMu sync.Mutex + config EventManagerConfig +} + +func (e *eventManagerImpl) RawEventsEnabled() bool { + return e.config.RawEventsEnabled +} + +// HandleGatewayEvent calls the correct core.EventHandler +func (e *eventManagerImpl) HandleGatewayEvent(gatewayEventType discord.GatewayEventType, sequenceNumber int, reader io.Reader) { + if handler, ok := e.config.GatewayHandlers[gatewayEventType]; ok { + v := handler.New() + if v != nil { + if err := json.NewDecoder(reader).Decode(&v); err != nil { + e.client.Logger().Errorf("error while unmarshalling event '%s'. error: %s", gatewayEventType, err.Error()) + return + } + } + handler.HandleGatewayEvent(e.client, sequenceNumber, v) + } else { + e.client.Logger().Warnf("no handler for gateway event '%s' found", gatewayEventType) + } +} + +// HandleHTTPEvent calls the correct core.EventHandler +func (e *eventManagerImpl) HandleHTTPEvent(responseChannel chan<- discord.InteractionResponse, reader io.Reader) { + v := e.config.HTTPServerHandler.New() + if err := json.NewDecoder(reader).Decode(&v); err != nil { + e.client.Logger().Error("error while unmarshalling httpserver event. error: ", err) + } + e.config.HTTPServerHandler.HandleHTTPEvent(e.client, responseChannel, v) +} + +// DispatchEvent dispatches a new event to the client +func (e *eventManagerImpl) DispatchEvent(event Event) { + defer func() { + if r := recover(); r != nil { + e.client.Logger().Errorf("recovered from panic in event listener: %+v\nstack: %s", r, string(debug.Stack())) + return + } + }() + e.eventListenerMu.Lock() + defer e.eventListenerMu.Unlock() + for i := range e.config.EventListeners { + if e.config.AsyncEventsEnabled { + go func() { + defer func() { + if r := recover(); r != nil { + e.client.Logger().Errorf("recovered from panic in event listener: %+v\nstack: %s", r, string(debug.Stack())) + return + } + }() + e.config.EventListeners[i].OnEvent(event) + }() + continue + } + e.config.EventListeners[i].OnEvent(event) + } +} + +// AddEventListeners adds one or more core.EventListener(s) to the core.EventManager +func (e *eventManagerImpl) AddEventListeners(listeners ...EventListener) { + e.eventListenerMu.Lock() + defer e.eventListenerMu.Unlock() + e.config.EventListeners = append(e.config.EventListeners, listeners...) +} + +// RemoveEventListeners removes one or more core.EventListener(s) from the core.EventManager +func (e *eventManagerImpl) RemoveEventListeners(listeners ...EventListener) { + e.eventListenerMu.Lock() + defer e.eventListenerMu.Unlock() + for _, listener := range listeners { + for i, l := range e.config.EventListeners { + if l == listener { + e.config.EventListeners = append(e.config.EventListeners[:i], e.config.EventListeners[i+1:]...) + break + } + } + } +} diff --git a/bot/event_manager_config.go b/bot/event_manager_config.go new file mode 100644 index 00000000..df94281e --- /dev/null +++ b/bot/event_manager_config.go @@ -0,0 +1,54 @@ +package bot + +import "github.com/disgoorg/disgo/discord" + +func DefaultEventManagerConfig() *EventManagerConfig { + return &EventManagerConfig{} +} + +type EventManagerConfig struct { + EventListeners []EventListener + RawEventsEnabled bool + AsyncEventsEnabled bool + + GatewayHandlers map[discord.GatewayEventType]GatewayEventHandler + HTTPServerHandler HTTPServerEventHandler +} + +type EventManagerConfigOpt func(config *EventManagerConfig) + +func (c *EventManagerConfig) Apply(opts []EventManagerConfigOpt) { + for _, opt := range opts { + opt(c) + } +} + +func WithListeners(listeners ...EventListener) EventManagerConfigOpt { + return func(config *EventManagerConfig) { + config.EventListeners = append(config.EventListeners, listeners...) + } +} + +func WithRawEventsEnabled() EventManagerConfigOpt { + return func(config *EventManagerConfig) { + config.RawEventsEnabled = true + } +} + +func WithAsyncEventsEnabled() EventManagerConfigOpt { + return func(config *EventManagerConfig) { + config.AsyncEventsEnabled = true + } +} + +func WithGatewayHandlers(handlers map[discord.GatewayEventType]GatewayEventHandler) EventManagerConfigOpt { + return func(config *EventManagerConfig) { + config.GatewayHandlers = handlers + } +} + +func WithHTTPServerHandler(handler HTTPServerEventHandler) EventManagerConfigOpt { + return func(config *EventManagerConfig) { + config.HTTPServerHandler = handler + } +} diff --git a/core/member_chunking_filter.go b/bot/member_chunking_filter.go similarity index 90% rename from core/member_chunking_filter.go rename to bot/member_chunking_filter.go index 0ae4aceb..dcb76d9f 100644 --- a/core/member_chunking_filter.go +++ b/bot/member_chunking_filter.go @@ -1,10 +1,9 @@ -package core +package bot -import "github.com/DisgoOrg/snowflake" +import "github.com/disgoorg/snowflake" type MemberChunkingFilter func(guildID snowflake.Snowflake) bool -//goland:noinspection GoUnusedGlobalVariable var ( MemberChunkingFilterAll MemberChunkingFilter = func(_ snowflake.Snowflake) bool { return true } MemberChunkingFilterNone MemberChunkingFilter = func(_ snowflake.Snowflake) bool { return false } diff --git a/core/member_chunking_manager.go b/bot/member_chunking_manager.go similarity index 66% rename from core/member_chunking_manager.go rename to bot/member_chunking_manager.go index a42d2175..9aff987f 100644 --- a/core/member_chunking_manager.go +++ b/bot/member_chunking_manager.go @@ -1,62 +1,62 @@ -package core +package bot import ( "context" "sync" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/internal/insecurerandstr" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/internal/insecurerandstr" + "github.com/disgoorg/snowflake" ) var _ MemberChunkingManager = (*memberChunkingManagerImpl)(nil) -func NewMemberChunkingManager(bot *Bot, memberChunkingFilter MemberChunkingFilter) MemberChunkingManager { +func NewMemberChunkingManager(client Client, memberChunkingFilter MemberChunkingFilter) MemberChunkingManager { return &memberChunkingManagerImpl{ - bot: bot, + bot: client, memberChunkingFilter: memberChunkingFilter, chunkingRequests: map[string]*chunkingRequest{}, } } type MemberChunkingManager interface { - Bot() *Bot + Client() Client MemberChunkingFilter() MemberChunkingFilter - HandleChunk(payload discord.GuildMembersChunkGatewayEvent) + HandleChunk(payload discord.GatewayEventGuildMembersChunk) - RequestMembers(guildID snowflake.Snowflake, userIDs ...snowflake.Snowflake) ([]*Member, error) - RequestMembersWithQuery(guildID snowflake.Snowflake, query string, limit int) ([]*Member, error) - RequestMembersWithFilter(guildID snowflake.Snowflake, memberFilterFunc func(member *Member) bool) ([]*Member, error) + RequestMembers(guildID snowflake.Snowflake, userIDs ...snowflake.Snowflake) ([]discord.Member, error) + RequestMembersWithQuery(guildID snowflake.Snowflake, query string, limit int) ([]discord.Member, error) + RequestMembersWithFilter(guildID snowflake.Snowflake, memberFilterFunc func(member discord.Member) bool) ([]discord.Member, error) - RequestMembersCtx(ctx context.Context, guildID snowflake.Snowflake, userIDs ...snowflake.Snowflake) ([]*Member, error) - RequestMembersWithQueryCtx(ctx context.Context, guildID snowflake.Snowflake, query string, limit int) ([]*Member, error) - RequestMembersWithFilterCtx(ctx context.Context, guildID snowflake.Snowflake, memberFilterFunc func(member *Member) bool) ([]*Member, error) + RequestMembersCtx(ctx context.Context, guildID snowflake.Snowflake, userIDs ...snowflake.Snowflake) ([]discord.Member, error) + RequestMembersWithQueryCtx(ctx context.Context, guildID snowflake.Snowflake, query string, limit int) ([]discord.Member, error) + RequestMembersWithFilterCtx(ctx context.Context, guildID snowflake.Snowflake, memberFilterFunc func(member discord.Member) bool) ([]discord.Member, error) - RequestMembersChan(guildID snowflake.Snowflake, userIDs ...snowflake.Snowflake) (<-chan *Member, func(), error) - RequestMembersWithQueryChan(guildID snowflake.Snowflake, query string, limit int) (<-chan *Member, func(), error) - RequestMembersWithFilterChan(guildID snowflake.Snowflake, memberFilterFunc func(member *Member) bool) (<-chan *Member, func(), error) + RequestMembersChan(guildID snowflake.Snowflake, userIDs ...snowflake.Snowflake) (<-chan discord.Member, func(), error) + RequestMembersWithQueryChan(guildID snowflake.Snowflake, query string, limit int) (<-chan discord.Member, func(), error) + RequestMembersWithFilterChan(guildID snowflake.Snowflake, memberFilterFunc func(member discord.Member) bool) (<-chan discord.Member, func(), error) } type chunkingRequest struct { sync.Mutex nonce string - memberChan chan<- *Member - memberFilterFunc func(member *Member) bool + memberChan chan<- discord.Member + memberFilterFunc func(member discord.Member) bool chunks int } type memberChunkingManagerImpl struct { - bot *Bot + bot Client memberChunkingFilter MemberChunkingFilter chunkingRequestsMu sync.RWMutex chunkingRequests map[string]*chunkingRequest } -func (m *memberChunkingManagerImpl) Bot() *Bot { +func (m *memberChunkingManagerImpl) Client() Client { return m.bot } @@ -64,12 +64,12 @@ func (m *memberChunkingManagerImpl) MemberChunkingFilter() MemberChunkingFilter return m.memberChunkingFilter } -func (m *memberChunkingManagerImpl) HandleChunk(payload discord.GuildMembersChunkGatewayEvent) { +func (m *memberChunkingManagerImpl) HandleChunk(payload discord.GatewayEventGuildMembersChunk) { m.chunkingRequestsMu.RLock() request, ok := m.chunkingRequests[payload.Nonce] m.chunkingRequestsMu.RUnlock() if !ok { - m.Bot().Logger.Debug("received unknown member chunk event: ", payload) + m.Client().Logger().Debug("received unknown member chunk event: ", payload) return } @@ -77,11 +77,12 @@ func (m *memberChunkingManagerImpl) HandleChunk(payload discord.GuildMembersChun defer request.Unlock() for _, member := range payload.Members { - coreMember := m.Bot().EntityBuilder.CreateMember(payload.GuildID, member, CacheStrategyYes) - if request.memberFilterFunc != nil && !request.memberFilterFunc(coreMember) { + // try to cache member + m.Client().Caches().Members().Put(member.GuildID, member.User.ID, member) + if request.memberFilterFunc != nil && !request.memberFilterFunc(member) { continue } - request.memberChan <- coreMember + request.memberChan <- member } // all chunks sent cleanup @@ -99,13 +100,13 @@ func cleanupRequest(m *memberChunkingManagerImpl, request *chunkingRequest) { m.chunkingRequestsMu.Unlock() } -func (m *memberChunkingManagerImpl) requestGuildMembersChan(ctx context.Context, guildID snowflake.Snowflake, query *string, limit *int, userIDs []snowflake.Snowflake, memberFilterFunc func(member *Member) bool) (<-chan *Member, func(), error) { - shard, err := m.Bot().Shard(guildID) +func (m *memberChunkingManagerImpl) requestGuildMembersChan(ctx context.Context, guildID snowflake.Snowflake, query *string, limit *int, userIDs []snowflake.Snowflake, memberFilterFunc func(member discord.Member) bool) (<-chan discord.Member, func(), error) { + shard, err := m.Client().Shard(guildID) if err != nil { return nil, nil, err } - if shard.Config().GatewayIntents.Missing(discord.GatewayIntentGuildMembers) { + if shard.GatewayIntents().Missing(discord.GatewayIntentGuildMembers) { return nil, nil, discord.ErrNoGuildMembersIntent } @@ -119,7 +120,7 @@ func (m *memberChunkingManagerImpl) requestGuildMembersChan(ctx context.Context, break } } - memberChan := make(chan *Member) + memberChan := make(chan discord.Member) request := &chunkingRequest{ nonce: nonce, memberChan: memberChan, @@ -130,22 +131,22 @@ func (m *memberChunkingManagerImpl) requestGuildMembersChan(ctx context.Context, m.chunkingRequests[nonce] = request m.chunkingRequestsMu.Unlock() - command := discord.RequestGuildMembersCommandData{ + command := discord.GatewayMessageDataRequestGuildMembers{ GuildID: guildID, Query: query, Limit: limit, - Presences: shard.Config().GatewayIntents.Has(discord.GatewayIntentGuildPresences), + Presences: shard.GatewayIntents().Has(discord.GatewayIntentGuildPresences), UserIDs: userIDs, Nonce: nonce, } return memberChan, func() { cleanupRequest(m, request) - }, shard.Send(ctx, discord.NewGatewayCommand(discord.GatewayOpcodeRequestGuildMembers, command)) + }, shard.Send(ctx, discord.GatewayOpcodeRequestGuildMembers, command) } -func (m *memberChunkingManagerImpl) requestGuildMembers(ctx context.Context, guildID snowflake.Snowflake, query *string, limit *int, userIDs []snowflake.Snowflake, memberFilterFunc func(member *Member) bool) ([]*Member, error) { - var members []*Member +func (m *memberChunkingManagerImpl) requestGuildMembers(ctx context.Context, guildID snowflake.Snowflake, query *string, limit *int, userIDs []snowflake.Snowflake, memberFilterFunc func(member discord.Member) bool) ([]discord.Member, error) { + var members []discord.Member memberChan, cls, err := m.requestGuildMembersChan(ctx, guildID, query, limit, userIDs, memberFilterFunc) if err != nil { return nil, err @@ -164,54 +165,54 @@ func (m *memberChunkingManagerImpl) requestGuildMembers(ctx context.Context, gui } } -func (m *memberChunkingManagerImpl) RequestMembers(guildID snowflake.Snowflake, userIDs ...snowflake.Snowflake) ([]*Member, error) { +func (m *memberChunkingManagerImpl) RequestMembers(guildID snowflake.Snowflake, userIDs ...snowflake.Snowflake) ([]discord.Member, error) { return m.RequestMembersCtx(context.Background(), guildID, userIDs...) } -func (m *memberChunkingManagerImpl) RequestMembersWithQuery(guildID snowflake.Snowflake, query string, limit int) ([]*Member, error) { +func (m *memberChunkingManagerImpl) RequestMembersWithQuery(guildID snowflake.Snowflake, query string, limit int) ([]discord.Member, error) { return m.RequestMembersWithQueryCtx(context.Background(), guildID, query, limit) } -func (m *memberChunkingManagerImpl) RequestAllMembers(guildID snowflake.Snowflake) ([]*Member, error) { +func (m *memberChunkingManagerImpl) RequestAllMembers(guildID snowflake.Snowflake) ([]discord.Member, error) { return m.RequestAllMembersCtx(context.Background(), guildID) } -func (m *memberChunkingManagerImpl) RequestMembersWithFilter(guildID snowflake.Snowflake, memberFilterFunc func(member *Member) bool) ([]*Member, error) { +func (m *memberChunkingManagerImpl) RequestMembersWithFilter(guildID snowflake.Snowflake, memberFilterFunc func(member discord.Member) bool) ([]discord.Member, error) { return m.RequestMembersWithFilterCtx(context.Background(), guildID, memberFilterFunc) } -func (m *memberChunkingManagerImpl) RequestMembersCtx(ctx context.Context, guildID snowflake.Snowflake, userIDs ...snowflake.Snowflake) ([]*Member, error) { +func (m *memberChunkingManagerImpl) RequestMembersCtx(ctx context.Context, guildID snowflake.Snowflake, userIDs ...snowflake.Snowflake) ([]discord.Member, error) { return m.requestGuildMembers(ctx, guildID, nil, nil, userIDs, nil) } -func (m *memberChunkingManagerImpl) RequestMembersWithQueryCtx(ctx context.Context, guildID snowflake.Snowflake, query string, limit int) ([]*Member, error) { +func (m *memberChunkingManagerImpl) RequestMembersWithQueryCtx(ctx context.Context, guildID snowflake.Snowflake, query string, limit int) ([]discord.Member, error) { return m.requestGuildMembers(ctx, guildID, &query, &limit, nil, nil) } -func (m *memberChunkingManagerImpl) RequestAllMembersCtx(ctx context.Context, guildID snowflake.Snowflake) ([]*Member, error) { +func (m *memberChunkingManagerImpl) RequestAllMembersCtx(ctx context.Context, guildID snowflake.Snowflake) ([]discord.Member, error) { query := "" limit := 0 return m.requestGuildMembers(ctx, guildID, &query, &limit, nil, nil) } -func (m *memberChunkingManagerImpl) RequestMembersWithFilterCtx(ctx context.Context, guildID snowflake.Snowflake, memberFilterFunc func(member *Member) bool) ([]*Member, error) { +func (m *memberChunkingManagerImpl) RequestMembersWithFilterCtx(ctx context.Context, guildID snowflake.Snowflake, memberFilterFunc func(member discord.Member) bool) ([]discord.Member, error) { query := "" limit := 0 return m.requestGuildMembers(ctx, guildID, &query, &limit, nil, memberFilterFunc) } -func (m *memberChunkingManagerImpl) RequestMembersChan(guildID snowflake.Snowflake, userIDs ...snowflake.Snowflake) (<-chan *Member, func(), error) { +func (m *memberChunkingManagerImpl) RequestMembersChan(guildID snowflake.Snowflake, userIDs ...snowflake.Snowflake) (<-chan discord.Member, func(), error) { return m.requestGuildMembersChan(context.Background(), guildID, nil, nil, userIDs, nil) } -func (m *memberChunkingManagerImpl) RequestMembersWithQueryChan(guildID snowflake.Snowflake, query string, limit int) (<-chan *Member, func(), error) { +func (m *memberChunkingManagerImpl) RequestMembersWithQueryChan(guildID snowflake.Snowflake, query string, limit int) (<-chan discord.Member, func(), error) { return m.requestGuildMembersChan(context.Background(), guildID, &query, &limit, nil, nil) } -func (m *memberChunkingManagerImpl) RequestAllMembersChan(guildID snowflake.Snowflake) (<-chan *Member, func(), error) { +func (m *memberChunkingManagerImpl) RequestAllMembersChan(guildID snowflake.Snowflake) (<-chan discord.Member, func(), error) { query := "" limit := 0 return m.requestGuildMembersChan(context.Background(), guildID, &query, &limit, nil, nil) } -func (m *memberChunkingManagerImpl) RequestMembersWithFilterChan(guildID snowflake.Snowflake, memberFilterFunc func(member *Member) bool) (<-chan *Member, func(), error) { +func (m *memberChunkingManagerImpl) RequestMembersWithFilterChan(guildID snowflake.Snowflake, memberFilterFunc func(member discord.Member) bool) (<-chan discord.Member, func(), error) { query := "" limit := 0 return m.requestGuildMembersChan(context.Background(), guildID, &query, &limit, nil, memberFilterFunc) diff --git a/cache/cache.go b/cache/cache.go new file mode 100644 index 00000000..8d9e4303 --- /dev/null +++ b/cache/cache.go @@ -0,0 +1,138 @@ +package cache + +import ( + "sync" + + "github.com/disgoorg/snowflake" +) + +type FilterFunc[T any] func(T) bool + +type Cache[T any] interface { + Get(id snowflake.Snowflake) (T, bool) + Put(id snowflake.Snowflake, entity T) + Remove(id snowflake.Snowflake) (T, bool) + RemoveIf(filterFunc FilterFunc[T]) + + All() []T + MapAll() map[snowflake.Snowflake]T + + FindFirst(cacheFindFunc FilterFunc[T]) (T, bool) + FindAll(cacheFindFunc FilterFunc[T]) []T + + ForEach(func(entity T)) +} + +var _ Cache[any] = (*DefaultCache[any])(nil) + +func NewCache[T any](flags Flags, neededFlags Flags, policy Policy[T]) Cache[T] { + return &DefaultCache[T]{ + flags: flags, + neededFlags: neededFlags, + policy: policy, + cache: make(map[snowflake.Snowflake]T), + } +} + +type DefaultCache[T any] struct { + mu sync.RWMutex + flags Flags + neededFlags Flags + policy Policy[T] + cache map[snowflake.Snowflake]T +} + +func (c *DefaultCache[T]) Get(id snowflake.Snowflake) (T, bool) { + c.mu.RLock() + defer c.mu.RUnlock() + entity, ok := c.cache[id] + return entity, ok +} + +func (c *DefaultCache[T]) Put(id snowflake.Snowflake, entity T) { + if c.neededFlags != FlagsNone && c.flags.Missing(c.neededFlags) { + return + } + if c.policy != nil && !c.policy(entity) { + return + } + c.mu.Lock() + defer c.mu.Unlock() + c.cache[id] = entity + return +} + +func (c *DefaultCache[T]) Remove(id snowflake.Snowflake) (T, bool) { + c.mu.Lock() + defer c.mu.Unlock() + entity, ok := c.cache[id] + if ok { + delete(c.cache, id) + } + return entity, ok +} + +func (c *DefaultCache[T]) RemoveIf(filterFunc FilterFunc[T]) { + c.mu.Lock() + defer c.mu.Unlock() + for id, entity := range c.cache { + if filterFunc(entity) { + delete(c.cache, id) + } + } +} + +func (c *DefaultCache[T]) All() []T { + c.mu.RLock() + defer c.mu.RUnlock() + entities := make([]T, len(c.cache)) + i := 0 + for _, entity := range c.cache { + entities[i] = entity + i++ + } + return entities +} + +func (c *DefaultCache[T]) MapAll() map[snowflake.Snowflake]T { + c.mu.RLock() + defer c.mu.RUnlock() + entities := make(map[snowflake.Snowflake]T, len(c.cache)) + for entityID, entity := range c.cache { + entities[entityID] = entity + } + return entities +} + +func (c *DefaultCache[T]) FindFirst(cacheFindFunc FilterFunc[T]) (T, bool) { + c.mu.RLock() + defer c.mu.RUnlock() + for _, entity := range c.cache { + if cacheFindFunc(entity) { + return entity, true + } + } + var entity T + return entity, false +} + +func (c *DefaultCache[T]) FindAll(cacheFindFunc FilterFunc[T]) []T { + c.mu.RLock() + defer c.mu.RUnlock() + var entities []T + for _, entity := range c.cache { + if cacheFindFunc(entity) { + entities = append(entities, entity) + } + } + return entities +} + +func (c *DefaultCache[T]) ForEach(forEachFunc func(entity T)) { + c.mu.RLock() + defer c.mu.RUnlock() + + for _, entity := range c.cache { + forEachFunc(entity) + } +} diff --git a/cache/cache_config.go b/cache/cache_config.go new file mode 100644 index 00000000..e4641094 --- /dev/null +++ b/cache/cache_config.go @@ -0,0 +1,49 @@ +package cache + +import ( + "github.com/disgoorg/disgo/discord" +) + +func DefaultConfig() *Config { + return &Config{ + CacheFlags: FlagsDefault, + MemberCachePolicy: MemberCachePolicyDefault, + MessageCachePolicy: MessageCachePolicyDefault, + } +} + +type Config struct { + CacheFlags Flags + MemberCachePolicy Policy[discord.Member] + MessageCachePolicy Policy[discord.Message] +} + +type ConfigOpt func(config *Config) + +func (c *Config) Apply(opts []ConfigOpt) { + for _, opt := range opts { + opt(c) + } +} + +func WithCacheFlags(cacheFlags ...Flags) ConfigOpt { + return func(config *Config) { + var flags Flags + for _, flag := range cacheFlags { + flags = flags.Add(flag) + } + config.CacheFlags = flags + } +} + +func WithMemberCachePolicy(memberCachePolicy Policy[discord.Member]) ConfigOpt { + return func(config *Config) { + config.MemberCachePolicy = memberCachePolicy + } +} + +func WithMessageCachePolicy(messageCachePolicy Policy[discord.Message]) ConfigOpt { + return func(config *Config) { + config.MessageCachePolicy = messageCachePolicy + } +} diff --git a/cache/cache_flags.go b/cache/cache_flags.go new file mode 100644 index 00000000..1d1e6381 --- /dev/null +++ b/cache/cache_flags.go @@ -0,0 +1,109 @@ +package cache + +// Flags are used to enable/disable certain internal caches +type Flags int + +// values for CacheFlags +const ( + FlagGuilds Flags = 1 << iota + FlagGuildScheduledEvents + FlagUsers + FlagMembers + FlagThreadMembers + FlagMessages + FlagPresences + + FlagGuildTextChannels + FlagDMChannels + FlagGuildVoiceChannels + FlagGroupDMChannels + FlagGuildCategories + FlagGuildNewsChannels + FlagGuildNewsThreads + FlagGuildPublicThreads + FlagGuildPrivateThreads + FlagGuildStageVoiceChannels + + FlagRoles + FlagRoleTags + + FlagEmojis + FlagStickers + + FlagVoiceStates + + FlagStageInstances + + FlagsNone Flags = 0 + + FlagsAllChannels = FlagGuildTextChannels | + FlagDMChannels | + FlagGuildVoiceChannels | + FlagGroupDMChannels | + FlagGuildCategories | + FlagGuildNewsChannels | + FlagGuildNewsThreads | + FlagGuildPublicThreads | + FlagGuildPrivateThreads | + FlagGuildStageVoiceChannels + + FlagsAllThreads = FlagGuildNewsThreads | + FlagGuildPublicThreads | + FlagGuildPrivateThreads + + FlagsDefault = FlagGuilds | + FlagsAllChannels | + FlagRoles | + FlagEmojis | + FlagStickers | + FlagVoiceStates + + FlagsFullRoles = FlagRoles | + FlagRoleTags + + FlagsAll = FlagGuilds | + FlagGuildScheduledEvents | + FlagsAllChannels | + FlagsFullRoles | + FlagEmojis | + FlagStickers | + FlagVoiceStates | + FlagStageInstances | + FlagPresences +) + +// Add allows you to add multiple bits together, producing a new bit +func (f Flags) Add(bits ...Flags) Flags { + for _, bit := range bits { + f |= bit + } + return f +} + +// Remove allows you to subtract multiple bits from the first, producing a new bit +func (f Flags) Remove(bits ...Flags) Flags { + for _, bit := range bits { + f &^= bit + } + return f +} + +// Has will ensure that the bit includes all the bits entered +func (f Flags) Has(bits ...Flags) bool { + for _, bit := range bits { + if (f & bit) != bit { + return false + } + } + return true +} + +// Missing will check whether the bit is missing any one of the bits +func (f Flags) Missing(bits ...Flags) bool { + for _, bit := range bits { + if (f & bit) != bit { + return true + } + } + return false +} diff --git a/cache/cache_policy.go b/cache/cache_policy.go new file mode 100644 index 00000000..089276f4 --- /dev/null +++ b/cache/cache_policy.go @@ -0,0 +1,74 @@ +package cache + +import ( + "time" + + "github.com/disgoorg/disgo/discord" +) + +// Policy can be used to define your own policy for caching cache +type Policy[T any] func(entity T) bool + +// Default discord.Message CachePolicy(s) +var ( + MessageCachePolicyNone Policy[discord.Message] = func(_ discord.Message) bool { return false } + + // MessageCachePolicyDuration creates a new CachePolicy which caches discord.Message(s) for the give time.Duration + MessageCachePolicyDuration = func(duration time.Duration) Policy[discord.Message] { + return func(message discord.Message) bool { + return message.CreatedAt.Add(duration).After(time.Now()) + } + } + MessageCachePolicyDefault = MessageCachePolicyNone +) + +// Default discord.Member CachePolicy(s) +var ( + MemberCachePolicyNone Policy[discord.Member] = func(_ discord.Member) bool { return false } + MemberCachePolicyAll Policy[discord.Member] = func(_ discord.Member) bool { return true } + MemberCachePolicyOwner Policy[discord.Member] = func(member discord.Member) bool { return false /*TODO*/ } + MemberCachePolicyOnline Policy[discord.Member] = func(_ discord.Member) bool { return false } + MemberCachePolicyVoice Policy[discord.Member] = func(member discord.Member) bool { return false } + MemberCachePolicyPending Policy[discord.Member] = func(member discord.Member) bool { return member.Pending } + MemberCachePolicyDefault = MemberCachePolicyOwner.Or(MemberCachePolicyVoice) +) + +// Or allows you to combine the CachePolicy with another, meaning either of them needs to be true +func (p Policy[T]) Or(policy Policy[T]) Policy[T] { + return func(entity T) bool { + return p(entity) || policy(entity) + } +} + +// And allows you to require both CachePolicy(s) to be true for the entity to be cached +func (p Policy[T]) And(policy Policy[T]) Policy[T] { + return func(entity T) bool { + return p(entity) && policy(entity) + } +} + +// AnyPolicy is a shorthand for CachePolicy.Or(CachePolicy).Or(CachePolicy) etc. +func AnyPolicy[T any](policies ...Policy[T]) Policy[T] { + var policy Policy[T] + for _, p := range policies { + if policy == nil { + policy = p + continue + } + policy = policy.Or(p) + } + return policy +} + +// AllPolicies is a shorthand for CachePolicy.And(CachePolicy).And(CachePolicy) etc. +func AllPolicies[T any](policies ...Policy[T]) Policy[T] { + var policy Policy[T] + for _, p := range policies { + if policy == nil { + policy = p + continue + } + policy = policy.And(p) + } + return policy +} diff --git a/cache/caches.go b/cache/caches.go new file mode 100644 index 00000000..73603528 --- /dev/null +++ b/cache/caches.go @@ -0,0 +1,213 @@ +package cache + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +type Caches interface { + CacheFlags() Flags + + GetMemberPermissions(member discord.Member) discord.Permissions + GetMemberPermissionsInChannel(channel discord.GuildChannel, member discord.Member) discord.Permissions + MemberRoles(member discord.Member) []discord.Role + + Roles() GroupedCache[discord.Role] + Members() GroupedCache[discord.Member] + ThreadMembers() GroupedCache[discord.ThreadMember] + Presences() GroupedCache[discord.Presence] + VoiceStates() GroupedCache[discord.VoiceState] + Messages() GroupedCache[discord.Message] + Emojis() GroupedCache[discord.Emoji] + Stickers() GroupedCache[discord.Sticker] + Guilds() GuildCache + Channels() ChannelCache + StageInstances() GroupedCache[discord.StageInstance] + GuildScheduledEvents() GroupedCache[discord.GuildScheduledEvent] +} + +func NewCaches(opts ...ConfigOpt) Caches { + config := DefaultConfig() + config.Apply(opts) + + return &cachesImpl{ + config: *config, + + guildCache: NewGuildCache(config.CacheFlags, FlagGuilds, nil), + channelCache: NewChannelCache(config.CacheFlags, FlagsAllChannels, nil), + stageInstanceCache: NewGroupedCache[discord.StageInstance](config.CacheFlags, FlagStageInstances, nil), + guildScheduledEventCache: NewGroupedCache[discord.GuildScheduledEvent](config.CacheFlags, FlagGuildScheduledEvents, nil), + roleCache: NewGroupedCache[discord.Role](config.CacheFlags, FlagRoles, nil), + memberCache: NewGroupedCache[discord.Member](config.CacheFlags, FlagMembers, config.MemberCachePolicy), + threadMemberCache: NewGroupedCache[discord.ThreadMember](config.CacheFlags, FlagThreadMembers, nil), + presenceCache: NewGroupedCache[discord.Presence](config.CacheFlags, FlagPresences, nil), + voiceStateCache: NewGroupedCache[discord.VoiceState](config.CacheFlags, FlagVoiceStates, nil), + messageCache: NewGroupedCache[discord.Message](config.CacheFlags, FlagMessages, config.MessageCachePolicy), + emojiCache: NewGroupedCache[discord.Emoji](config.CacheFlags, FlagEmojis, nil), + stickerCache: NewGroupedCache[discord.Sticker](config.CacheFlags, FlagStickers, nil), + } +} + +type cachesImpl struct { + config Config + + guildCache GuildCache + channelCache ChannelCache + stageInstanceCache GroupedCache[discord.StageInstance] + guildScheduledEventCache GroupedCache[discord.GuildScheduledEvent] + roleCache GroupedCache[discord.Role] + memberCache GroupedCache[discord.Member] + threadMemberCache GroupedCache[discord.ThreadMember] + presenceCache GroupedCache[discord.Presence] + voiceStateCache GroupedCache[discord.VoiceState] + messageCache GroupedCache[discord.Message] + emojiCache GroupedCache[discord.Emoji] + stickerCache GroupedCache[discord.Sticker] +} + +func (c *cachesImpl) CacheFlags() Flags { + return c.config.CacheFlags +} + +func (c *cachesImpl) GetMemberPermissions(member discord.Member) discord.Permissions { + if guild, ok := c.Guilds().Get(member.GuildID); ok && guild.OwnerID == member.User.ID { + return discord.PermissionsAll + } + + var permissions discord.Permissions + if publicRole, ok := c.Roles().Get(member.GuildID, member.GuildID); ok { + permissions = publicRole.Permissions + } + + for _, role := range c.MemberRoles(member) { + permissions = permissions.Add(role.Permissions) + if permissions.Has(discord.PermissionAdministrator) { + return discord.PermissionsAll + } + } + if member.CommunicationDisabledUntil != nil { + permissions &= discord.PermissionViewChannel | discord.PermissionReadMessageHistory + } + return permissions +} + +func (c *cachesImpl) GetMemberPermissionsInChannel(channel discord.GuildChannel, member discord.Member) discord.Permissions { + return 0 + /*channel, ok := c.Channels().GetGuildChannel(channelID) + if !ok { + return discord.PermissionsNone + } + + if guild, ok := c.Guilds().Option(channel.GuildID()); ok && guild.OwnerID == member.User.CommandID { + return discord.PermissionsAll + } + + permissions := c.GetMemberPermissions(member) + if permissions.Has(discord.PermissionAdministrator) { + return discord.PermissionsAll + } + + var ( + allowRaw discord.Permissions + denyRaw discord.Permissions + ) + if overwrite := channel.RolePermissionOverwrite(channel.GuildID()); overwrite != nil { + allowRaw = overwrite.Allow + denyRaw = overwrite.Deny + } + + var ( + allowRole discord.Permissions + denyRole discord.Permissions + ) + for _, roleID := range member.RoleIDs { + if roleID == channel.GuildID() { + continue + } + + overwrite := channel.RolePermissionOverwrite(roleID) + if overwrite == nil { + break + } + allowRole = allowRole.Add(overwrite.Allow) + denyRole = denyRole.Add(overwrite.Deny) + } + + allowRaw = (allowRaw & (denyRole - 1)) | allowRole + denyRaw = (denyRaw & (allowRole - 1)) | denyRole + + if overwrite := channel.MemberPermissionOverwrite(member.User.CommandID); overwrite != nil { + allowRaw = (allowRaw & (overwrite.Deny - 1)) | overwrite.Allow + denyRaw = (denyRaw & (overwrite.Allow - 1)) | overwrite.Deny + } + + permissions &= denyRaw - 1 + permissions |= allowRaw + + if member.CommunicationDisabledUntil != nil { + permissions &= discord.PermissionViewChannel | discord.PermissionReadMessageHistory + } + return permissions*/ +} + +func (c *cachesImpl) MemberRoles(member discord.Member) []discord.Role { + return c.Roles().FindAll(func(groupID snowflake.Snowflake, role discord.Role) bool { + if groupID != member.GuildID { + return false + } + for _, roleID := range member.RoleIDs { + if roleID == role.ID { + return true + } + } + return false + }) +} + +func (c *cachesImpl) Roles() GroupedCache[discord.Role] { + return c.roleCache +} + +func (c *cachesImpl) Members() GroupedCache[discord.Member] { + return c.memberCache +} + +func (c *cachesImpl) ThreadMembers() GroupedCache[discord.ThreadMember] { + return c.threadMemberCache +} + +func (c *cachesImpl) Presences() GroupedCache[discord.Presence] { + return c.presenceCache +} + +func (c *cachesImpl) VoiceStates() GroupedCache[discord.VoiceState] { + return c.voiceStateCache +} + +func (c *cachesImpl) Messages() GroupedCache[discord.Message] { + return c.messageCache +} + +func (c *cachesImpl) Emojis() GroupedCache[discord.Emoji] { + return c.emojiCache +} + +func (c *cachesImpl) Stickers() GroupedCache[discord.Sticker] { + return c.stickerCache +} + +func (c *cachesImpl) Guilds() GuildCache { + return c.guildCache +} + +func (c *cachesImpl) Channels() ChannelCache { + return c.channelCache +} + +func (c *cachesImpl) StageInstances() GroupedCache[discord.StageInstance] { + return c.stageInstanceCache +} + +func (c *cachesImpl) GuildScheduledEvents() GroupedCache[discord.GuildScheduledEvent] { + return c.guildScheduledEventCache +} diff --git a/cache/channel_cache.go b/cache/channel_cache.go new file mode 100644 index 00000000..05a4e0f8 --- /dev/null +++ b/cache/channel_cache.go @@ -0,0 +1,191 @@ +package cache + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +func NewChannelCache(flags Flags, neededFlags Flags, policy Policy[discord.Channel]) ChannelCache { + return &ChannelCacheImpl{ + Cache: NewCache[discord.Channel](flags, neededFlags, policy), + guildChannels: map[snowflake.Snowflake]snowflake.Snowflake{}, + dmChannels: map[snowflake.Snowflake]snowflake.Snowflake{}, + } +} + +type ChannelCache interface { + Cache[discord.Channel] + + GuildChannels(guildID snowflake.Snowflake) []discord.GuildChannel + GuildThreadsInChannel(channelID snowflake.Snowflake) []discord.GuildThread + + GetGuildChannel(channelID snowflake.Snowflake) (discord.GuildChannel, bool) + GetMessageChannel(channelID snowflake.Snowflake) (discord.MessageChannel, bool) + GetGuildMessageChannel(channelID snowflake.Snowflake) (discord.GuildMessageChannel, bool) + GetGuildThread(channelID snowflake.Snowflake) (discord.GuildThread, bool) + GetGuildAudioChannel(channelID snowflake.Snowflake) (discord.GuildAudioChannel, bool) + + GetGuildTextChannel(channelID snowflake.Snowflake) (discord.GuildTextChannel, bool) + GetDMChannel(channelID snowflake.Snowflake) (discord.DMChannel, bool) + GetGuildVoiceChannel(channelID snowflake.Snowflake) (discord.GuildVoiceChannel, bool) + GetGuildCategoryChannel(channelID snowflake.Snowflake) (discord.GuildCategoryChannel, bool) + GetGuildNewsChannel(channelID snowflake.Snowflake) (discord.GuildNewsChannel, bool) + GetGuildNewsThread(channelID snowflake.Snowflake) (discord.GuildThread, bool) + GetGuildPublicThread(channelID snowflake.Snowflake) (discord.GuildThread, bool) + GetGuildPrivateThread(channelID snowflake.Snowflake) (discord.GuildThread, bool) + GetGuildStageVoiceChannel(channelID snowflake.Snowflake) (discord.GuildStageVoiceChannel, bool) +} + +type ChannelCacheImpl struct { + Cache[discord.Channel] + guildChannels map[snowflake.Snowflake]snowflake.Snowflake + dmChannels map[snowflake.Snowflake]snowflake.Snowflake +} + +func (c *ChannelCacheImpl) GuildChannels(guildID snowflake.Snowflake) []discord.GuildChannel { + channels := c.FindAll(func(channel discord.Channel) bool { + if ch, ok := channel.(discord.GuildChannel); ok { + return ch.GuildID() == guildID + } + return false + }) + guildChannels := make([]discord.GuildChannel, len(channels)) + for i, channel := range channels { + guildChannels[i] = channel.(discord.GuildChannel) + } + return guildChannels +} + +func (c *ChannelCacheImpl) GuildThreadsInChannel(channelID snowflake.Snowflake) []discord.GuildThread { + channels := c.FindAll(func(channel discord.Channel) bool { + if thread, ok := channel.(discord.GuildThread); ok { + return *thread.ParentID() == channelID + } + return false + }) + threads := make([]discord.GuildThread, len(channels)) + for i, channel := range channels { + threads[i] = channel.(discord.GuildThread) + } + return threads +} + +func (c *ChannelCacheImpl) GetGuildChannel(channelID snowflake.Snowflake) (discord.GuildChannel, bool) { + if ch, ok := c.Get(channelID); ok { + if cCh, ok := ch.(discord.GuildChannel); ok { + return cCh, true + } + } + return nil, false +} + +func (c *ChannelCacheImpl) GetMessageChannel(channelID snowflake.Snowflake) (discord.MessageChannel, bool) { + if ch, ok := c.Get(channelID); ok { + if cCh, ok := ch.(discord.MessageChannel); ok { + return cCh, true + } + } + return nil, false +} + +func (c *ChannelCacheImpl) GetGuildMessageChannel(channelID snowflake.Snowflake) (discord.GuildMessageChannel, bool) { + if ch, ok := c.Get(channelID); ok { + if cCh, ok := ch.(discord.GuildMessageChannel); ok { + return cCh, true + } + } + return nil, false +} + +func (c *ChannelCacheImpl) GetGuildThread(channelID snowflake.Snowflake) (discord.GuildThread, bool) { + if ch, ok := c.Get(channelID); ok { + if cCh, ok := ch.(discord.GuildThread); ok { + return cCh, true + } + } + return discord.GuildThread{}, false +} + +func (c *ChannelCacheImpl) GetGuildAudioChannel(channelID snowflake.Snowflake) (discord.GuildAudioChannel, bool) { + if ch, ok := c.Get(channelID); ok { + if cCh, ok := ch.(discord.GuildAudioChannel); ok { + return cCh, true + } + } + return nil, false +} + +func (c *ChannelCacheImpl) GetGuildTextChannel(channelID snowflake.Snowflake) (discord.GuildTextChannel, bool) { + if ch, ok := c.Get(channelID); ok { + if cCh, ok := ch.(discord.GuildTextChannel); ok { + return cCh, true + } + } + return discord.GuildTextChannel{}, false +} + +func (c *ChannelCacheImpl) GetDMChannel(channelID snowflake.Snowflake) (discord.DMChannel, bool) { + if ch, ok := c.Get(channelID); ok { + if cCh, ok := ch.(discord.DMChannel); ok { + return cCh, true + } + } + return discord.DMChannel{}, false +} + +func (c *ChannelCacheImpl) GetGuildVoiceChannel(channelID snowflake.Snowflake) (discord.GuildVoiceChannel, bool) { + if ch, ok := c.Get(channelID); ok { + if cCh, ok := ch.(discord.GuildVoiceChannel); ok { + return cCh, true + } + } + return discord.GuildVoiceChannel{}, false +} + +func (c *ChannelCacheImpl) GetGuildCategoryChannel(channelID snowflake.Snowflake) (discord.GuildCategoryChannel, bool) { + if ch, ok := c.Get(channelID); ok { + if cCh, ok := ch.(discord.GuildCategoryChannel); ok { + return cCh, true + } + } + return discord.GuildCategoryChannel{}, false +} + +func (c *ChannelCacheImpl) GetGuildNewsChannel(channelID snowflake.Snowflake) (discord.GuildNewsChannel, bool) { + if ch, ok := c.Get(channelID); ok { + if cCh, ok := ch.(discord.GuildNewsChannel); ok { + return cCh, true + } + } + return discord.GuildNewsChannel{}, false +} + +func (c *ChannelCacheImpl) GetGuildNewsThread(channelID snowflake.Snowflake) (discord.GuildThread, bool) { + if ch, ok := c.GetGuildThread(channelID); ok && ch.Type() == discord.ChannelTypeGuildNewsThread { + return ch, true + } + return discord.GuildThread{}, false +} + +func (c *ChannelCacheImpl) GetGuildPublicThread(channelID snowflake.Snowflake) (discord.GuildThread, bool) { + if ch, ok := c.GetGuildThread(channelID); ok && ch.Type() == discord.ChannelTypeGuildPublicThread { + return ch, true + } + return discord.GuildThread{}, false +} + +func (c *ChannelCacheImpl) GetGuildPrivateThread(channelID snowflake.Snowflake) (discord.GuildThread, bool) { + if ch, ok := c.GetGuildThread(channelID); ok && ch.Type() == discord.ChannelTypeGuildPrivateThread { + return ch, true + } + return discord.GuildThread{}, false +} + +func (c *ChannelCacheImpl) GetGuildStageVoiceChannel(channelID snowflake.Snowflake) (discord.GuildStageVoiceChannel, bool) { + if ch, ok := c.Get(channelID); ok { + if cCh, ok := ch.(discord.GuildStageVoiceChannel); ok { + return cCh, true + } + } + return discord.GuildStageVoiceChannel{}, false +} diff --git a/cache/grouped_cache.go b/cache/grouped_cache.go new file mode 100644 index 00000000..c0ff7973 --- /dev/null +++ b/cache/grouped_cache.go @@ -0,0 +1,261 @@ +package cache + +import ( + "sync" + + "github.com/disgoorg/snowflake" +) + +type GroupedCacheFilterFunc[T any] func(groupID snowflake.Snowflake, entity T) bool + +type GroupedCache[T any] interface { + Get(groupID snowflake.Snowflake, id snowflake.Snowflake) (T, bool) + Put(groupID snowflake.Snowflake, id snowflake.Snowflake, entity T) + Remove(groupID snowflake.Snowflake, id snowflake.Snowflake) (T, bool) + RemoveAll(groupID snowflake.Snowflake) + RemoveIf(filterFunc GroupedCacheFilterFunc[T]) + + All() map[snowflake.Snowflake][]T + GroupAll(groupID snowflake.Snowflake) []T + + MapAll() map[snowflake.Snowflake]map[snowflake.Snowflake]T + MapGroupAll(groupID snowflake.Snowflake) map[snowflake.Snowflake]T + + FindFirst(cacheFindFunc GroupedCacheFilterFunc[T]) (T, bool) + GroupFindFirst(groupID snowflake.Snowflake, cacheFindFunc GroupedCacheFilterFunc[T]) (T, bool) + + FindAll(cacheFindFunc GroupedCacheFilterFunc[T]) []T + GroupFindAll(groupID snowflake.Snowflake, cacheFindFunc GroupedCacheFilterFunc[T]) []T + + ForEach(func(groupID snowflake.Snowflake, entity T)) + ForEachGroup(groupID snowflake.Snowflake, forEachFunc func(entity T)) +} + +var _ GroupedCache[any] = (*DefaultGroupedCache[any])(nil) + +func NewGroupedCache[T any](flags Flags, neededFlags Flags, policy Policy[T]) GroupedCache[T] { + return &DefaultGroupedCache[T]{ + flags: flags, + neededFlags: neededFlags, + policy: policy, + cache: make(map[snowflake.Snowflake]map[snowflake.Snowflake]T), + } +} + +type DefaultGroupedCache[T any] struct { + mu sync.RWMutex + flags Flags + neededFlags Flags + policy Policy[T] + cache map[snowflake.Snowflake]map[snowflake.Snowflake]T +} + +func (c *DefaultGroupedCache[T]) Get(groupID snowflake.Snowflake, id snowflake.Snowflake) (T, bool) { + c.mu.RLock() + defer c.mu.RUnlock() + + if groupEntities, ok := c.cache[groupID]; ok { + if entity, ok := groupEntities[id]; ok { + return entity, true + } + } + + var entity T + return entity, false +} + +func (c *DefaultGroupedCache[T]) Put(groupID snowflake.Snowflake, id snowflake.Snowflake, entity T) { + if c.neededFlags != FlagsNone && c.flags.Missing(c.neededFlags) { + return + } + if c.policy != nil && !c.policy(entity) { + return + } + c.mu.Lock() + defer c.mu.Unlock() + + if c.cache == nil { + c.cache = make(map[snowflake.Snowflake]map[snowflake.Snowflake]T) + } + + if groupEntities, ok := c.cache[groupID]; ok { + groupEntities[id] = entity + } else { + groupEntities = make(map[snowflake.Snowflake]T) + groupEntities[id] = entity + c.cache[groupID] = groupEntities + } +} + +func (c *DefaultGroupedCache[T]) Remove(groupID snowflake.Snowflake, id snowflake.Snowflake) (entity T, ok bool) { + c.mu.Lock() + defer c.mu.Unlock() + + if groupEntities, ok := c.cache[groupID]; ok { + if entity, ok := groupEntities[id]; ok { + delete(groupEntities, id) + return entity, ok + } + } + ok = false + return +} + +func (c *DefaultGroupedCache[T]) RemoveAll(groupID snowflake.Snowflake) { + c.mu.Lock() + defer c.mu.Unlock() + + delete(c.cache, groupID) +} + +func (c *DefaultGroupedCache[T]) RemoveIf(filterFunc GroupedCacheFilterFunc[T]) { + c.mu.Lock() + defer c.mu.Unlock() + + for groupID := range c.cache { + for id, entity := range c.cache[groupID] { + if filterFunc(groupID, entity) { + delete(c.cache[groupID], id) + } + } + } +} + +func (c *DefaultGroupedCache[T]) All() map[snowflake.Snowflake][]T { + c.mu.RLock() + defer c.mu.RUnlock() + + all := make(map[snowflake.Snowflake][]T) + for groupID, groupEntities := range c.cache { + all[groupID] = make([]T, 0, len(groupEntities)) + for _, entity := range groupEntities { + all[groupID] = append(all[groupID], entity) + } + } + + return all +} + +func (c *DefaultGroupedCache[T]) GroupAll(groupID snowflake.Snowflake) []T { + c.mu.RLock() + defer c.mu.RUnlock() + + groupEntities, ok := c.cache[groupID] + if !ok { + return nil + } + all := make([]T, 0, len(groupEntities)) + for _, entity := range groupEntities { + all = append(all, entity) + } + + return all +} + +func (c *DefaultGroupedCache[T]) MapAll() map[snowflake.Snowflake]map[snowflake.Snowflake]T { + c.mu.RLock() + defer c.mu.RUnlock() + + all := make(map[snowflake.Snowflake]map[snowflake.Snowflake]T, len(c.cache)) + for groupID, groupEntities := range c.cache { + all[groupID] = make(map[snowflake.Snowflake]T, len(groupEntities)) + for entityID, entity := range groupEntities { + all[groupID][entityID] = entity + } + } + + return all +} + +func (c *DefaultGroupedCache[T]) MapGroupAll(groupID snowflake.Snowflake) map[snowflake.Snowflake]T { + c.mu.RLock() + defer c.mu.RUnlock() + + groupEntities, ok := c.cache[groupID] + if !ok { + return nil + } + all := make(map[snowflake.Snowflake]T, len(groupEntities)) + for entityID, entity := range groupEntities { + all[entityID] = entity + } + + return all +} + +func (c *DefaultGroupedCache[T]) FindFirst(cacheFindFunc GroupedCacheFilterFunc[T]) (T, bool) { + c.mu.RLock() + defer c.mu.RUnlock() + + for groupID, groupEntities := range c.cache { + for _, entity := range groupEntities { + if cacheFindFunc(groupID, entity) { + return entity, true + } + } + } + + var entity T + return entity, false +} + +func (c *DefaultGroupedCache[T]) GroupFindFirst(groupID snowflake.Snowflake, cacheFindFunc GroupedCacheFilterFunc[T]) (T, bool) { + c.mu.RLock() + defer c.mu.RUnlock() + + for _, entity := range c.cache[groupID] { + if cacheFindFunc(groupID, entity) { + return entity, true + } + } + + var entity T + return entity, false +} + +func (c *DefaultGroupedCache[T]) FindAll(cacheFindFunc GroupedCacheFilterFunc[T]) []T { + c.mu.RLock() + defer c.mu.RUnlock() + + all := make([]T, 0) + for groupID, groupEntities := range c.cache { + for _, entity := range groupEntities { + if cacheFindFunc(groupID, entity) { + all = append(all, entity) + } + } + } + return all +} + +func (c *DefaultGroupedCache[T]) GroupFindAll(groupID snowflake.Snowflake, cacheFindFunc GroupedCacheFilterFunc[T]) []T { + c.mu.RLock() + defer c.mu.RUnlock() + + all := make([]T, 0) + for _, entity := range c.cache[groupID] { + if cacheFindFunc(groupID, entity) { + all = append(all, entity) + } + } + return all +} + +func (c *DefaultGroupedCache[T]) ForEach(forEachFunc func(groupID snowflake.Snowflake, entity T)) { + c.mu.RLock() + defer c.mu.RUnlock() + + for groupID, groupEntities := range c.cache { + for _, entity := range groupEntities { + forEachFunc(groupID, entity) + } + } +} +func (c *DefaultGroupedCache[T]) ForEachGroup(groupID snowflake.Snowflake, forEachFunc func(entity T)) { + c.mu.RLock() + defer c.mu.RUnlock() + + for _, entity := range c.cache[groupID] { + forEachFunc(entity) + } +} diff --git a/cache/guild_cache.go b/cache/guild_cache.go new file mode 100644 index 00000000..64a9d85c --- /dev/null +++ b/cache/guild_cache.go @@ -0,0 +1,114 @@ +package cache + +import ( + "sync" + + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +func NewGuildCache(flags Flags, neededFlags Flags, policy Policy[discord.Guild]) GuildCache { + return &GuildCacheImpl{ + Cache: NewCache[discord.Guild](flags, neededFlags, policy), + unreadyGuilds: map[int]map[snowflake.Snowflake]struct{}{}, + unavailableGuilds: map[snowflake.Snowflake]struct{}{}, + } +} + +type GuildCache interface { + Cache[discord.Guild] + + SetReady(shardID int, guildID snowflake.Snowflake) + SetUnready(shardID int, guildID snowflake.Snowflake) + IsUnready(shardID int, guildID snowflake.Snowflake) bool + UnreadyGuilds(shardID int) []snowflake.Snowflake + + SetUnavailable(guildID snowflake.Snowflake) + SetAvailable(guildID snowflake.Snowflake) + IsUnavailable(guildID snowflake.Snowflake) bool + UnavailableGuilds() []snowflake.Snowflake +} + +type GuildCacheImpl struct { + Cache[discord.Guild] + unreadyGuildsMu sync.RWMutex + unreadyGuilds map[int]map[snowflake.Snowflake]struct{} + + unavailableGuildsMu sync.RWMutex + unavailableGuilds map[snowflake.Snowflake]struct{} +} + +func (c *GuildCacheImpl) SetReady(shardID int, guildID snowflake.Snowflake) { + c.unreadyGuildsMu.Lock() + defer c.unreadyGuildsMu.Unlock() + if _, ok := c.unreadyGuilds[shardID]; !ok { + return + } + delete(c.unreadyGuilds[shardID], guildID) +} + +func (c *GuildCacheImpl) SetUnready(shardID int, guildID snowflake.Snowflake) { + c.unreadyGuildsMu.Lock() + defer c.unreadyGuildsMu.Unlock() + if _, ok := c.unreadyGuilds[shardID]; !ok { + c.unreadyGuilds[shardID] = map[snowflake.Snowflake]struct{}{} + } + c.unreadyGuilds[shardID][guildID] = struct{}{} +} + +func (c *GuildCacheImpl) IsUnready(shardID int, guildID snowflake.Snowflake) bool { + c.unreadyGuildsMu.RLock() + defer c.unreadyGuildsMu.RUnlock() + if _, ok := c.unreadyGuilds[shardID]; !ok { + return false + } + _, ok := c.unreadyGuilds[shardID][guildID] + return ok +} + +func (c *GuildCacheImpl) UnreadyGuilds(shardID int) []snowflake.Snowflake { + c.unreadyGuildsMu.RLock() + defer c.unreadyGuildsMu.RUnlock() + if _, ok := c.unreadyGuilds[shardID]; !ok { + return nil + } + guilds := make([]snowflake.Snowflake, len(c.unreadyGuilds[shardID])) + var i int + for guildID := range c.unreadyGuilds[shardID] { + guilds[i] = guildID + i++ + } + return guilds +} + +func (c *GuildCacheImpl) SetUnavailable(id snowflake.Snowflake) { + c.unavailableGuildsMu.Lock() + defer c.unavailableGuildsMu.Unlock() + c.Remove(id) + c.unavailableGuilds[id] = struct{}{} +} + +func (c *GuildCacheImpl) SetAvailable(guildID snowflake.Snowflake) { + c.unavailableGuildsMu.Lock() + defer c.unavailableGuildsMu.Unlock() + delete(c.unavailableGuilds, guildID) +} + +func (c *GuildCacheImpl) IsUnavailable(guildID snowflake.Snowflake) bool { + c.unavailableGuildsMu.RLock() + defer c.unavailableGuildsMu.RUnlock() + _, ok := c.unavailableGuilds[guildID] + return ok +} + +func (c *GuildCacheImpl) UnavailableGuilds() []snowflake.Snowflake { + c.unavailableGuildsMu.RLock() + defer c.unavailableGuildsMu.RUnlock() + guilds := make([]snowflake.Snowflake, len(c.unavailableGuilds)) + var i int + for guildID := range c.unavailableGuilds { + guilds[i] = guildID + i++ + } + return guilds +} diff --git a/core/application_command.go b/core/application_command.go deleted file mode 100644 index e598949e..00000000 --- a/core/application_command.go +++ /dev/null @@ -1,218 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/snowflake" -) - -type ApplicationCommand interface { - discord.ApplicationCommand -} - -type SlashCommand struct { - discord.SlashCommand - Bot *Bot -} - -// Guild returns the Guild the ApplicationCommand is from the Caches or nil if it is a global ApplicationCommand -func (c *SlashCommand) Guild() *Guild { - if c.GuildID == nil { - return nil - } - return c.Bot.Caches.Guilds().Get(*c.GuildID) -} - -// IsGlobal returns true if this is a global ApplicationCommand and false for a guild ApplicationCommand -func (c *SlashCommand) IsGlobal() bool { - - return c.GuildID == nil -} - -// ToCreate return the ApplicationCommandCreate for this ApplicationCommand -func (c *SlashCommand) ToCreate() discord.SlashCommandCreate { - return discord.SlashCommandCreate{ - CommandName: c.CommandName, - Description: c.Description, - Options: c.Options, - DefaultPermission: c.DefaultPermission, - } -} - -// Update updates the current ApplicationCommand with the given fields -func (c *SlashCommand) Update(commandUpdate discord.SlashCommandUpdate, opts ...rest.RequestOpt) (*SlashCommand, error) { - var command discord.ApplicationCommand - var err error - if c.GuildID == nil { - command, err = c.Bot.RestServices.ApplicationService().UpdateGlobalCommand(c.Bot.ApplicationID, c.ID(), commandUpdate, opts...) - - } else { - command, err = c.Bot.RestServices.ApplicationService().UpdateGuildCommand(c.Bot.ApplicationID, *c.GuildID, c.ID(), commandUpdate, opts...) - } - if err != nil { - return nil, err - } - return c.Bot.EntityBuilder.CreateApplicationCommand(command).(*SlashCommand), nil -} - -// SetPermissions sets the ApplicationCommandPermissions for a specific Guild. this overrides all existing ApplicationCommandPermission(s). thx discord for that -func (c *SlashCommand) SetPermissions(guildID snowflake.Snowflake, commandPermissions []discord.ApplicationCommandPermission, opts ...rest.RequestOpt) (*ApplicationCommandPermissions, error) { - permissions, err := c.Bot.RestServices.ApplicationService().SetGuildCommandPermissions(c.Bot.ApplicationID, guildID, c.ID(), commandPermissions, opts...) - if err != nil { - return nil, err - } - return c.Bot.EntityBuilder.CreateApplicationCommandPermissions(*permissions), nil -} - -// GetPermissions fetched the ApplicationCommandPermissions for a specific Guild from discord -func (c *SlashCommand) GetPermissions(guildID snowflake.Snowflake, opts ...rest.RequestOpt) (*ApplicationCommandPermissions, error) { - permissions, err := c.Bot.RestServices.ApplicationService().GetGuildCommandPermissions(c.Bot.ApplicationID, guildID, c.ID(), opts...) - if err != nil { - return nil, err - } - return c.Bot.EntityBuilder.CreateApplicationCommandPermissions(*permissions), nil -} - -// Delete deletes the ApplicationCommand from discord -func (c *SlashCommand) Delete(opts ...rest.RequestOpt) error { - if c.GuildID == nil { - return c.Bot.RestServices.ApplicationService().DeleteGlobalCommand(c.Bot.ApplicationID, c.ID()) - } - return c.Bot.RestServices.ApplicationService().DeleteGuildCommand(c.Bot.ApplicationID, *c.GuildID, c.ID(), opts...) -} - -type UserCommand struct { - discord.UserCommand - Bot *Bot -} - -// Guild returns the Guild the ApplicationCommand is from the Caches or nil if it is a global ApplicationCommand -func (c *UserCommand) Guild() *Guild { - if c.GuildID == nil { - return nil - } - return c.Bot.Caches.Guilds().Get(*c.GuildID) -} - -// IsGlobal returns true if this is a global ApplicationCommand and false for a guild ApplicationCommand -func (c *UserCommand) IsGlobal() bool { - return c.GuildID == nil -} - -// ToCreate return the ApplicationCommandCreate for this ApplicationCommand -func (c *UserCommand) ToCreate() discord.UserCommandCreate { - return discord.UserCommandCreate{ - CommandName: c.CommandName, - DefaultPermission: c.DefaultPermission, - } -} - -// Update updates the current ApplicationCommand with the given fields -func (c *UserCommand) Update(commandUpdate discord.UserCommandUpdate, opts ...rest.RequestOpt) (*UserCommand, error) { - var command discord.ApplicationCommand - var err error - if c.GuildID == nil { - command, err = c.Bot.RestServices.ApplicationService().UpdateGlobalCommand(c.Bot.ApplicationID, c.ID(), commandUpdate, opts...) - - } else { - command, err = c.Bot.RestServices.ApplicationService().UpdateGuildCommand(c.Bot.ApplicationID, *c.GuildID, c.ID(), commandUpdate, opts...) - } - if err != nil { - return nil, err - } - return c.Bot.EntityBuilder.CreateApplicationCommand(command).(*UserCommand), nil -} - -// SetPermissions sets the ApplicationCommandPermissions for a specific Guild. this overrides all existing ApplicationCommandPermission(s). thx discord for that -func (c *UserCommand) SetPermissions(guildID snowflake.Snowflake, commandPermissions []discord.ApplicationCommandPermission, opts ...rest.RequestOpt) (*ApplicationCommandPermissions, error) { - permissions, err := c.Bot.RestServices.ApplicationService().SetGuildCommandPermissions(c.Bot.ApplicationID, guildID, c.ID(), commandPermissions, opts...) - if err != nil { - return nil, err - } - return c.Bot.EntityBuilder.CreateApplicationCommandPermissions(*permissions), nil -} - -// GetPermissions fetched the ApplicationCommandPermissions for a specific Guild from discord -func (c *UserCommand) GetPermissions(guildID snowflake.Snowflake, opts ...rest.RequestOpt) (*ApplicationCommandPermissions, error) { - permissions, err := c.Bot.RestServices.ApplicationService().GetGuildCommandPermissions(c.Bot.ApplicationID, guildID, c.ID(), opts...) - if err != nil { - return nil, err - } - return c.Bot.EntityBuilder.CreateApplicationCommandPermissions(*permissions), nil -} - -// Delete deletes the ApplicationCommand from discord -func (c *UserCommand) Delete(opts ...rest.RequestOpt) error { - if c.GuildID == nil { - return c.Bot.RestServices.ApplicationService().DeleteGlobalCommand(c.Bot.ApplicationID, c.ID()) - } - return c.Bot.RestServices.ApplicationService().DeleteGuildCommand(c.Bot.ApplicationID, *c.GuildID, c.ID(), opts...) -} - -type MessageCommand struct { - discord.MessageCommand - Bot *Bot -} - -// Guild returns the Guild the ApplicationCommand is from the Caches or nil if it is a global ApplicationCommand -func (c *MessageCommand) Guild() *Guild { - if c.GuildID == nil { - return nil - } - return c.Bot.Caches.Guilds().Get(*c.GuildID) -} - -// IsGlobal returns true if this is a global ApplicationCommand and false for a guild ApplicationCommand -func (c *MessageCommand) IsGlobal() bool { - return c.GuildID == nil -} - -// ToCreate return the ApplicationCommandCreate for this ApplicationCommand -func (c *MessageCommand) ToCreate() discord.MessageCommandCreate { - return discord.MessageCommandCreate{ - CommandName: c.CommandName, - DefaultPermission: c.DefaultPermission, - } -} - -// Update updates the current ApplicationCommand with the given discord.ApplicationCommandUpdate -func (c *MessageCommand) Update(commandUpdate discord.MessageCommandUpdate, opts ...rest.RequestOpt) (*MessageCommand, error) { - var command discord.ApplicationCommand - var err error - if c.GuildID == nil { - command, err = c.Bot.RestServices.ApplicationService().UpdateGlobalCommand(c.Bot.ApplicationID, c.ID(), commandUpdate, opts...) - - } else { - command, err = c.Bot.RestServices.ApplicationService().UpdateGuildCommand(c.Bot.ApplicationID, *c.GuildID, c.ID(), commandUpdate, opts...) - } - if err != nil { - return nil, err - } - return c.Bot.EntityBuilder.CreateApplicationCommand(command).(*MessageCommand), nil -} - -// SetPermissions sets the ApplicationCommandPermissions for a specific Guild. this overrides all existing ApplicationCommandPermission(s). thx discord for that -func (c *MessageCommand) SetPermissions(guildID snowflake.Snowflake, commandPermissions []discord.ApplicationCommandPermission, opts ...rest.RequestOpt) (*ApplicationCommandPermissions, error) { - permissions, err := c.Bot.RestServices.ApplicationService().SetGuildCommandPermissions(c.Bot.ApplicationID, guildID, c.ID(), commandPermissions, opts...) - if err != nil { - return nil, err - } - return c.Bot.EntityBuilder.CreateApplicationCommandPermissions(*permissions), nil -} - -// GetPermissions fetched the ApplicationCommandPermissions for a specific Guild from discord -func (c *MessageCommand) GetPermissions(guildID snowflake.Snowflake, opts ...rest.RequestOpt) (*ApplicationCommandPermissions, error) { - permissions, err := c.Bot.RestServices.ApplicationService().GetGuildCommandPermissions(c.Bot.ApplicationID, guildID, c.ID(), opts...) - if err != nil { - return nil, err - } - return c.Bot.EntityBuilder.CreateApplicationCommandPermissions(*permissions), nil -} - -// Delete deletes the ApplicationCommand from discord -func (c *MessageCommand) Delete(opts ...rest.RequestOpt) error { - if c.GuildID == nil { - return c.Bot.RestServices.ApplicationService().DeleteGlobalCommand(c.Bot.ApplicationID, c.ID()) - } - return c.Bot.RestServices.ApplicationService().DeleteGuildCommand(c.Bot.ApplicationID, *c.GuildID, c.ID(), opts...) -} diff --git a/core/application_command_interaction.go b/core/application_command_interaction.go deleted file mode 100644 index e9fe3f13..00000000 --- a/core/application_command_interaction.go +++ /dev/null @@ -1,102 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/snowflake" -) - -type ApplicationCommandInteractionFilter func(interaction *ApplicationCommandInteraction) bool - -var _ Interaction = (*ApplicationCommandInteraction)(nil) - -// ApplicationCommandInteraction represents a generic ApplicationCommandInteraction received from discord -type ApplicationCommandInteraction struct { - CreateInteraction - Data ApplicationCommandInteractionData -} - -func (i ApplicationCommandInteraction) interaction() {} -func (i ApplicationCommandInteraction) Type() discord.InteractionType { - return discord.InteractionTypeApplicationCommand -} - -func (i ApplicationCommandInteraction) SlashCommandInteractionData() SlashCommandInteractionData { - return i.Data.(SlashCommandInteractionData) -} - -func (i ApplicationCommandInteraction) UserCommandInteractionData() UserCommandInteractionData { - return i.Data.(UserCommandInteractionData) -} - -func (i ApplicationCommandInteraction) MessageCommandInteractionData() MessageCommandInteractionData { - return i.Data.(MessageCommandInteractionData) -} - -func (i ApplicationCommandInteraction) CreateModal(modalCreate discord.ModalCreate, opts ...rest.RequestOpt) error { - return i.Respond(discord.InteractionCallbackTypeModal, modalCreate, opts...) -} - -type ApplicationCommandInteractionData interface { - discord.ApplicationCommandInteractionData -} - -type SlashCommandInteractionData struct { - discord.SlashCommandInteractionData - SubCommandName *string - SubCommandGroupName *string - Resolved *SlashCommandResolved - Options SlashCommandOptionsMap -} - -// CommandPath returns the ApplicationCommand path -func (i SlashCommandInteractionData) CommandPath() string { - path := i.CommandName - if name := i.SubCommandName; name != nil { - path += "/" + *name - } - if name := i.SubCommandGroupName; name != nil { - path += "/" + *name - } - return path -} - -// SlashCommandResolved contains resolved mention data for SlashCommand(s) -type SlashCommandResolved struct { - Users map[snowflake.Snowflake]*User - Members map[snowflake.Snowflake]*Member - Roles map[snowflake.Snowflake]*Role - Channels map[snowflake.Snowflake]Channel - Attachments map[snowflake.Snowflake]discord.Attachment -} - -type UserCommandInteractionData struct { - discord.UserCommandInteractionData - Resolved *UserCommandResolved -} - -func (i *UserCommandInteractionData) TargetUser() *User { - return i.Resolved.Users[i.TargetID] -} - -func (i *UserCommandInteractionData) TargetMember() *Member { - return i.Resolved.Members[i.TargetID] -} - -type UserCommandResolved struct { - Users map[snowflake.Snowflake]*User - Members map[snowflake.Snowflake]*Member -} - -type MessageCommandInteractionData struct { - discord.MessageCommandInteractionData - Resolved *MessageCommandResolved -} - -func (i *MessageCommandInteractionData) TargetMessage() *Message { - return i.Resolved.Messages[i.TargetID] -} - -type MessageCommandResolved struct { - Messages map[snowflake.Snowflake]*Message -} diff --git a/core/application_command_permissions.go b/core/application_command_permissions.go deleted file mode 100644 index 087cd70e..00000000 --- a/core/application_command_permissions.go +++ /dev/null @@ -1,12 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" -) - -type ApplicationCommandPermissions struct { - discord.ApplicationCommandPermissions - Bot *Bot -} - -// TODO: implement methods to update diff --git a/core/audio_controller.go b/core/audio_controller.go deleted file mode 100644 index 3746e4dd..00000000 --- a/core/audio_controller.go +++ /dev/null @@ -1,66 +0,0 @@ -package core - -import ( - "context" - - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/snowflake" -) - -// AudioController lets you Connect / Disconnect from a Channel -type AudioController interface { - // Bot returns the core.Bot instance - Bot() *Bot - - // Connect sends a discord.GatewayCommand to connect to the specified Channel - Connect(ctx context.Context, guildID snowflake.Snowflake, channelID snowflake.Snowflake) error - - // Disconnect sends a discord.GatewayCommand to disconnect from a Channel - Disconnect(ctx context.Context, guildID snowflake.Snowflake) error -} - -func NewAudioController(bot *Bot) AudioController { - return &audioControllerImpl{bot: bot} -} - -type audioControllerImpl struct { - bot *Bot -} - -func (c *audioControllerImpl) Bot() *Bot { - return c.bot -} - -func (c *audioControllerImpl) Connect(ctx context.Context, guildID snowflake.Snowflake, channelID snowflake.Snowflake) error { - shard, err := c.getShard(guildID) - if err != nil { - return err - } - return shard.Send(ctx, discord.NewGatewayCommand(discord.GatewayOpcodeVoiceStateUpdate, discord.UpdateVoiceStateCommandData{ - GuildID: guildID, - ChannelID: &channelID, - })) -} - -func (c *audioControllerImpl) Disconnect(ctx context.Context, guildID snowflake.Snowflake) error { - shard, err := c.getShard(guildID) - if err != nil { - return err - } - return shard.Send(ctx, discord.NewGatewayCommand(discord.GatewayOpcodeVoiceStateUpdate, discord.UpdateVoiceStateCommandData{ - GuildID: guildID, - ChannelID: nil, - })) -} - -func (c *audioControllerImpl) getShard(guildID snowflake.Snowflake) (gateway.Gateway, error) { - shard, err := c.Bot().Shard(guildID) - if err != nil { - return nil, err - } - if shard.Status() != gateway.StatusReady { - return nil, discord.ErrShardNotConnected - } - return shard, nil -} diff --git a/core/audit_log.go b/core/audit_log.go deleted file mode 100644 index a39dffdb..00000000 --- a/core/audit_log.go +++ /dev/null @@ -1,44 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/snowflake" -) - -type AuditLog struct { - discord.AuditLog - GuildScheduledEvents map[snowflake.Snowflake]*GuildScheduledEvent - Integrations map[snowflake.Snowflake]Integration - Threads map[snowflake.Snowflake]GuildThread - Users map[snowflake.Snowflake]*User - Webhooks map[snowflake.Snowflake]Webhook - GuildID snowflake.Snowflake - FilterOptions AuditLogFilterOptions - Bot *Bot -} - -func (l *AuditLog) Guild() *Guild { - return l.Bot.Caches.Guilds().Get(l.GuildID) -} - -// AuditLogFilterOptions fields used to filter audit-log retrieving -type AuditLogFilterOptions struct { - UserID snowflake.Snowflake - ActionType discord.AuditLogEvent - Before snowflake.Snowflake - Limit int -} - -// Before gets new AuditLog(s) from Discord before the last one -func (l *AuditLog) Before(opts ...rest.RequestOpt) (*AuditLog, error) { - before := snowflake.Snowflake("") - if len(l.Entries) > 0 { - before = l.Entries[len(l.Entries)-1].ID - } - auditLog, err := l.Bot.RestServices.AuditLogService().GetAuditLog(l.GuildID, l.FilterOptions.UserID, l.FilterOptions.ActionType, before, l.FilterOptions.Limit, opts...) - if err != nil { - return nil, err - } - return l.Bot.EntityBuilder.CreateAuditLog(l.GuildID, *auditLog, l.FilterOptions, CacheStrategyNoWs), nil -} diff --git a/core/autocomplete_interaction.go b/core/autocomplete_interaction.go deleted file mode 100644 index 7704f63f..00000000 --- a/core/autocomplete_interaction.go +++ /dev/null @@ -1,280 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/snowflake" -) - -type AutocompleteInteractionFilter func(autocompleteInteraction *AutocompleteInteraction) bool - -var _ Interaction = (*AutocompleteInteraction)(nil) - -type AutocompleteInteraction struct { - *BaseInteraction - Data AutocompleteInteractionData -} - -func (i AutocompleteInteraction) interaction() {} -func (i AutocompleteInteraction) Type() discord.InteractionType { - return discord.InteractionTypeAutocomplete -} - -func (i AutocompleteInteraction) Result(choices []discord.AutocompleteChoice, opts ...rest.RequestOpt) error { - return i.Respond(discord.InteractionCallbackTypeAutocompleteResult, discord.AutocompleteResult{Choices: choices}, opts...) -} - -func (i AutocompleteInteraction) ResultMapString(resultMap map[string]string, opts ...rest.RequestOpt) error { - choices := make([]discord.AutocompleteChoice, len(resultMap)) - ii := 0 - for name, value := range resultMap { - choices[ii] = discord.AutocompleteChoiceString{ - Name: name, - Value: value, - } - ii++ - } - return i.Result(choices, opts...) -} - -func (i AutocompleteInteraction) ResultMapInt(resultMap map[string]int, opts ...rest.RequestOpt) error { - choices := make([]discord.AutocompleteChoice, len(resultMap)) - ii := 0 - for name, value := range resultMap { - choices[ii] = discord.AutocompleteChoiceInt{ - Name: name, - Value: value, - } - ii++ - } - return i.Result(choices, opts...) -} - -func (i AutocompleteInteraction) ResultMapFloat(resultMap map[string]float64, opts ...rest.RequestOpt) error { - choices := make([]discord.AutocompleteChoice, len(resultMap)) - ii := 0 - for name, value := range resultMap { - choices[ii] = discord.AutocompleteChoiceFloat{ - Name: name, - Value: value, - } - ii++ - } - return i.Result(choices, opts...) -} - -type AutocompleteInteractionData struct { - discord.AutocompleteInteractionData - SubCommandName *string - SubCommandGroupName *string - Options AutocompleteOptionsMap -} - -// CommandPath returns the ApplicationCommand path -func (i *AutocompleteInteractionData) CommandPath() string { - path := i.CommandName - if name := i.SubCommandName; name != nil { - path += "/" + *name - } - if name := i.SubCommandGroupName; name != nil { - path += "/" + *name - } - return path -} - -type AutocompleteOptionsMap map[string]discord.AutocompleteOption - -func (m AutocompleteOptionsMap) Get(name string) discord.AutocompleteOption { - if option, ok := m[name]; ok { - return option - } - return nil -} - -func (m AutocompleteOptionsMap) StringOption(name string) *discord.AutocompleteOptionString { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(discord.AutocompleteOptionString); ok { - return &opt - } - return nil -} - -func (m AutocompleteOptionsMap) String(name string) *string { - option := m.StringOption(name) - if option == nil { - return nil - } - return &option.Value -} - -func (m AutocompleteOptionsMap) IntOption(name string) *discord.AutocompleteOptionInt { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(discord.AutocompleteOptionInt); ok { - return &opt - } - return nil -} - -func (m AutocompleteOptionsMap) Int(name string) *int { - option := m.IntOption(name) - if option == nil { - return nil - } - return &option.Value -} - -func (m AutocompleteOptionsMap) BoolOption(name string) *discord.AutocompleteOptionBool { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(discord.AutocompleteOptionBool); ok { - return &opt - } - return nil -} - -func (m AutocompleteOptionsMap) Bool(name string) *bool { - option := m.BoolOption(name) - if option == nil { - return nil - } - return &option.Value -} - -func (m AutocompleteOptionsMap) UserOption(name string) *discord.AutocompleteOptionUser { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(discord.AutocompleteOptionUser); ok { - return &opt - } - return nil -} - -func (m AutocompleteOptionsMap) ChannelOption(name string) *discord.AutocompleteOptionChannel { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(discord.AutocompleteOptionChannel); ok { - return &opt - } - return nil -} - -func (m AutocompleteOptionsMap) RoleOption(name string) *discord.AutocompleteOptionRole { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(discord.AutocompleteOptionRole); ok { - return &opt - } - return nil -} - -func (m AutocompleteOptionsMap) MentionableOption(name string) *discord.AutocompleteOptionMentionable { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(discord.AutocompleteOptionMentionable); ok { - return &opt - } - return nil -} - -func (m AutocompleteOptionsMap) Snowflake(name string) *snowflake.Snowflake { - option := m.Get(name) - if option == nil { - return nil - } - switch opt := option.(type) { - case discord.AutocompleteOptionChannel: - return &opt.Value - - case discord.AutocompleteOptionRole: - return &opt.Value - - case discord.AutocompleteOptionUser: - return &opt.Value - - case discord.AutocompleteOptionMentionable: - return &opt.Value - - default: - return nil - } -} - -func (m AutocompleteOptionsMap) FloatOption(name string) *discord.AutocompleteOptionFloat { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(discord.AutocompleteOptionFloat); ok { - return &opt - } - return nil -} - -func (m AutocompleteOptionsMap) Float(name string) *float64 { - option := m.FloatOption(name) - if option == nil { - return nil - } - return &option.Value -} - -func (m AutocompleteOptionsMap) GetAll() []discord.AutocompleteOption { - options := make([]discord.AutocompleteOption, len(m)) - i := 0 - for _, option := range m { - options[i] = option - i++ - } - return options -} - -func (m AutocompleteOptionsMap) GetByType(optionType discord.ApplicationCommandOptionType) []discord.AutocompleteOption { - return m.FindAll(func(option discord.AutocompleteOption) bool { - return option.Type() == optionType - }) -} - -func (m AutocompleteOptionsMap) Find(optionFindFunc func(option discord.AutocompleteOption) bool) discord.AutocompleteOption { - for _, option := range m { - if optionFindFunc(option) { - return option - } - } - return nil -} - -func (m AutocompleteOptionsMap) FindAll(optionFindFunc func(option discord.AutocompleteOption) bool) []discord.AutocompleteOption { - var options []discord.AutocompleteOption - for _, option := range m { - if optionFindFunc(option) { - options = append(options, option) - } - } - return options -} - -func (m AutocompleteOptionsMap) Focused(name string) bool { - return m.Get(name).Focused() -} - -func (m AutocompleteOptionsMap) FocusedOption() discord.AutocompleteOption { - return m.Find(func(option discord.AutocompleteOption) bool { - return option.Focused() - }) -} diff --git a/core/ban.go b/core/ban.go deleted file mode 100644 index c0cf9e6e..00000000 --- a/core/ban.go +++ /dev/null @@ -1,20 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/snowflake" -) - -// Ban represents a banned User from a Guild (https://discord.com/developers/docs/resources/guild#ban-object) -type Ban struct { - discord.Ban - Bot *Bot - User *User - GuildID snowflake.Snowflake -} - -// Unban unbans the User associated with this Ban from the Guild -func (b *Ban) Unban(opts ...rest.RequestOpt) error { - return b.Bot.RestServices.GuildService().DeleteBan(b.GuildID, b.User.ID, opts...) -} diff --git a/core/bot.go b/core/bot.go deleted file mode 100644 index a5b63e4a..00000000 --- a/core/bot.go +++ /dev/null @@ -1,373 +0,0 @@ -package core - -import ( - "context" - - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/disgo/gateway/sharding" - "github.com/DisgoOrg/disgo/httpserver" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/log" - "github.com/DisgoOrg/snowflake" -) - -// Bot is the main discord client -type Bot struct { - Token string - ApplicationID snowflake.Snowflake - ClientID snowflake.Snowflake - SelfUser *SelfUser - - Logger log.Logger - - RestServices rest.Services - - EventManager EventManager - Collectors Collectors - - ShardManager sharding.ShardManager - Gateway gateway.Gateway - - HTTPServer httpserver.Server - - Caches Caches - - EntityBuilder EntityBuilder - AudioController AudioController - MemberChunkingManager MemberChunkingManager -} - -// Close will clean up all disgo internals and close the discord connection safely -func (b *Bot) Close(ctx context.Context) { - if b.RestServices != nil { - b.RestServices.Close(ctx) - } - if b.Gateway != nil { - b.Gateway.Close(ctx) - } - if b.ShardManager != nil { - b.ShardManager.Close(ctx) - } - if b.HTTPServer != nil { - b.HTTPServer.Close(ctx) - } -} - -// SelfMember returns a core.OAuth2User for the client, if available -func (b *Bot) SelfMember(guildID snowflake.Snowflake) *Member { - return b.Caches.Members().Get(guildID, b.ClientID) -} - -// AddEventListeners adds one or more EventListener(s) to the EventManager -func (b *Bot) AddEventListeners(listeners ...EventListener) { - b.EventManager.AddEventListeners(listeners...) -} - -// RemoveEventListeners removes one or more EventListener(s) from the EventManager -func (b *Bot) RemoveEventListeners(listeners ...EventListener) { - b.EventManager.RemoveEventListeners(listeners...) -} - -// ConnectGateway opens the gateway connection to discord -func (b *Bot) ConnectGateway(ctx context.Context) error { - if b.Gateway == nil { - return discord.ErrNoGateway - } - return b.Gateway.Open(ctx) -} - -// ConnectShardManager opens the gateway connection to discord -func (b *Bot) ConnectShardManager(ctx context.Context) error { - if b.ShardManager == nil { - return discord.ErrNoShardManager - } - b.ShardManager.Open(ctx) - return nil -} - -// HasGateway returns whether this Bot has an active gateway.Gateway connection -func (b *Bot) HasGateway() bool { - return b.Gateway != nil -} - -// HasShardManager returns whether this Bot is sharded -func (b *Bot) HasShardManager() bool { - return b.ShardManager != nil -} - -func (b *Bot) Shard(guildID snowflake.Snowflake) (gateway.Gateway, error) { - if b.HasGateway() { - return b.Gateway, nil - } else if b.HasShardManager() { - shard := b.ShardManager.GetGuildShard(guildID) - if shard == nil { - return nil, discord.ErrShardNotFound - } - return shard, nil - } - return nil, discord.ErrNoGatewayOrShardManager -} - -func (b *Bot) SetPresence(ctx context.Context, presenceUpdate discord.UpdatePresenceCommandData) error { - if !b.HasGateway() { - return discord.ErrNoGateway - } - return b.Gateway.Send(ctx, discord.NewGatewayCommand(discord.GatewayOpcodePresenceUpdate, presenceUpdate)) -} - -// SetPresenceForShard sets the Presence of this Bot for the provided shard -func (b *Bot) SetPresenceForShard(ctx context.Context, shardId int, presenceUpdate discord.UpdatePresenceCommandData) error { - if !b.HasShardManager() { - return discord.ErrNoShardManager - } - shard := b.ShardManager.Shard(shardId) - if shard == nil { - return discord.ErrShardNotFound - } - return shard.Send(ctx, discord.NewGatewayCommand(discord.GatewayOpcodePresenceUpdate, presenceUpdate)) -} - -// StartHTTPServer starts the interaction webhook server -func (b *Bot) StartHTTPServer() error { - if b.HTTPServer == nil { - return discord.ErrNoHTTPServer - } - b.HTTPServer.Start() - return nil -} - -// HasHTTPServer returns whether Bot has an active httpserver.Server -func (b *Bot) HasHTTPServer() bool { - return b.HTTPServer != nil -} - -// GetCommand fetches a specific global discord.ApplicationCommand -func (b *Bot) GetCommand(commandID snowflake.Snowflake, opts ...rest.RequestOpt) (ApplicationCommand, error) { - command, err := b.RestServices.ApplicationService().GetGlobalCommand(b.ApplicationID, commandID, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateApplicationCommand(command), nil -} - -// GetCommands fetches all global discord.ApplicationCommand(s) -func (b *Bot) GetCommands(opts ...rest.RequestOpt) ([]ApplicationCommand, error) { - cmds, err := b.RestServices.ApplicationService().GetGlobalCommands(b.ApplicationID, opts...) - if err != nil { - return nil, err - } - commands := make([]ApplicationCommand, len(cmds)) - for i, command := range cmds { - commands[i] = b.EntityBuilder.CreateApplicationCommand(command) - } - return commands, nil -} - -// CreateCommand creates a new global discord.ApplicationCommand -func (b *Bot) CreateCommand(commandCreate discord.ApplicationCommandCreate, opts ...rest.RequestOpt) (ApplicationCommand, error) { - command, err := b.RestServices.ApplicationService().CreateGlobalCommand(b.ApplicationID, commandCreate, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateApplicationCommand(command), nil -} - -// EditCommand edits a specific global discord.ApplicationCommand -func (b *Bot) EditCommand(commandID snowflake.Snowflake, commandUpdate discord.ApplicationCommandUpdate, opts ...rest.RequestOpt) (ApplicationCommand, error) { - command, err := b.RestServices.ApplicationService().UpdateGlobalCommand(b.ApplicationID, commandID, commandUpdate, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateApplicationCommand(command), nil -} - -// DeleteCommand creates a new global discord.ApplicationCommand -func (b *Bot) DeleteCommand(commandID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return b.RestServices.ApplicationService().DeleteGlobalCommand(b.ApplicationID, commandID, opts...) -} - -// SetCommands overrides all global discord.ApplicationCommand(s) -func (b *Bot) SetCommands(commandCreates []discord.ApplicationCommandCreate, opts ...rest.RequestOpt) ([]ApplicationCommand, error) { - cmds, err := b.RestServices.ApplicationService().SetGlobalCommands(b.ApplicationID, commandCreates, opts...) - if err != nil { - return nil, err - } - commands := make([]ApplicationCommand, len(cmds)) - for i, command := range cmds { - commands[i] = b.EntityBuilder.CreateApplicationCommand(command) - } - return commands, nil -} - -// GetGuildCommand fetches a specific Guild discord.ApplicationCommand -func (b *Bot) GetGuildCommand(guildID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...rest.RequestOpt) (ApplicationCommand, error) { - command, err := b.RestServices.ApplicationService().GetGuildCommand(b.ApplicationID, guildID, commandID, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateApplicationCommand(command), nil -} - -// GetGuildCommands fetches all Guild discord.ApplicationCommand(s) -func (b *Bot) GetGuildCommands(guildID snowflake.Snowflake, opts ...rest.RequestOpt) ([]ApplicationCommand, error) { - cmds, err := b.RestServices.ApplicationService().GetGuildCommands(b.ApplicationID, guildID, opts...) - if err != nil { - return nil, err - } - commands := make([]ApplicationCommand, len(cmds)) - for i, command := range cmds { - commands[i] = b.EntityBuilder.CreateApplicationCommand(command) - } - return commands, nil -} - -// CreateGuildCommand creates a new Guild discord.ApplicationCommand -func (b *Bot) CreateGuildCommand(guildID snowflake.Snowflake, commandCreate discord.ApplicationCommandCreate, opts ...rest.RequestOpt) (ApplicationCommand, error) { - command, err := b.RestServices.ApplicationService().CreateGuildCommand(b.ApplicationID, guildID, commandCreate, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateApplicationCommand(command), nil -} - -// EditGuildCommand edits a specific Guild discord.ApplicationCommand -func (b *Bot) EditGuildCommand(guildID snowflake.Snowflake, commandID snowflake.Snowflake, commandUpdate discord.ApplicationCommandUpdate, opts ...rest.RequestOpt) (ApplicationCommand, error) { - command, err := b.RestServices.ApplicationService().UpdateGuildCommand(b.ApplicationID, guildID, commandID, commandUpdate, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateApplicationCommand(command), nil -} - -// DeleteGuildCommand creates a new Guild discord.ApplicationCommand -func (b *Bot) DeleteGuildCommand(guildID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return b.RestServices.ApplicationService().DeleteGuildCommand(b.ApplicationID, guildID, commandID, opts...) -} - -// SetGuildCommands overrides all Guild discord.ApplicationCommand(s) -func (b *Bot) SetGuildCommands(guildID snowflake.Snowflake, commandCreates []discord.ApplicationCommandCreate, opts ...rest.RequestOpt) ([]ApplicationCommand, error) { - cmds, err := b.RestServices.ApplicationService().SetGuildCommands(b.ApplicationID, guildID, commandCreates, opts...) - if err != nil { - return nil, err - } - commands := make([]ApplicationCommand, len(cmds)) - for i, command := range cmds { - commands[i] = b.EntityBuilder.CreateApplicationCommand(command) - } - return commands, nil -} - -// GetGuildCommandsPermissions returns the core.ApplicationCommandPermissions for an all discord.ApplicationCommand(s) in an core.Guild -func (b *Bot) GetGuildCommandsPermissions(guildID snowflake.Snowflake, opts ...rest.RequestOpt) ([]*ApplicationCommandPermissions, error) { - perms, err := b.RestServices.ApplicationService().GetGuildCommandsPermissions(b.ApplicationID, guildID, opts...) - if err != nil { - return nil, err - } - permissions := make([]*ApplicationCommandPermissions, len(perms)) - for i, permission := range perms { - permissions[i] = b.EntityBuilder.CreateApplicationCommandPermissions(permission) - } - return permissions, nil -} - -// GetGuildCommandPermissions returns the core.ApplicationCommandPermissions for a specific discord.ApplicationCommand in a core.Guild -func (b *Bot) GetGuildCommandPermissions(guildID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...rest.RequestOpt) (*ApplicationCommandPermissions, error) { - permissions, err := b.RestServices.ApplicationService().GetGuildCommandPermissions(b.ApplicationID, guildID, commandID, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateApplicationCommandPermissions(*permissions), nil -} - -// SetGuildCommandsPermissions sets the discord.ApplicationCommandPermissions for all discord.ApplicationCommand(s) -func (b *Bot) SetGuildCommandsPermissions(guildID snowflake.Snowflake, commandPermissions []discord.ApplicationCommandPermissionsSet, opts ...rest.RequestOpt) ([]*ApplicationCommandPermissions, error) { - perms, err := b.RestServices.ApplicationService().SetGuildCommandsPermissions(b.ApplicationID, guildID, commandPermissions, opts...) - if err != nil { - return nil, err - } - permissions := make([]*ApplicationCommandPermissions, len(perms)) - for i, permission := range perms { - permissions[i] = b.EntityBuilder.CreateApplicationCommandPermissions(permission) - } - return permissions, nil -} - -// SetGuildCommandPermissions sets the core.ApplicationCommandPermissions for a specific discord.ApplicationCommand -func (b *Bot) SetGuildCommandPermissions(guildID snowflake.Snowflake, commandID snowflake.Snowflake, permissions []discord.ApplicationCommandPermission, opts ...rest.RequestOpt) (*ApplicationCommandPermissions, error) { - perms, err := b.RestServices.ApplicationService().SetGuildCommandPermissions(b.ApplicationID, guildID, commandID, permissions, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateApplicationCommandPermissions(*perms), nil -} - -// GetTemplate gets a core.GuildTemplate by its code -func (b *Bot) GetTemplate(code string, opts ...rest.RequestOpt) (*GuildTemplate, error) { - guildTemplate, err := b.RestServices.GuildTemplateService().GetGuildTemplate(code, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateGuildTemplate(*guildTemplate, CacheStrategyNoWs), nil -} - -// CreateGuildFromTemplate creates a core.Guild using a core.GuildTemplate code -func (b *Bot) CreateGuildFromTemplate(templateCode string, createGuildFromTemplate discord.GuildFromTemplateCreate, opts ...rest.RequestOpt) (*Guild, error) { - guild, err := b.RestServices.GuildTemplateService().CreateGuildFromTemplate(templateCode, createGuildFromTemplate, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateGuild(*guild, CacheStrategyNoWs), nil -} - -func (b *Bot) GetInvite(inviteCode string, opts ...rest.RequestOpt) (*Invite, error) { - invite, err := b.RestServices.InviteService().GetInvite(inviteCode, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateInvite(*invite, CacheStrategyNoWs), nil -} - -func (b *Bot) DeleteInvite(inviteCode string, opts ...rest.RequestOpt) (*Invite, error) { - invite, err := b.RestServices.InviteService().DeleteInvite(inviteCode, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateInvite(*invite, CacheStrategyNoWs), nil -} - -func (b *Bot) GetNitroStickerPacks(opts ...rest.RequestOpt) ([]*StickerPack, error) { - stickerPacks, err := b.RestServices.StickerService().GetNitroStickerPacks(opts...) - if err != nil { - return nil, err - } - coreStickerPacks := make([]*StickerPack, len(stickerPacks)) - for i, stickerPack := range stickerPacks { - coreStickerPacks[i] = b.EntityBuilder.CreateStickerPack(stickerPack, CacheStrategyNoWs) - } - return coreStickerPacks, nil -} - -func (b *Bot) GetSticker(stickerID snowflake.Snowflake, opts ...rest.RequestOpt) (*Sticker, error) { - sticker, err := b.RestServices.StickerService().GetSticker(stickerID, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateSticker(*sticker, CacheStrategyNoWs), nil -} - -func (b *Bot) CreateDMChannel(userID snowflake.Snowflake, opts ...rest.RequestOpt) (*DMChannel, error) { - sticker, err := b.RestServices.UserService().CreateDMChannel(userID, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateChannel(*sticker, CacheStrategyNoWs).(*DMChannel), nil -} - -func (b *Bot) GetUser(userID snowflake.Snowflake, opts ...rest.RequestOpt) (*User, error) { - user, err := b.RestServices.UserService().GetUser(userID, opts...) - if err != nil { - return nil, err - } - return b.EntityBuilder.CreateUser(*user, CacheStrategyNoWs), nil -} diff --git a/core/bot/bot.go b/core/bot/bot.go deleted file mode 100644 index 8f84b9f4..00000000 --- a/core/bot/bot.go +++ /dev/null @@ -1,173 +0,0 @@ -package bot - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/collectors" - "github.com/DisgoOrg/disgo/core/handlers" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/disgo/gateway/sharding" - "github.com/DisgoOrg/disgo/gateway/sharding/srate" - "github.com/DisgoOrg/disgo/httpserver" - "github.com/DisgoOrg/disgo/internal/tokenhelper" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/log" - "github.com/pkg/errors" -) - -// New creates a new core.Bot instance with the provided bot token & ConfigOpt(s) -//goland:noinspection GoUnusedExportedFunction -func New(token string, opts ...ConfigOpt) (*core.Bot, error) { - config := &Config{} - config.Apply(opts) - - if config.EventManagerConfig == nil { - config.EventManagerConfig = &core.DefaultEventManagerConfig - } - - if config.EventManagerConfig.GatewayHandlers == nil { - config.EventManagerConfig.GatewayHandlers = handlers.GetGatewayHandlers() - } - if config.EventManagerConfig.HTTPServerHandler == nil { - config.EventManagerConfig.HTTPServerHandler = handlers.GetHTTPServerHandler() - } - - return buildBot(token, *config) -} - -func buildBot(token string, config Config) (*core.Bot, error) { - if token == "" { - return nil, discord.ErrNoBotToken - } - id, err := tokenhelper.IDFromToken(token) - if err != nil { - return nil, errors.Wrap(err, "error while getting application id from BotToken") - } - bot := &core.Bot{ - Token: token, - } - - // TODO: figure out how we handle different application & client ids - bot.ApplicationID = *id - bot.ClientID = *id - - if config.Logger == nil { - config.Logger = log.Default() - } - bot.Logger = config.Logger - - if config.RestClient == nil { - if config.RestClientConfig == nil { - config.RestClientConfig = &rest.DefaultConfig - } - if config.RestClientConfig.Logger == nil { - config.RestClientConfig.Logger = config.Logger - } - if config.RestClientConfig.BotTokenFunc == nil { - config.RestClientConfig.BotTokenFunc = func() string { return bot.Token } - } - config.RestClient = rest.NewClient(config.RestClientConfig) - } - - if config.RestServices == nil { - config.RestServices = rest.NewServices(config.RestClient) - } - bot.RestServices = config.RestServices - - if config.EventManager == nil { - if config.EventManagerConfig == nil { - config.EventManagerConfig = &core.DefaultEventManagerConfig - } - - config.EventManager = core.NewEventManager(bot, config.EventManagerConfig) - } - bot.EventManager = config.EventManager - - if config.Collectors == nil { - if config.CollectorsConfig == nil { - config.CollectorsConfig = &collectors.DefaultConfig - } - config.Collectors = core.NewCollectors(bot, *config.CollectorsConfig) - } - bot.Collectors = config.Collectors - - if config.Gateway == nil && config.GatewayConfig != nil { - var gatewayRs *discord.Gateway - gatewayRs, err = bot.RestServices.GatewayService().GetGateway() - if err != nil { - return nil, err - } - if config.GatewayConfig.Logger == nil { - config.GatewayConfig.Logger = bot.Logger - } - config.Gateway = gateway.New(token, gatewayRs.URL, 0, 0, handlers.DefaultGatewayEventHandler(bot), config.GatewayConfig) - } - bot.Gateway = config.Gateway - - if config.ShardManager == nil && config.ShardManagerConfig != nil { - var gatewayBotRs *discord.GatewayBot - gatewayBotRs, err = bot.RestServices.GatewayService().GetGatewayBot() - if err != nil { - return nil, err - } - - if config.ShardManagerConfig.RateLimiterConfig == nil { - config.ShardManagerConfig.RateLimiterConfig = &srate.DefaultConfig - } - if config.ShardManagerConfig.RateLimiterConfig.Logger == nil { - config.ShardManagerConfig.RateLimiterConfig.Logger = config.Logger - } - if config.ShardManagerConfig.RateLimiterConfig.MaxConcurrency == 0 { - config.ShardManagerConfig.RateLimiterConfig.MaxConcurrency = gatewayBotRs.SessionStartLimit.MaxConcurrency - } - - // apply recommended shard count - if !config.ShardManagerConfig.CustomShards { - config.ShardManagerConfig.ShardCount = gatewayBotRs.Shards - config.ShardManagerConfig.Shards = sharding.NewIntSet() - for i := 0; i < gatewayBotRs.Shards; i++ { - config.ShardManagerConfig.Shards.Add(i) - } - } - if config.ShardManager == nil { - config.ShardManager = sharding.New(token, gatewayBotRs.URL, handlers.DefaultGatewayEventHandler(bot), config.ShardManagerConfig) - } - } - bot.ShardManager = config.ShardManager - - if config.HTTPServer == nil && config.HTTPServerConfig != nil { - if config.HTTPServerConfig.Logger == nil { - config.HTTPServerConfig.Logger = config.Logger - } - config.HTTPServer = httpserver.New(handlers.DefaultHTTPServerEventHandler(bot), config.HTTPServerConfig) - } - bot.HTTPServer = config.HTTPServer - - if config.AudioController == nil { - config.AudioController = core.NewAudioController(bot) - } - bot.AudioController = config.AudioController - - if config.MemberChunkingManager == nil { - if config.MemberChunkingFilter == nil { - config.MemberChunkingFilter = &core.MemberChunkingFilterNone - } - config.MemberChunkingManager = core.NewMemberChunkingManager(bot, *config.MemberChunkingFilter) - } - bot.MemberChunkingManager = config.MemberChunkingManager - - if config.EntityBuilder == nil { - config.EntityBuilder = core.NewEntityBuilder(bot) - } - bot.EntityBuilder = config.EntityBuilder - - if config.Caches == nil { - if config.CacheConfig == nil { - config.CacheConfig = &core.DefaultCacheConfig - } - config.Caches = core.NewCaches(*config.CacheConfig) - } - bot.Caches = config.Caches - - return bot, nil -} diff --git a/core/bot/config.go b/core/bot/config.go deleted file mode 100644 index bdae5791..00000000 --- a/core/bot/config.go +++ /dev/null @@ -1,265 +0,0 @@ -package bot - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/disgo/gateway/sharding" - "github.com/DisgoOrg/disgo/httpserver" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/log" -) - -// Config lets you configure your Bot instance -// Config is the core.Bot config used to configure everything -type Config struct { - Logger log.Logger - - RestClient rest.Client - RestClientConfig *rest.Config - RestServices rest.Services - - EventManager core.EventManager - EventManagerConfig *core.EventManagerConfig - - Collectors core.Collectors - CollectorsConfig *core.CollectorsConfig - - Gateway gateway.Gateway - GatewayConfig *gateway.Config - - ShardManager sharding.ShardManager - ShardManagerConfig *sharding.Config - - HTTPServer httpserver.Server - HTTPServerConfig *httpserver.Config - - Caches core.Caches - CacheConfig *core.CacheConfig - - AudioController core.AudioController - EntityBuilder core.EntityBuilder - MemberChunkingManager core.MemberChunkingManager - MemberChunkingFilter *core.MemberChunkingFilter -} - -type ConfigOpt func(config *Config) - -func (c *Config) Apply(opts []ConfigOpt) { - for _, opt := range opts { - opt(c) - } -} - -// WithLogger lets you inject your own logger implementing log.Logger -//goland:noinspection GoUnusedExportedFunction -func WithLogger(logger log.Logger) ConfigOpt { - return func(config *Config) { - config.Logger = logger - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithRestClient(restClient rest.Client) ConfigOpt { - return func(config *Config) { - config.RestClient = restClient - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithRestClientConfig(restClientConfig rest.Config) ConfigOpt { - return func(config *Config) { - config.RestClientConfig = &restClientConfig - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithRestClientOpts(opts ...rest.ConfigOpt) ConfigOpt { - return func(config *Config) { - if config.RestClientConfig == nil { - config.RestClientConfig = &rest.DefaultConfig - } - config.RestClientConfig.Apply(opts) - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithRestServices(restServices rest.Services) ConfigOpt { - return func(config *Config) { - config.RestServices = restServices - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithEventManager(eventManager core.EventManager) ConfigOpt { - return func(config *Config) { - config.EventManager = eventManager - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithEventListeners(listeners ...core.EventListener) ConfigOpt { - return func(config *Config) { - if config.EventManagerConfig == nil { - config.EventManagerConfig = &core.DefaultEventManagerConfig - } - config.EventManagerConfig.EventListeners = append(config.EventManagerConfig.EventListeners, listeners...) - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithRawEventsEnabled() ConfigOpt { - return func(config *Config) { - if config.EventManagerConfig == nil { - config.EventManagerConfig = &core.DefaultEventManagerConfig - } - config.EventManagerConfig.RawEventsEnabled = true - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithAsyncEventsEnabled() ConfigOpt { - return func(config *Config) { - if config.EventManagerConfig == nil { - config.EventManagerConfig = &core.DefaultEventManagerConfig - } - config.EventManagerConfig.AsyncEventsEnabled = true - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithCollectors(collectors core.Collectors) ConfigOpt { - return func(config *Config) { - config.Collectors = collectors - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithCollectorsConfig(collectorsConfig core.CollectorsConfig) ConfigOpt { - return func(config *Config) { - config.CollectorsConfig = &collectorsConfig - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithGateway(gateway gateway.Gateway) ConfigOpt { - return func(config *Config) { - config.Gateway = gateway - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithGatewayConfig(gatewayConfig gateway.Config) ConfigOpt { - return func(config *Config) { - config.GatewayConfig = &gatewayConfig - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithGatewayOpts(opts ...gateway.ConfigOpt) ConfigOpt { - return func(config *Config) { - if config.GatewayConfig == nil { - config.GatewayConfig = &gateway.DefaultConfig - } - config.GatewayConfig.Apply(opts) - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithShardManager(shardManager sharding.ShardManager) ConfigOpt { - return func(config *Config) { - config.ShardManager = shardManager - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithShardManagerConfig(shardManagerConfig sharding.Config) ConfigOpt { - return func(config *Config) { - config.ShardManagerConfig = &shardManagerConfig - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithShardManagerOpts(opts ...sharding.ConfigOpt) ConfigOpt { - return func(config *Config) { - if config.ShardManagerConfig == nil { - config.ShardManagerConfig = &sharding.DefaultConfig - } - config.ShardManagerConfig.Apply(opts) - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithHTTPServer(httpServer httpserver.Server) ConfigOpt { - return func(config *Config) { - config.HTTPServer = httpServer - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithHTTPServerConfig(httpServerConfig httpserver.Config) ConfigOpt { - return func(config *Config) { - config.HTTPServerConfig = &httpServerConfig - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithHTTPServerOpts(opts ...httpserver.ConfigOpt) ConfigOpt { - return func(config *Config) { - if config.HTTPServerConfig == nil { - config.HTTPServerConfig = &httpserver.DefaultConfig - } - config.HTTPServerConfig.Apply(opts) - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithCaches(caches core.Caches) ConfigOpt { - return func(config *Config) { - config.Caches = caches - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithCacheConfig(cacheConfig core.CacheConfig) ConfigOpt { - return func(config *Config) { - config.CacheConfig = &cacheConfig - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithCacheOpts(opts ...core.CacheConfigOpt) ConfigOpt { - return func(config *Config) { - if config.CacheConfig == nil { - config.CacheConfig = &core.DefaultCacheConfig - } - config.CacheConfig.Apply(opts) - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithEntityBuilder(entityBuilder core.EntityBuilder) ConfigOpt { - return func(config *Config) { - config.EntityBuilder = entityBuilder - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithAudioController(audioController core.AudioController) ConfigOpt { - return func(config *Config) { - config.AudioController = audioController - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithMemberChunkingManager(memberChunkingManager core.MemberChunkingManager) ConfigOpt { - return func(config *Config) { - config.MemberChunkingManager = memberChunkingManager - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithMemberChunkingFilter(memberChunkingFilter core.MemberChunkingFilter) ConfigOpt { - return func(config *Config) { - config.MemberChunkingFilter = &memberChunkingFilter - } -} diff --git a/core/cache_channel.go b/core/cache_channel.go deleted file mode 100644 index df946b33..00000000 --- a/core/cache_channel.go +++ /dev/null @@ -1,131 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" -) - -type ( - ChannelFindFunc func(channel Channel) bool - - ChannelCache interface { - Get(channelID snowflake.Snowflake) Channel - GetCopy(channelID snowflake.Snowflake) Channel - Set(channel Channel) Channel - Remove(channelID snowflake.Snowflake) - - Cache() map[snowflake.Snowflake]Channel - All() []Channel - - FindFirst(channelFindFunc ChannelFindFunc) Channel - FindAll(channelFindFunc ChannelFindFunc) []Channel - - ForAll(channelFunc func(channel Channel)) - } - - channelCacheImpl struct { - channels map[snowflake.Snowflake]Channel - cacheFlags CacheFlags - } -) - -func NewChannelCache(cacheFlags CacheFlags) ChannelCache { - return &channelCacheImpl{channels: map[snowflake.Snowflake]Channel{}, cacheFlags: cacheFlags} -} - -func (c *channelCacheImpl) Get(channelID snowflake.Snowflake) Channel { - return c.channels[channelID] -} - -func (c *channelCacheImpl) GetCopy(channelID snowflake.Snowflake) Channel { - if channel := c.Get(channelID); channel != nil { - ch := &channel - return *ch - } - return nil -} - -func (c *channelCacheImpl) Set(channel Channel) Channel { - if c.cacheFlags.Missing(getCacheFlagForChannelType(channel.Type())) { - return channel - } - ch, ok := c.channels[channel.ID()] - if ok { - ch = ch.set(channel) - return ch - } - c.channels[channel.ID()] = channel - return channel -} - -func (c *channelCacheImpl) Remove(id snowflake.Snowflake) { - delete(c.channels, id) -} - -func (c *channelCacheImpl) Cache() map[snowflake.Snowflake]Channel { - return c.channels -} - -func (c *channelCacheImpl) All() []Channel { - channels := make([]Channel, len(c.channels)) - i := 0 - for _, channel := range c.channels { - channels[i] = channel - i++ - } - return channels -} - -func (c *channelCacheImpl) FindFirst(channelFindFunc ChannelFindFunc) Channel { - for _, channel := range c.channels { - if channelFindFunc(channel) { - return channel - } - } - return nil -} - -func (c *channelCacheImpl) FindAll(channelFindFunc ChannelFindFunc) []Channel { - var channels []Channel - for _, channel := range c.channels { - if channelFindFunc(channel) { - channels = append(channels, channel) - } - } - return channels -} - -func (c *channelCacheImpl) ForAll(channelFunc func(channel Channel)) { - for _, channel := range c.channels { - channelFunc(channel) - } -} - -func getCacheFlagForChannelType(channelType discord.ChannelType) CacheFlags { - switch channelType { - case discord.ChannelTypeGuildText: - return CacheFlagGuildTextChannels - case discord.ChannelTypeDM: - return CacheFlagDMChannels - case discord.ChannelTypeGuildVoice: - return CacheFlagGuildVoiceChannels - case discord.ChannelTypeGroupDM: - return CacheFlagGroupDMChannels - case discord.ChannelTypeGuildCategory: - return CacheFlagGuildCategories - case discord.ChannelTypeGuildNews: - return CacheFlagGuildNewsChannels - case discord.ChannelTypeGuildStore: - return CacheFlagGuildStoreChannels - case discord.ChannelTypeGuildNewsThread: - return CacheFlagGuildNewsThreads - case discord.ChannelTypeGuildPublicThread: - return CacheFlagGuildPublicThreads - case discord.ChannelTypeGuildPrivateThread: - return CacheFlagGuildPrivateThreads - case discord.ChannelTypeGuildStageVoice: - return CacheFlagGuildStageVoiceChannels - default: - return CacheFlagsNone - } -} diff --git a/core/cache_config.go b/core/cache_config.go deleted file mode 100644 index 05fc19ac..00000000 --- a/core/cache_config.go +++ /dev/null @@ -1,47 +0,0 @@ -package core - -//goland:noinspection GoUnusedGlobalVariable -var DefaultCacheConfig = CacheConfig{ - CacheFlags: CacheFlagsDefault, - MemberCachePolicy: MemberCachePolicyDefault, - MessageCachePolicy: MessageCachePolicyDefault, -} - -type CacheConfig struct { - CacheFlags CacheFlags - MemberCachePolicy MemberCachePolicy - MessageCachePolicy MessageCachePolicy -} - -type CacheConfigOpt func(config *CacheConfig) - -func (c *CacheConfig) Apply(opts []CacheConfigOpt) { - for _, opt := range opts { - opt(c) - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithCacheFlags(cacheFlags ...CacheFlags) CacheConfigOpt { - return func(config *CacheConfig) { - var flags CacheFlags - for _, flag := range cacheFlags { - flags = flags.Add(flag) - } - config.CacheFlags = flags - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithMemberCachePolicy(memberCachePolicy MemberCachePolicy) CacheConfigOpt { - return func(config *CacheConfig) { - config.MemberCachePolicy = memberCachePolicy - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithMessageCachePolicy(messageCachePolicy MessageCachePolicy) CacheConfigOpt { - return func(config *CacheConfig) { - config.MessageCachePolicy = messageCachePolicy - } -} diff --git a/core/cache_emoji.go b/core/cache_emoji.go deleted file mode 100644 index a4d34db8..00000000 --- a/core/cache_emoji.go +++ /dev/null @@ -1,134 +0,0 @@ -package core - -import "github.com/DisgoOrg/snowflake" - -type ( - EmojiFindFunc func(emoji *Emoji) bool - - EmojiCache interface { - Get(guildID snowflake.Snowflake, emojiID snowflake.Snowflake) *Emoji - GetCopy(guildID snowflake.Snowflake, emojiID snowflake.Snowflake) *Emoji - Set(emoji *Emoji) *Emoji - Remove(guildID snowflake.Snowflake, emojiID snowflake.Snowflake) - - Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*Emoji - All() map[snowflake.Snowflake][]*Emoji - - GuildCache(guildID snowflake.Snowflake) map[snowflake.Snowflake]*Emoji - GuildAll(guildID snowflake.Snowflake) []*Emoji - - FindFirst(emojiFindFunc EmojiFindFunc) *Emoji - FindAll(emojiFindFunc EmojiFindFunc) []*Emoji - } - - emojiCacheImpl struct { - cacheFlags CacheFlags - emojis map[snowflake.Snowflake]map[snowflake.Snowflake]*Emoji - } -) - -func NewEmojiCache(cacheFlags CacheFlags) EmojiCache { - return &emojiCacheImpl{ - cacheFlags: cacheFlags, - emojis: map[snowflake.Snowflake]map[snowflake.Snowflake]*Emoji{}, - } -} - -func (c *emojiCacheImpl) Get(guildID snowflake.Snowflake, emojiID snowflake.Snowflake) *Emoji { - if _, ok := c.emojis[guildID]; !ok { - return nil - } - return c.emojis[guildID][emojiID] -} - -func (c *emojiCacheImpl) GetCopy(guildID snowflake.Snowflake, emojiID snowflake.Snowflake) *Emoji { - if emoji := c.Get(guildID, emojiID); emoji != nil { - em := *emoji - return &em - } - return nil -} - -func (c *emojiCacheImpl) Set(emoji *Emoji) *Emoji { - if c.cacheFlags.Missing(CacheFlagEmojis) { - return emoji - } - if _, ok := c.emojis[emoji.GuildID]; !ok { - c.emojis[emoji.GuildID] = map[snowflake.Snowflake]*Emoji{} - } - em, ok := c.emojis[emoji.GuildID][emoji.ID] - if ok { - *em = *emoji - return em - } - c.emojis[emoji.GuildID][emoji.ID] = emoji - - return emoji -} - -func (c *emojiCacheImpl) Remove(guildID snowflake.Snowflake, emojiID snowflake.Snowflake) { - if _, ok := c.emojis[guildID]; !ok { - return - } - delete(c.emojis[guildID], emojiID) -} - -func (c *emojiCacheImpl) Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*Emoji { - return c.emojis -} - -func (c *emojiCacheImpl) All() map[snowflake.Snowflake][]*Emoji { - emojis := make(map[snowflake.Snowflake][]*Emoji, len(c.emojis)) - for guildID, guildEmojis := range c.emojis { - emojis[guildID] = make([]*Emoji, len(guildEmojis)) - i := 0 - for _, guildEmoji := range guildEmojis { - emojis[guildID] = append(emojis[guildID], guildEmoji) - } - i++ - } - return emojis -} - -func (c *emojiCacheImpl) GuildCache(guildID snowflake.Snowflake) map[snowflake.Snowflake]*Emoji { - if _, ok := c.emojis[guildID]; !ok { - return nil - } - return c.emojis[guildID] -} - -func (c *emojiCacheImpl) GuildAll(guildID snowflake.Snowflake) []*Emoji { - if _, ok := c.emojis[guildID]; !ok { - return nil - } - emojis := make([]*Emoji, len(c.emojis[guildID])) - i := 0 - for _, emoji := range c.emojis[guildID] { - emojis = append(emojis, emoji) - i++ - } - return emojis -} - -func (c *emojiCacheImpl) FindFirst(emojiFindFunc EmojiFindFunc) *Emoji { - for _, guildEmojis := range c.emojis { - for _, emoji := range guildEmojis { - if emojiFindFunc(emoji) { - return emoji - } - } - } - return nil -} - -func (c *emojiCacheImpl) FindAll(emojiFindFunc EmojiFindFunc) []*Emoji { - var emojis []*Emoji - for _, guildEmojis := range c.emojis { - for _, emoji := range guildEmojis { - if emojiFindFunc(emoji) { - emojis = append(emojis, emoji) - } - } - } - return emojis -} diff --git a/core/cache_flags.go b/core/cache_flags.go deleted file mode 100644 index a4b53a66..00000000 --- a/core/cache_flags.go +++ /dev/null @@ -1,109 +0,0 @@ -package core - -// CacheFlags are used to enable/disable certain internal caches -type CacheFlags int - -// values for CacheFlags -//goland:noinspection GoUnusedConst -const ( - CacheFlagGuilds CacheFlags = 1 << iota - CacheFlagGuildScheduledEvents - - CacheFlagPresences - - CacheFlagGuildTextChannels - CacheFlagDMChannels - CacheFlagGuildVoiceChannels - CacheFlagGroupDMChannels - CacheFlagGuildCategories - CacheFlagGuildNewsChannels - CacheFlagGuildStoreChannels - CacheFlagGuildNewsThreads - CacheFlagGuildPublicThreads - CacheFlagGuildPrivateThreads - CacheFlagGuildStageVoiceChannels - - CacheFlagRoles - CacheFlagRoleTags - - CacheFlagEmojis - CacheFlagStickers - - CacheFlagVoiceStates - - CacheFlagStageInstances - - CacheFlagsNone CacheFlags = 0 - - CacheFlagsAllChannels = CacheFlagGuildTextChannels | - CacheFlagDMChannels | - CacheFlagGuildVoiceChannels | - CacheFlagGroupDMChannels | - CacheFlagGuildCategories | - CacheFlagGuildNewsChannels | - CacheFlagGuildStoreChannels | - CacheFlagGuildNewsThreads | - CacheFlagGuildPublicThreads | - CacheFlagGuildPrivateThreads | - CacheFlagGuildStageVoiceChannels - - CacheFlagsAllThreads = CacheFlagGuildNewsThreads | - CacheFlagGuildPublicThreads | - CacheFlagGuildPrivateThreads - - CacheFlagsDefault = CacheFlagGuilds | - CacheFlagsAllChannels | - CacheFlagRoles | - CacheFlagEmojis | - CacheFlagStickers | - CacheFlagVoiceStates - - CacheFlagsFullRoles = CacheFlagRoles | - CacheFlagRoleTags - - CacheFlagsAll = CacheFlagGuilds | - CacheFlagGuildScheduledEvents | - CacheFlagsAllChannels | - CacheFlagsFullRoles | - CacheFlagEmojis | - CacheFlagStickers | - CacheFlagVoiceStates | - CacheFlagStageInstances | - CacheFlagPresences -) - -// Add allows you to add multiple bits together, producing a new bit -func (f CacheFlags) Add(bits ...CacheFlags) CacheFlags { - for _, bit := range bits { - f |= bit - } - return f -} - -// Remove allows you to subtract multiple bits from the first, producing a new bit -func (f CacheFlags) Remove(bits ...CacheFlags) CacheFlags { - for _, bit := range bits { - f &^= bit - } - return f -} - -// Has will ensure that the bit includes all the bits entered -func (f CacheFlags) Has(bits ...CacheFlags) bool { - for _, bit := range bits { - if (f & bit) != bit { - return false - } - } - return true -} - -// Missing will check whether the bit is missing any one of the bits -func (f CacheFlags) Missing(bits ...CacheFlags) bool { - for _, bit := range bits { - if (f & bit) != bit { - return true - } - } - return false -} diff --git a/core/cache_guild.go b/core/cache_guild.go deleted file mode 100644 index 171cb210..00000000 --- a/core/cache_guild.go +++ /dev/null @@ -1,207 +0,0 @@ -package core - -import ( - "sync" - - "github.com/DisgoOrg/disgo/internal/rwsync" - "github.com/DisgoOrg/snowflake" -) - -type ( - GuildFindFunc func(guild *Guild) bool - - GuildCache interface { - rwsync.RWLocker - - Get(guildID snowflake.Snowflake) *Guild - GetCopy(guildID snowflake.Snowflake) *Guild - Set(guild *Guild) *Guild - Remove(guildID snowflake.Snowflake) - - Cache() map[snowflake.Snowflake]*Guild - All() []*Guild - - FindFirst(guildFindFunc GuildFindFunc) *Guild - FindAll(guildFindFunc GuildFindFunc) []*Guild - - SetReady(shardID int, guildID snowflake.Snowflake) - SetUnready(shardID int, guildID snowflake.Snowflake) - IsUnready(shardID int, guildID snowflake.Snowflake) bool - UnreadyGuilds(shardID int) []snowflake.Snowflake - - SetUnavailable(guildID snowflake.Snowflake) - SetAvailable(guildID snowflake.Snowflake) - IsUnavailable(guildID snowflake.Snowflake) bool - UnavailableGuilds() []snowflake.Snowflake - } - - guildCacheImpl struct { - sync.RWMutex - cacheFlags CacheFlags - guilds map[snowflake.Snowflake]*Guild - - unreadyGuildsMu sync.RWMutex - unreadyGuilds map[int]map[snowflake.Snowflake]struct{} - - unavailableGuildsMu sync.RWMutex - unavailableGuilds map[snowflake.Snowflake]struct{} - } -) - -func NewGuildCache(cacheFlags CacheFlags) GuildCache { - return &guildCacheImpl{ - cacheFlags: cacheFlags, - guilds: map[snowflake.Snowflake]*Guild{}, - unreadyGuilds: map[int]map[snowflake.Snowflake]struct{}{}, - unavailableGuilds: map[snowflake.Snowflake]struct{}{}, - } -} - -func (c *guildCacheImpl) Get(guildID snowflake.Snowflake) *Guild { - c.RLock() - defer c.RUnlock() - return c.guilds[guildID] -} - -func (c *guildCacheImpl) GetCopy(guildID snowflake.Snowflake) *Guild { - if guild := c.Get(guildID); guild != nil { - gu := *guild - return &gu - } - return nil -} - -func (c *guildCacheImpl) Set(guild *Guild) *Guild { - if c.cacheFlags.Missing(CacheFlagGuilds) { - return guild - } - c.Lock() - defer c.Unlock() - gui, ok := c.guilds[guild.ID] - if ok { - *gui = *guild - return gui - } - c.guilds[guild.ID] = guild - return guild -} - -func (c *guildCacheImpl) Remove(id snowflake.Snowflake) { - c.Lock() - defer c.Unlock() - delete(c.guilds, id) -} - -func (c *guildCacheImpl) Cache() map[snowflake.Snowflake]*Guild { - return c.guilds -} - -func (c *guildCacheImpl) All() []*Guild { - c.RLock() - defer c.RUnlock() - guilds := make([]*Guild, len(c.guilds)) - i := 0 - for _, guild := range c.guilds { - guilds[i] = guild - i++ - } - return guilds -} - -func (c *guildCacheImpl) FindFirst(guildFindFunc GuildFindFunc) *Guild { - c.RLock() - defer c.RUnlock() - for _, gui := range c.guilds { - if guildFindFunc(gui) { - return gui - } - } - return nil -} - -func (c *guildCacheImpl) FindAll(guildFindFunc GuildFindFunc) []*Guild { - c.RLock() - defer c.RUnlock() - var guilds []*Guild - for _, gui := range c.guilds { - if guildFindFunc(gui) { - guilds = append(guilds, gui) - } - } - return guilds -} - -func (c *guildCacheImpl) SetReady(shardID int, guildID snowflake.Snowflake) { - c.unreadyGuildsMu.Lock() - defer c.unreadyGuildsMu.Unlock() - if _, ok := c.unreadyGuilds[shardID]; !ok { - return - } - delete(c.unreadyGuilds[shardID], guildID) -} - -func (c *guildCacheImpl) SetUnready(shardID int, guildID snowflake.Snowflake) { - c.unreadyGuildsMu.Lock() - defer c.unreadyGuildsMu.Unlock() - if _, ok := c.unreadyGuilds[shardID]; !ok { - c.unreadyGuilds[shardID] = map[snowflake.Snowflake]struct{}{} - } - c.unreadyGuilds[shardID][guildID] = struct{}{} -} - -func (c *guildCacheImpl) IsUnready(shardID int, guildID snowflake.Snowflake) bool { - c.unreadyGuildsMu.RLock() - defer c.unreadyGuildsMu.RUnlock() - if _, ok := c.unreadyGuilds[shardID]; !ok { - return false - } - _, ok := c.unreadyGuilds[shardID][guildID] - return ok -} - -func (c *guildCacheImpl) UnreadyGuilds(shardID int) []snowflake.Snowflake { - c.unreadyGuildsMu.RLock() - defer c.unreadyGuildsMu.RUnlock() - if _, ok := c.unreadyGuilds[shardID]; !ok { - return nil - } - guilds := make([]snowflake.Snowflake, len(c.unreadyGuilds[shardID])) - var i int - for guildID := range c.unreadyGuilds[shardID] { - guilds[i] = guildID - i++ - } - return guilds -} - -func (c *guildCacheImpl) SetUnavailable(id snowflake.Snowflake) { - c.unavailableGuildsMu.Lock() - defer c.unavailableGuildsMu.Unlock() - c.Remove(id) - c.unavailableGuilds[id] = struct{}{} -} - -func (c *guildCacheImpl) SetAvailable(guildID snowflake.Snowflake) { - c.unavailableGuildsMu.Lock() - defer c.unavailableGuildsMu.Unlock() - delete(c.unavailableGuilds, guildID) -} - -func (c *guildCacheImpl) IsUnavailable(guildID snowflake.Snowflake) bool { - c.unavailableGuildsMu.RLock() - defer c.unavailableGuildsMu.RUnlock() - _, ok := c.unavailableGuilds[guildID] - return ok -} - -func (c *guildCacheImpl) UnavailableGuilds() []snowflake.Snowflake { - c.unavailableGuildsMu.RLock() - defer c.unavailableGuildsMu.RUnlock() - guilds := make([]snowflake.Snowflake, len(c.unavailableGuilds)) - var i int - for guildID := range c.unavailableGuilds { - guilds[i] = guildID - i++ - } - return guilds -} diff --git a/core/cache_guild_scheduled_events.go b/core/cache_guild_scheduled_events.go deleted file mode 100644 index 72e306a3..00000000 --- a/core/cache_guild_scheduled_events.go +++ /dev/null @@ -1,94 +0,0 @@ -package core - -import "github.com/DisgoOrg/snowflake" - -type ( - GuildScheduledEventFindFunc func(guildScheduledEvent *GuildScheduledEvent) bool - - GuildScheduledEventCache interface { - Get(guildScheduledEventID snowflake.Snowflake) *GuildScheduledEvent - GetCopy(guildScheduledEventID snowflake.Snowflake) *GuildScheduledEvent - Set(guildScheduledEvent *GuildScheduledEvent) *GuildScheduledEvent - Remove(guildScheduledEventID snowflake.Snowflake) - - Cache() map[snowflake.Snowflake]*GuildScheduledEvent - All() []*GuildScheduledEvent - - FindFirst(guildScheduledEventFindFunc GuildScheduledEventFindFunc) *GuildScheduledEvent - FindAll(guildScheduledEventFindFunc GuildScheduledEventFindFunc) []*GuildScheduledEvent - } - - guildScheduledEventCacheImpl struct { - cacheFlags CacheFlags - guildScheduledEvents map[snowflake.Snowflake]*GuildScheduledEvent - } -) - -func NewGuildScheduledEventCache(cacheFlags CacheFlags) GuildScheduledEventCache { - return &guildScheduledEventCacheImpl{ - cacheFlags: cacheFlags, - guildScheduledEvents: map[snowflake.Snowflake]*GuildScheduledEvent{}, - } -} - -func (c *guildScheduledEventCacheImpl) Get(guildScheduledEventID snowflake.Snowflake) *GuildScheduledEvent { - return c.guildScheduledEvents[guildScheduledEventID] -} - -func (c *guildScheduledEventCacheImpl) GetCopy(guildScheduledEventID snowflake.Snowflake) *GuildScheduledEvent { - if guildScheduledEvent := c.Get(guildScheduledEventID); guildScheduledEvent != nil { - st := *guildScheduledEvent - return &st - } - return nil -} - -func (c *guildScheduledEventCacheImpl) Set(guildScheduledEvent *GuildScheduledEvent) *GuildScheduledEvent { - if c.cacheFlags.Missing(CacheFlagGuildScheduledEvents) { - return guildScheduledEvent - } - gse, ok := c.guildScheduledEvents[guildScheduledEvent.ID] - if ok { - *gse = *guildScheduledEvent - return gse - } - c.guildScheduledEvents[guildScheduledEvent.ID] = guildScheduledEvent - return guildScheduledEvent -} - -func (c *guildScheduledEventCacheImpl) Remove(id snowflake.Snowflake) { - delete(c.guildScheduledEvents, id) -} - -func (c *guildScheduledEventCacheImpl) Cache() map[snowflake.Snowflake]*GuildScheduledEvent { - return c.guildScheduledEvents -} - -func (c *guildScheduledEventCacheImpl) All() []*GuildScheduledEvent { - guildScheduledEvents := make([]*GuildScheduledEvent, len(c.guildScheduledEvents)) - i := 0 - for _, guildScheduledEvent := range c.guildScheduledEvents { - guildScheduledEvents[i] = guildScheduledEvent - i++ - } - return guildScheduledEvents -} - -func (c *guildScheduledEventCacheImpl) FindFirst(guildScheduledEventFindFunc GuildScheduledEventFindFunc) *GuildScheduledEvent { - for _, gse := range c.guildScheduledEvents { - if guildScheduledEventFindFunc(gse) { - return gse - } - } - return nil -} - -func (c *guildScheduledEventCacheImpl) FindAll(guildScheduledEventFindFunc GuildScheduledEventFindFunc) []*GuildScheduledEvent { - var guildScheduledEvents []*GuildScheduledEvent - for _, gse := range c.guildScheduledEvents { - if guildScheduledEventFindFunc(gse) { - guildScheduledEvents = append(guildScheduledEvents, gse) - } - } - return guildScheduledEvents -} diff --git a/core/cache_member.go b/core/cache_member.go deleted file mode 100644 index e85278ed..00000000 --- a/core/cache_member.go +++ /dev/null @@ -1,143 +0,0 @@ -package core - -import "github.com/DisgoOrg/snowflake" - -type ( - MemberFindFunc func(member *Member) bool - - MemberCache interface { - Get(guildID snowflake.Snowflake, userID snowflake.Snowflake) *Member - GetCopy(guildID snowflake.Snowflake, userID snowflake.Snowflake) *Member - Set(member *Member) *Member - Remove(guildID snowflake.Snowflake, userID snowflake.Snowflake) - RemoveAll(guildID snowflake.Snowflake) - - Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*Member - All() map[snowflake.Snowflake][]*Member - - GuildCache(guildID snowflake.Snowflake) map[snowflake.Snowflake]*Member - GuildAll(guildID snowflake.Snowflake) []*Member - - FindFirst(memberFindFunc MemberFindFunc) *Member - FindAll(memberFindFunc MemberFindFunc) []*Member - } - - memberCacheImpl struct { - memberCachePolicy MemberCachePolicy - members map[snowflake.Snowflake]map[snowflake.Snowflake]*Member - } -) - -func NewMemberCache(memberCachePolicy MemberCachePolicy) MemberCache { - if memberCachePolicy == nil { - memberCachePolicy = MemberCachePolicyDefault - } - return &memberCacheImpl{ - memberCachePolicy: memberCachePolicy, - members: map[snowflake.Snowflake]map[snowflake.Snowflake]*Member{}, - } -} - -func (c *memberCacheImpl) Get(guildID snowflake.Snowflake, userID snowflake.Snowflake) *Member { - if _, ok := c.members[guildID]; !ok { - return nil - } - return c.members[guildID][userID] -} - -func (c *memberCacheImpl) GetCopy(guildID snowflake.Snowflake, userID snowflake.Snowflake) *Member { - if member := c.Get(guildID, userID); member != nil { - m := *member - return &m - } - return nil -} - -func (c *memberCacheImpl) Set(member *Member) *Member { - // always cache self members - if !c.memberCachePolicy(member) && member.User.ID != member.Bot.ClientID { - return member - } - if _, ok := c.members[member.GuildID]; !ok { - c.members[member.GuildID] = map[snowflake.Snowflake]*Member{} - } - rol, ok := c.members[member.GuildID][member.User.ID] - if ok { - *rol = *member - return rol - } - c.members[member.GuildID][member.User.ID] = member - - return member -} - -func (c *memberCacheImpl) Remove(guildID snowflake.Snowflake, userID snowflake.Snowflake) { - if _, ok := c.members[guildID]; !ok { - return - } - delete(c.members[guildID], userID) -} - -func (c *memberCacheImpl) RemoveAll(guildID snowflake.Snowflake) { - delete(c.members, guildID) -} - -func (c *memberCacheImpl) Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*Member { - return c.members -} - -func (c *memberCacheImpl) All() map[snowflake.Snowflake][]*Member { - members := make(map[snowflake.Snowflake][]*Member, len(c.members)) - for guildID, guildMembers := range c.members { - members[guildID] = make([]*Member, len(guildMembers)) - i := 0 - for _, member := range guildMembers { - members[guildID] = append(members[guildID], member) - } - i++ - } - return members -} - -func (c *memberCacheImpl) GuildCache(guildID snowflake.Snowflake) map[snowflake.Snowflake]*Member { - if _, ok := c.members[guildID]; !ok { - return nil - } - return c.members[guildID] -} - -func (c *memberCacheImpl) GuildAll(guildID snowflake.Snowflake) []*Member { - if _, ok := c.members[guildID]; !ok { - return nil - } - members := make([]*Member, len(c.members[guildID])) - i := 0 - for _, member := range c.members[guildID] { - members = append(members, member) - i++ - } - return members -} - -func (c *memberCacheImpl) FindFirst(memberFindFunc MemberFindFunc) *Member { - for _, guildMembers := range c.members { - for _, member := range guildMembers { - if memberFindFunc(member) { - return member - } - } - } - return nil -} - -func (c *memberCacheImpl) FindAll(memberFindFunc MemberFindFunc) []*Member { - var members []*Member - for _, guildMembers := range c.members { - for _, member := range guildMembers { - if memberFindFunc(member) { - members = append(members, member) - } - } - } - return members -} diff --git a/core/cache_message.go b/core/cache_message.go deleted file mode 100644 index 0516074b..00000000 --- a/core/cache_message.go +++ /dev/null @@ -1,137 +0,0 @@ -package core - -import "github.com/DisgoOrg/snowflake" - -type ( - MessageFindFunc func(message *Message) bool - - MessageCache interface { - Get(channelID snowflake.Snowflake, messageID snowflake.Snowflake) *Message - GetCopy(channelID snowflake.Snowflake, messageID snowflake.Snowflake) *Message - Set(message *Message) *Message - Remove(channelID snowflake.Snowflake, messageID snowflake.Snowflake) - - Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*Message - All() map[snowflake.Snowflake][]*Message - - ChannelCache(channelID snowflake.Snowflake) map[snowflake.Snowflake]*Message - ChannelAll(channelID snowflake.Snowflake) []*Message - - FindFirst(messageFindFunc MessageFindFunc) *Message - FindAll(messageFindFunc MessageFindFunc) []*Message - } - - messageCacheImpl struct { - messageCachePolicy MessageCachePolicy - messages map[snowflake.Snowflake]map[snowflake.Snowflake]*Message - } -) - -func NewMessageCache(messageCachePolicy MessageCachePolicy) MessageCache { - if messageCachePolicy == nil { - messageCachePolicy = MessageCachePolicyDefault - } - return &messageCacheImpl{ - messageCachePolicy: messageCachePolicy, - messages: map[snowflake.Snowflake]map[snowflake.Snowflake]*Message{}, - } -} - -func (c *messageCacheImpl) Get(channelID snowflake.Snowflake, messageID snowflake.Snowflake) *Message { - if _, ok := c.messages[channelID]; !ok { - return nil - } - return c.messages[channelID][messageID] -} - -func (c *messageCacheImpl) GetCopy(channelID snowflake.Snowflake, messageID snowflake.Snowflake) *Message { - if message := c.Get(channelID, messageID); message != nil { - me := *message - return &me - } - return nil -} - -func (c *messageCacheImpl) Set(message *Message) *Message { - if !c.messageCachePolicy(message) { - return message - } - if _, ok := c.messages[message.ChannelID]; !ok { - c.messages[message.ChannelID] = map[snowflake.Snowflake]*Message{} - } - rol, ok := c.messages[message.ChannelID][message.ID] - if ok { - *rol = *message - return rol - } - c.messages[message.ChannelID][message.ID] = message - - return message -} - -func (c *messageCacheImpl) Remove(channelID snowflake.Snowflake, messageID snowflake.Snowflake) { - if _, ok := c.messages[channelID]; !ok { - return - } - delete(c.messages[channelID], messageID) -} - -func (c *messageCacheImpl) Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*Message { - return c.messages -} - -func (c *messageCacheImpl) All() map[snowflake.Snowflake][]*Message { - messages := make(map[snowflake.Snowflake][]*Message, len(c.messages)) - for channelID, channelMessages := range c.messages { - messages[channelID] = make([]*Message, len(channelMessages)) - i := 0 - for _, channelMessage := range channelMessages { - messages[channelID] = append(messages[channelID], channelMessage) - } - i++ - } - return messages -} - -func (c *messageCacheImpl) ChannelCache(channelID snowflake.Snowflake) map[snowflake.Snowflake]*Message { - if _, ok := c.messages[channelID]; !ok { - return nil - } - return c.messages[channelID] -} - -func (c *messageCacheImpl) ChannelAll(channelID snowflake.Snowflake) []*Message { - if _, ok := c.messages[channelID]; !ok { - return nil - } - messages := make([]*Message, len(c.messages[channelID])) - i := 0 - for _, message := range c.messages[channelID] { - messages = append(messages, message) - i++ - } - return messages -} - -func (c *messageCacheImpl) FindFirst(messageFindFunc MessageFindFunc) *Message { - for _, channelMessages := range c.messages { - for _, message := range channelMessages { - if messageFindFunc(message) { - return message - } - } - } - return nil -} - -func (c *messageCacheImpl) FindAll(messageFindFunc MessageFindFunc) []*Message { - var messages []*Message - for _, channelMessages := range c.messages { - for _, message := range channelMessages { - if messageFindFunc(message) { - messages = append(messages, message) - } - } - } - return messages -} diff --git a/core/cache_presence.go b/core/cache_presence.go deleted file mode 100644 index 76ef02df..00000000 --- a/core/cache_presence.go +++ /dev/null @@ -1,134 +0,0 @@ -package core - -import "github.com/DisgoOrg/snowflake" - -type ( - PresenceFindFunc func(presence *Presence) bool - - PresenceCache interface { - Get(guildID snowflake.Snowflake, userID snowflake.Snowflake) *Presence - GetCopy(guildID snowflake.Snowflake, userID snowflake.Snowflake) *Presence - Set(presence *Presence) *Presence - Remove(guildID snowflake.Snowflake, userID snowflake.Snowflake) - - Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*Presence - All() map[snowflake.Snowflake][]*Presence - - GuildCache(guildID snowflake.Snowflake) map[snowflake.Snowflake]*Presence - GuildAll(guildID snowflake.Snowflake) []*Presence - - FindFirst(presenceFindFunc PresenceFindFunc) *Presence - FindAll(presenceFindFunc PresenceFindFunc) []*Presence - } - - presenceCacheImpl struct { - cacheFlags CacheFlags - presences map[snowflake.Snowflake]map[snowflake.Snowflake]*Presence - } -) - -func NewPresenceCache(cacheFlags CacheFlags) PresenceCache { - return &presenceCacheImpl{ - cacheFlags: cacheFlags, - presences: map[snowflake.Snowflake]map[snowflake.Snowflake]*Presence{}, - } -} - -func (c *presenceCacheImpl) Get(guildID snowflake.Snowflake, userID snowflake.Snowflake) *Presence { - if _, ok := c.presences[guildID]; !ok { - return nil - } - return c.presences[guildID][userID] -} - -func (c *presenceCacheImpl) GetCopy(guildID snowflake.Snowflake, userID snowflake.Snowflake) *Presence { - if presence := c.Get(guildID, userID); presence != nil { - m := *presence - return &m - } - return nil -} - -func (c *presenceCacheImpl) Set(presence *Presence) *Presence { - if c.cacheFlags.Missing(CacheFlagPresences) { - return presence - } - if _, ok := c.presences[presence.GuildID]; !ok { - c.presences[presence.GuildID] = map[snowflake.Snowflake]*Presence{} - } - rol, ok := c.presences[presence.GuildID][presence.PresenceUser.ID] - if ok { - *rol = *presence - return rol - } - c.presences[presence.GuildID][presence.PresenceUser.ID] = presence - - return presence -} - -func (c *presenceCacheImpl) Remove(guildID snowflake.Snowflake, userID snowflake.Snowflake) { - if _, ok := c.presences[guildID]; !ok { - return - } - delete(c.presences[guildID], userID) -} - -func (c *presenceCacheImpl) Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*Presence { - return c.presences -} - -func (c *presenceCacheImpl) All() map[snowflake.Snowflake][]*Presence { - presences := make(map[snowflake.Snowflake][]*Presence, len(c.presences)) - for guildID, guildPresences := range c.presences { - presences[guildID] = make([]*Presence, len(guildPresences)) - i := 0 - for _, presence := range guildPresences { - presences[guildID] = append(presences[guildID], presence) - } - i++ - } - return presences -} - -func (c *presenceCacheImpl) GuildCache(guildID snowflake.Snowflake) map[snowflake.Snowflake]*Presence { - if _, ok := c.presences[guildID]; !ok { - return nil - } - return c.presences[guildID] -} - -func (c *presenceCacheImpl) GuildAll(guildID snowflake.Snowflake) []*Presence { - if _, ok := c.presences[guildID]; !ok { - return nil - } - presences := make([]*Presence, len(c.presences[guildID])) - i := 0 - for _, presence := range c.presences[guildID] { - presences = append(presences, presence) - i++ - } - return presences -} - -func (c *presenceCacheImpl) FindFirst(presenceFindFunc PresenceFindFunc) *Presence { - for _, guildPresences := range c.presences { - for _, presence := range guildPresences { - if presenceFindFunc(presence) { - return presence - } - } - } - return nil -} - -func (c *presenceCacheImpl) FindAll(presenceFindFunc PresenceFindFunc) []*Presence { - var presences []*Presence - for _, guildPresences := range c.presences { - for _, presence := range guildPresences { - if presenceFindFunc(presence) { - presences = append(presences, presence) - } - } - } - return presences -} diff --git a/core/cache_role.go b/core/cache_role.go deleted file mode 100644 index 2f23b392..00000000 --- a/core/cache_role.go +++ /dev/null @@ -1,134 +0,0 @@ -package core - -import "github.com/DisgoOrg/snowflake" - -type ( - RoleFindFunc func(role *Role) bool - - RoleCache interface { - Get(guildID snowflake.Snowflake, roleID snowflake.Snowflake) *Role - GetCopy(guildID snowflake.Snowflake, roleID snowflake.Snowflake) *Role - Set(role *Role) *Role - Remove(guildID snowflake.Snowflake, roleID snowflake.Snowflake) - - Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*Role - All() map[snowflake.Snowflake][]*Role - - GuildCache(guildID snowflake.Snowflake) map[snowflake.Snowflake]*Role - GuildAll(guildID snowflake.Snowflake) []*Role - - FindFirst(roleFindFunc RoleFindFunc) *Role - FindAll(roleFindFunc RoleFindFunc) []*Role - } - - roleCacheImpl struct { - cacheFlags CacheFlags - roles map[snowflake.Snowflake]map[snowflake.Snowflake]*Role - } -) - -func NewRoleCache(cacheFlags CacheFlags) RoleCache { - return &roleCacheImpl{ - cacheFlags: cacheFlags, - roles: map[snowflake.Snowflake]map[snowflake.Snowflake]*Role{}, - } -} - -func (c *roleCacheImpl) Get(guildID snowflake.Snowflake, roleID snowflake.Snowflake) *Role { - if _, ok := c.roles[guildID]; !ok { - return nil - } - return c.roles[guildID][roleID] -} - -func (c *roleCacheImpl) GetCopy(guildID snowflake.Snowflake, roleID snowflake.Snowflake) *Role { - if role := c.Get(guildID, roleID); role != nil { - ro := *role - return &ro - } - return nil -} - -func (c *roleCacheImpl) Set(role *Role) *Role { - if c.cacheFlags.Missing(CacheFlagRoles) { - return role - } - if _, ok := c.roles[role.GuildID]; !ok { - c.roles[role.GuildID] = map[snowflake.Snowflake]*Role{} - } - rol, ok := c.roles[role.GuildID][role.ID] - if ok { - *rol = *role - return rol - } - c.roles[role.GuildID][role.ID] = role - - return role -} - -func (c *roleCacheImpl) Remove(guildID snowflake.Snowflake, roleID snowflake.Snowflake) { - if _, ok := c.roles[guildID]; !ok { - return - } - delete(c.roles[guildID], roleID) -} - -func (c *roleCacheImpl) Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*Role { - return c.roles -} - -func (c *roleCacheImpl) All() map[snowflake.Snowflake][]*Role { - roles := make(map[snowflake.Snowflake][]*Role, len(c.roles)) - for guildID, guildRoles := range c.roles { - roles[guildID] = make([]*Role, len(guildRoles)) - i := 0 - for _, guildRole := range guildRoles { - roles[guildID] = append(roles[guildID], guildRole) - } - i++ - } - return roles -} - -func (c *roleCacheImpl) GuildCache(guildID snowflake.Snowflake) map[snowflake.Snowflake]*Role { - if _, ok := c.roles[guildID]; !ok { - return nil - } - return c.roles[guildID] -} - -func (c *roleCacheImpl) GuildAll(guildID snowflake.Snowflake) []*Role { - if _, ok := c.roles[guildID]; !ok { - return nil - } - roles := make([]*Role, len(c.roles[guildID])) - i := 0 - for _, role := range c.roles[guildID] { - roles = append(roles, role) - i++ - } - return roles -} - -func (c *roleCacheImpl) FindFirst(roleFindFunc RoleFindFunc) *Role { - for _, guildRoles := range c.roles { - for _, role := range guildRoles { - if roleFindFunc(role) { - return role - } - } - } - return nil -} - -func (c *roleCacheImpl) FindAll(roleFindFunc RoleFindFunc) []*Role { - var roles []*Role - for _, guildRoles := range c.roles { - for _, role := range guildRoles { - if roleFindFunc(role) { - roles = append(roles, role) - } - } - } - return roles -} diff --git a/core/cache_stage_instance.go b/core/cache_stage_instance.go deleted file mode 100644 index e6602483..00000000 --- a/core/cache_stage_instance.go +++ /dev/null @@ -1,94 +0,0 @@ -package core - -import "github.com/DisgoOrg/snowflake" - -type ( - StageInstanceFindFunc func(stageInstance *StageInstance) bool - - StageInstanceCache interface { - Get(stageInstanceID snowflake.Snowflake) *StageInstance - GetCopy(stageInstanceID snowflake.Snowflake) *StageInstance - Set(stageInstance *StageInstance) *StageInstance - Remove(stageInstanceID snowflake.Snowflake) - - Cache() map[snowflake.Snowflake]*StageInstance - All() []*StageInstance - - FindFirst(stageInstanceFindFunc StageInstanceFindFunc) *StageInstance - FindAll(stageInstanceFindFunc StageInstanceFindFunc) []*StageInstance - } - - stageInstanceCacheImpl struct { - cacheFlags CacheFlags - stageInstances map[snowflake.Snowflake]*StageInstance - } -) - -func NewStageInstanceCache(cacheFlags CacheFlags) StageInstanceCache { - return &stageInstanceCacheImpl{ - cacheFlags: cacheFlags, - stageInstances: map[snowflake.Snowflake]*StageInstance{}, - } -} - -func (c *stageInstanceCacheImpl) Get(stageInstanceID snowflake.Snowflake) *StageInstance { - return c.stageInstances[stageInstanceID] -} - -func (c *stageInstanceCacheImpl) GetCopy(stageInstanceID snowflake.Snowflake) *StageInstance { - if stageInstance := c.Get(stageInstanceID); stageInstance != nil { - st := *stageInstance - return &st - } - return nil -} - -func (c *stageInstanceCacheImpl) Set(stageInstance *StageInstance) *StageInstance { - if c.cacheFlags.Missing(CacheFlagStageInstances) { - return stageInstance - } - stI, ok := c.stageInstances[stageInstance.ID] - if ok { - *stI = *stageInstance - return stI - } - c.stageInstances[stageInstance.ID] = stageInstance - return stageInstance -} - -func (c *stageInstanceCacheImpl) Remove(id snowflake.Snowflake) { - delete(c.stageInstances, id) -} - -func (c *stageInstanceCacheImpl) Cache() map[snowflake.Snowflake]*StageInstance { - return c.stageInstances -} - -func (c *stageInstanceCacheImpl) All() []*StageInstance { - stageInstances := make([]*StageInstance, len(c.stageInstances)) - i := 0 - for _, stageInstance := range c.stageInstances { - stageInstances[i] = stageInstance - i++ - } - return stageInstances -} - -func (c *stageInstanceCacheImpl) FindFirst(stageInstanceFindFunc StageInstanceFindFunc) *StageInstance { - for _, stI := range c.stageInstances { - if stageInstanceFindFunc(stI) { - return stI - } - } - return nil -} - -func (c *stageInstanceCacheImpl) FindAll(stageInstanceFindFunc StageInstanceFindFunc) []*StageInstance { - var stageInstances []*StageInstance - for _, stI := range c.stageInstances { - if stageInstanceFindFunc(stI) { - stageInstances = append(stageInstances, stI) - } - } - return stageInstances -} diff --git a/core/cache_sticker.go b/core/cache_sticker.go deleted file mode 100644 index 458f2ad9..00000000 --- a/core/cache_sticker.go +++ /dev/null @@ -1,137 +0,0 @@ -package core - -import "github.com/DisgoOrg/snowflake" - -type ( - StickerFindFunc func(sticker *Sticker) bool - - StickerCache interface { - Get(guildID snowflake.Snowflake, stickerID snowflake.Snowflake) *Sticker - GetCopy(guildID snowflake.Snowflake, stickerID snowflake.Snowflake) *Sticker - Set(sticker *Sticker) *Sticker - Remove(guildID snowflake.Snowflake, stickerID snowflake.Snowflake) - - Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*Sticker - All() map[snowflake.Snowflake][]*Sticker - - GuildCache(guildID snowflake.Snowflake) map[snowflake.Snowflake]*Sticker - GuildAll(guildID snowflake.Snowflake) []*Sticker - - FindFirst(stickerFindFunc StickerFindFunc) *Sticker - FindAll(stickerFindFunc StickerFindFunc) []*Sticker - } - - stickerCacheImpl struct { - cacheFlags CacheFlags - stickers map[snowflake.Snowflake]map[snowflake.Snowflake]*Sticker - } -) - -func NewStickerCache(cacheFlags CacheFlags) StickerCache { - return &stickerCacheImpl{ - cacheFlags: cacheFlags, - stickers: map[snowflake.Snowflake]map[snowflake.Snowflake]*Sticker{}, - } -} - -func (c *stickerCacheImpl) Get(guildID snowflake.Snowflake, stickerID snowflake.Snowflake) *Sticker { - if _, ok := c.stickers[guildID]; !ok { - return nil - } - return c.stickers[guildID][stickerID] -} - -func (c *stickerCacheImpl) GetCopy(guildID snowflake.Snowflake, stickerID snowflake.Snowflake) *Sticker { - if sticker := c.Get(guildID, stickerID); sticker != nil { - st := *sticker - return &st - } - return nil -} - -func (c *stickerCacheImpl) Set(sticker *Sticker) *Sticker { - if sticker.GuildID == nil { - return sticker - } - if c.cacheFlags.Missing(CacheFlagStickers) { - return sticker - } - if _, ok := c.stickers[*sticker.GuildID]; !ok { - c.stickers[*sticker.GuildID] = map[snowflake.Snowflake]*Sticker{} - } - st, ok := c.stickers[*sticker.GuildID][sticker.ID] - if ok { - *st = *sticker - return st - } - c.stickers[*sticker.GuildID][sticker.ID] = sticker - - return sticker -} - -func (c *stickerCacheImpl) Remove(guildID snowflake.Snowflake, stickerID snowflake.Snowflake) { - if _, ok := c.stickers[guildID]; !ok { - return - } - delete(c.stickers[guildID], stickerID) -} - -func (c *stickerCacheImpl) Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*Sticker { - return c.stickers -} - -func (c *stickerCacheImpl) All() map[snowflake.Snowflake][]*Sticker { - stickers := make(map[snowflake.Snowflake][]*Sticker, len(c.stickers)) - for guildID, guildStickers := range c.stickers { - stickers[guildID] = make([]*Sticker, len(guildStickers)) - i := 0 - for _, guildSticker := range guildStickers { - stickers[guildID] = append(stickers[guildID], guildSticker) - } - i++ - } - return stickers -} - -func (c *stickerCacheImpl) GuildCache(guildID snowflake.Snowflake) map[snowflake.Snowflake]*Sticker { - if _, ok := c.stickers[guildID]; !ok { - return nil - } - return c.stickers[guildID] -} - -func (c *stickerCacheImpl) GuildAll(guildID snowflake.Snowflake) []*Sticker { - if _, ok := c.stickers[guildID]; !ok { - return nil - } - stickers := make([]*Sticker, len(c.stickers[guildID])) - i := 0 - for _, sticker := range c.stickers[guildID] { - stickers = append(stickers, sticker) - i++ - } - return stickers -} - -func (c *stickerCacheImpl) FindFirst(stickerFindFunc StickerFindFunc) *Sticker { - for _, guildStickers := range c.stickers { - for _, sticker := range guildStickers { - if stickerFindFunc(sticker) { - return sticker - } - } - } - return nil -} - -func (c *stickerCacheImpl) FindAll(stickerFindFunc StickerFindFunc) []*Sticker { - var stickers []*Sticker - for _, guildStickers := range c.stickers { - for _, sticker := range guildStickers { - if stickerFindFunc(sticker) { - stickers = append(stickers, sticker) - } - } - } - return stickers -} diff --git a/core/cache_thread_member.go b/core/cache_thread_member.go deleted file mode 100644 index 07154add..00000000 --- a/core/cache_thread_member.go +++ /dev/null @@ -1,140 +0,0 @@ -package core - -import "github.com/DisgoOrg/snowflake" - -type ( - ThreadMemberFindFunc func(threadMember *ThreadMember) bool - - ThreadMemberCache interface { - Get(threadID snowflake.Snowflake, userID snowflake.Snowflake) *ThreadMember - GetCopy(threadID snowflake.Snowflake, userID snowflake.Snowflake) *ThreadMember - Set(threadMember *ThreadMember) *ThreadMember - Remove(threadID snowflake.Snowflake, userID snowflake.Snowflake) - RemoveAll(threadID snowflake.Snowflake) - - Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*ThreadMember - All() map[snowflake.Snowflake][]*ThreadMember - - ThreadCache(threadID snowflake.Snowflake) map[snowflake.Snowflake]*ThreadMember - ThreadAll(threadID snowflake.Snowflake) []*ThreadMember - - FindFirst(threadMemberFindFunc ThreadMemberFindFunc) *ThreadMember - FindAll(threadMemberFindFunc ThreadMemberFindFunc) []*ThreadMember - } - - threadMemberCacheImpl struct { - cacheFlags CacheFlags - threadMembers map[snowflake.Snowflake]map[snowflake.Snowflake]*ThreadMember - } -) - -func NewThreadMemberCache(cacheFlags CacheFlags) ThreadMemberCache { - return &threadMemberCacheImpl{ - cacheFlags: cacheFlags, - threadMembers: map[snowflake.Snowflake]map[snowflake.Snowflake]*ThreadMember{}, - } -} - -func (c *threadMemberCacheImpl) Get(threadID snowflake.Snowflake, userID snowflake.Snowflake) *ThreadMember { - if _, ok := c.threadMembers[threadID]; !ok { - return nil - } - return c.threadMembers[threadID][userID] -} - -func (c *threadMemberCacheImpl) GetCopy(threadID snowflake.Snowflake, userID snowflake.Snowflake) *ThreadMember { - if threadMember := c.Get(threadID, userID); threadMember != nil { - m := *threadMember - return &m - } - return nil -} - -func (c *threadMemberCacheImpl) Set(threadMember *ThreadMember) *ThreadMember { - // always cache self threadMembers - if c.cacheFlags.Missing(CacheFlagRoles) && threadMember.UserID != threadMember.Bot.ClientID { - return threadMember - } - if _, ok := c.threadMembers[threadMember.ThreadID]; !ok { - c.threadMembers[threadMember.ThreadID] = map[snowflake.Snowflake]*ThreadMember{} - } - rol, ok := c.threadMembers[threadMember.ThreadID][threadMember.UserID] - if ok { - *rol = *threadMember - return rol - } - c.threadMembers[threadMember.ThreadID][threadMember.UserID] = threadMember - - return threadMember -} - -func (c *threadMemberCacheImpl) Remove(threadID snowflake.Snowflake, userID snowflake.Snowflake) { - if _, ok := c.threadMembers[threadID]; !ok { - return - } - delete(c.threadMembers[threadID], userID) -} - -func (c *threadMemberCacheImpl) RemoveAll(threadID snowflake.Snowflake) { - delete(c.threadMembers, threadID) -} - -func (c *threadMemberCacheImpl) Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*ThreadMember { - return c.threadMembers -} - -func (c *threadMemberCacheImpl) All() map[snowflake.Snowflake][]*ThreadMember { - threadMembers := make(map[snowflake.Snowflake][]*ThreadMember, len(c.threadMembers)) - for threadID, guildThreadMembers := range c.threadMembers { - threadMembers[threadID] = make([]*ThreadMember, len(guildThreadMembers)) - i := 0 - for _, threadMember := range guildThreadMembers { - threadMembers[threadID] = append(threadMembers[threadID], threadMember) - } - i++ - } - return threadMembers -} - -func (c *threadMemberCacheImpl) ThreadCache(threadID snowflake.Snowflake) map[snowflake.Snowflake]*ThreadMember { - if _, ok := c.threadMembers[threadID]; !ok { - return nil - } - return c.threadMembers[threadID] -} - -func (c *threadMemberCacheImpl) ThreadAll(threadID snowflake.Snowflake) []*ThreadMember { - if _, ok := c.threadMembers[threadID]; !ok { - return nil - } - threadMembers := make([]*ThreadMember, len(c.threadMembers[threadID])) - i := 0 - for _, threadMember := range c.threadMembers[threadID] { - threadMembers = append(threadMembers, threadMember) - i++ - } - return threadMembers -} - -func (c *threadMemberCacheImpl) FindFirst(threadMemberFindFunc ThreadMemberFindFunc) *ThreadMember { - for _, guildThreadMembers := range c.threadMembers { - for _, threadMember := range guildThreadMembers { - if threadMemberFindFunc(threadMember) { - return threadMember - } - } - } - return nil -} - -func (c *threadMemberCacheImpl) FindAll(threadMemberFindFunc ThreadMemberFindFunc) []*ThreadMember { - var threadMembers []*ThreadMember - for _, guildThreadMembers := range c.threadMembers { - for _, threadMember := range guildThreadMembers { - if threadMemberFindFunc(threadMember) { - threadMembers = append(threadMembers, threadMember) - } - } - } - return threadMembers -} diff --git a/core/cache_voice_state.go b/core/cache_voice_state.go deleted file mode 100644 index c7a57f65..00000000 --- a/core/cache_voice_state.go +++ /dev/null @@ -1,134 +0,0 @@ -package core - -import "github.com/DisgoOrg/snowflake" - -type ( - VoiceStateFindFunc func(voiceState *VoiceState) bool - - VoiceStateCache interface { - Get(guildID snowflake.Snowflake, userID snowflake.Snowflake) *VoiceState - GetCopy(guildID snowflake.Snowflake, userID snowflake.Snowflake) *VoiceState - Set(voiceState *VoiceState) *VoiceState - Remove(guildID snowflake.Snowflake, userID snowflake.Snowflake) - - Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*VoiceState - All() map[snowflake.Snowflake][]*VoiceState - - GuildCache(guildID snowflake.Snowflake) map[snowflake.Snowflake]*VoiceState - GuildAll(guildID snowflake.Snowflake) []*VoiceState - - FindFirst(voiceStateFindFunc VoiceStateFindFunc) *VoiceState - FindAll(voiceStateFindFunc VoiceStateFindFunc) []*VoiceState - } - - voiceStateCacheImpl struct { - cacheFlags CacheFlags - voiceStates map[snowflake.Snowflake]map[snowflake.Snowflake]*VoiceState - } -) - -func NewVoiceStateCache(cacheFlags CacheFlags) VoiceStateCache { - return &voiceStateCacheImpl{ - cacheFlags: cacheFlags, - voiceStates: map[snowflake.Snowflake]map[snowflake.Snowflake]*VoiceState{}, - } -} - -func (c *voiceStateCacheImpl) Get(guildID snowflake.Snowflake, userID snowflake.Snowflake) *VoiceState { - if _, ok := c.voiceStates[guildID]; !ok { - return nil - } - return c.voiceStates[guildID][userID] -} - -func (c *voiceStateCacheImpl) GetCopy(guildID snowflake.Snowflake, userID snowflake.Snowflake) *VoiceState { - if voiceState := c.Get(guildID, userID); voiceState != nil { - vs := *voiceState - return &vs - } - return nil -} - -func (c *voiceStateCacheImpl) Set(voiceState *VoiceState) *VoiceState { - if c.cacheFlags.Missing(CacheFlagVoiceStates) { - return voiceState - } - if _, ok := c.voiceStates[voiceState.GuildID]; !ok { - c.voiceStates[voiceState.GuildID] = map[snowflake.Snowflake]*VoiceState{} - } - rol, ok := c.voiceStates[voiceState.GuildID][voiceState.UserID] - if ok { - *rol = *voiceState - return rol - } - c.voiceStates[voiceState.GuildID][voiceState.UserID] = voiceState - - return voiceState -} - -func (c *voiceStateCacheImpl) Remove(guildID snowflake.Snowflake, userID snowflake.Snowflake) { - if _, ok := c.voiceStates[guildID]; !ok { - return - } - delete(c.voiceStates[guildID], userID) -} - -func (c *voiceStateCacheImpl) Cache() map[snowflake.Snowflake]map[snowflake.Snowflake]*VoiceState { - return c.voiceStates -} - -func (c *voiceStateCacheImpl) All() map[snowflake.Snowflake][]*VoiceState { - voiceStates := make(map[snowflake.Snowflake][]*VoiceState, len(c.voiceStates)) - for guildID, guildVoiceStates := range c.voiceStates { - voiceStates[guildID] = make([]*VoiceState, len(guildVoiceStates)) - i := 0 - for _, voiceStateVoiceState := range guildVoiceStates { - voiceStates[guildID] = append(voiceStates[guildID], voiceStateVoiceState) - } - i++ - } - return voiceStates -} - -func (c *voiceStateCacheImpl) GuildCache(guildID snowflake.Snowflake) map[snowflake.Snowflake]*VoiceState { - if _, ok := c.voiceStates[guildID]; !ok { - return nil - } - return c.voiceStates[guildID] -} - -func (c *voiceStateCacheImpl) GuildAll(guildID snowflake.Snowflake) []*VoiceState { - if _, ok := c.voiceStates[guildID]; !ok { - return nil - } - voiceStates := make([]*VoiceState, len(c.voiceStates[guildID])) - i := 0 - for _, voiceState := range c.voiceStates[guildID] { - voiceStates = append(voiceStates, voiceState) - i++ - } - return voiceStates -} - -func (c *voiceStateCacheImpl) FindFirst(voiceStateFindFunc VoiceStateFindFunc) *VoiceState { - for _, guildVoiceStates := range c.voiceStates { - for _, voiceState := range guildVoiceStates { - if voiceStateFindFunc(voiceState) { - return voiceState - } - } - } - return nil -} - -func (c *voiceStateCacheImpl) FindAll(voiceStateFindFunc VoiceStateFindFunc) []*VoiceState { - var voiceStates []*VoiceState - for _, guildVoiceStates := range c.voiceStates { - for _, voiceState := range guildVoiceStates { - if voiceStateFindFunc(voiceState) { - voiceStates = append(voiceStates, voiceState) - } - } - } - return voiceStates -} diff --git a/core/caches.go b/core/caches.go deleted file mode 100644 index 472f9071..00000000 --- a/core/caches.go +++ /dev/null @@ -1,113 +0,0 @@ -package core - -type Caches interface { - Config() CacheConfig - - Users() UserCache - Roles() RoleCache - Members() MemberCache - ThreadMembers() ThreadMemberCache - Presences() PresenceCache - VoiceStates() VoiceStateCache - Messages() MessageCache - Emojis() EmojiCache - Stickers() StickerCache - Guilds() GuildCache - Channels() ChannelCache - StageInstances() StageInstanceCache - GuildScheduledEvents() GuildScheduledEventCache -} - -func NewCaches(config CacheConfig) Caches { - return &cachesImpl{ - config: config, - - userCache: NewUserCache(config.CacheFlags), - roleCache: NewRoleCache(config.CacheFlags), - memberCache: NewMemberCache(config.MemberCachePolicy), - threadMemberCache: NewThreadMemberCache(config.CacheFlags), - presenceCache: NewPresenceCache(config.CacheFlags), - voiceStateCache: NewVoiceStateCache(config.CacheFlags), - messageCache: NewMessageCache(config.MessageCachePolicy), - emojiCache: NewEmojiCache(config.CacheFlags), - stickerCache: NewStickerCache(config.CacheFlags), - guildCache: NewGuildCache(config.CacheFlags), - channelCache: NewChannelCache(config.CacheFlags), - stageInstanceCache: NewStageInstanceCache(config.CacheFlags), - guildScheduledEventCache: NewGuildScheduledEventCache(config.CacheFlags), - } -} - -type cachesImpl struct { - config CacheConfig - - userCache UserCache - roleCache RoleCache - memberCache MemberCache - threadMemberCache ThreadMemberCache - presenceCache PresenceCache - voiceStateCache VoiceStateCache - messageCache MessageCache - emojiCache EmojiCache - stickerCache StickerCache - guildCache GuildCache - channelCache ChannelCache - stageInstanceCache StageInstanceCache - guildScheduledEventCache GuildScheduledEventCache -} - -func (c *cachesImpl) Config() CacheConfig { - return c.config -} - -func (c *cachesImpl) Users() UserCache { - return c.userCache -} - -func (c *cachesImpl) Roles() RoleCache { - return c.roleCache -} - -func (c *cachesImpl) Members() MemberCache { - return c.memberCache -} - -func (c *cachesImpl) ThreadMembers() ThreadMemberCache { - return c.threadMemberCache -} - -func (c *cachesImpl) Presences() PresenceCache { - return c.presenceCache -} - -func (c *cachesImpl) VoiceStates() VoiceStateCache { - return c.voiceStateCache -} - -func (c *cachesImpl) Messages() MessageCache { - return c.messageCache -} - -func (c *cachesImpl) Emojis() EmojiCache { - return c.emojiCache -} - -func (c *cachesImpl) Stickers() StickerCache { - return c.stickerCache -} - -func (c *cachesImpl) Guilds() GuildCache { - return c.guildCache -} - -func (c *cachesImpl) Channels() ChannelCache { - return c.channelCache -} - -func (c *cachesImpl) StageInstances() StageInstanceCache { - return c.stageInstanceCache -} - -func (c *cachesImpl) GuildScheduledEvents() GuildScheduledEventCache { - return c.guildScheduledEventCache -} diff --git a/core/channel.go b/core/channel.go deleted file mode 100644 index 8b4820dd..00000000 --- a/core/channel.go +++ /dev/null @@ -1,1934 +0,0 @@ -package core - -import ( - "context" - - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" - "github.com/pkg/errors" -) - -type Channel interface { - discord.Channel - set(channel Channel) Channel -} - -type GuildChannel interface { - discord.GuildChannel - Channel - Guild() *Guild - - UpdateGuildChannel(guildChannelUpdate discord.GuildChannelUpdate, opts ...rest.RequestOpt) (GuildChannel, error) - Delete(opts ...rest.RequestOpt) error - - PermissionOverwrites() []discord.PermissionOverwrite - PermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake) discord.PermissionOverwrite - RolePermissionOverwrite(id snowflake.Snowflake) *discord.RolePermissionOverwrite - MemberPermissionOverwrite(id snowflake.Snowflake) *discord.MemberPermissionOverwrite - SetPermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error - UpdatePermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error - DeletePermissionOverwrite(id snowflake.Snowflake, opts ...rest.RequestOpt) error - - Members() []*Member -} - -type MessageChannel interface { - discord.MessageChannel - Channel - - SendTyping(opts ...rest.RequestOpt) error - - GetMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) (*Message, error) - GetMessages(around snowflake.Snowflake, before snowflake.Snowflake, after snowflake.Snowflake, limit int, opts ...rest.RequestOpt) ([]*Message, error) - CreateMessage(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) - UpdateMessage(messageID snowflake.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) - DeleteMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error - BulkDeleteMessages(messageIDs []snowflake.Snowflake, opts ...rest.RequestOpt) error - - AddReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error - RemoveOwnReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error - RemoveUserReaction(messageID snowflake.Snowflake, emoji string, userID snowflake.Snowflake, opts ...rest.RequestOpt) error - RemoveAllReactions(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error - RemoveAllReactionsForEmoji(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error -} - -type BaseGuildMessageChannel interface { - discord.BaseGuildMessageChannel - GuildChannel - MessageChannel -} - -type GuildMessageChannel interface { - discord.GuildMessageChannel - BaseGuildMessageChannel - - GetWebhooks(opts ...rest.RequestOpt) ([]Webhook, error) - CreateWebhook(webhookCreate discord.WebhookCreate, opts ...rest.RequestOpt) (Webhook, error) - DeleteWebhook(webhookID snowflake.Snowflake, opts ...rest.RequestOpt) error - - Threads() []GuildThread - Thread(threadID snowflake.Snowflake) GuildThread - - CreateThread(theadCreate discord.ThreadCreate, opts ...rest.RequestOpt) (GuildThread, error) - CreateThreadWithMessage(messageID snowflake.Snowflake, threadCreateWithMessage discord.ThreadCreateWithMessage, opts ...rest.RequestOpt) (GuildThread, error) - - GetPublicArchivedThreads(before discord.Time, limit int, opts ...rest.RequestOpt) ([]GuildThread, map[snowflake.Snowflake]*ThreadMember, bool, error) -} - -type GuildThread interface { - discord.GuildThread - BaseGuildMessageChannel - - ParentMessageChannel() GuildMessageChannel - SelfThreadMember() *ThreadMember - ThreadMember(userID snowflake.Snowflake) *ThreadMember - ThreadMembers() []*ThreadMember - Join(opts ...rest.RequestOpt) error - Leave(opts ...rest.RequestOpt) error - AddThreadMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) error - RemoveThreadMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) error - GetThreadMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) (*ThreadMember, error) - GetThreadMembers(opts ...rest.RequestOpt) ([]*ThreadMember, error) -} - -type GuildAudioChannel interface { - discord.GuildAudioChannel - GuildChannel - - Connect(ctx context.Context) error - connectedMembers() map[snowflake.Snowflake]struct{} -} - -var ( - _ Channel = (*GuildTextChannel)(nil) - _ GuildChannel = (*GuildTextChannel)(nil) - _ MessageChannel = (*GuildTextChannel)(nil) - _ GuildMessageChannel = (*GuildTextChannel)(nil) -) - -type GuildTextChannel struct { - discord.GuildTextChannel - Bot *Bot -} - -func (c *GuildTextChannel) set(channel Channel) Channel { - switch ch := channel.(type) { - case *GuildTextChannel: - *c = *ch - return c - - default: - return c - } -} - -func (c *GuildTextChannel) UpdateGuildChannel(guildChannelUpdate discord.GuildChannelUpdate, opts ...rest.RequestOpt) (GuildChannel, error) { - channel, err := updateChannel(c.Bot, c.ID(), guildChannelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(GuildChannel), nil -} - -// Update updates the GuildNewsChannel which can return either a GuildNewsChannel or a GuildTextChannel -func (c *GuildTextChannel) Update(channelUpdate discord.GuildTextChannelUpdate, opts ...rest.RequestOpt) (GuildMessageChannel, error) { - channel, err := c.UpdateGuildChannel(channelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(GuildMessageChannel), nil -} - -func (c *GuildTextChannel) Delete(opts ...rest.RequestOpt) error { - return deleteChannel(c.Bot, c.ID(), opts...) -} - -func (c *GuildTextChannel) PermissionOverwrites() []discord.PermissionOverwrite { - return c.ChannelPermissionOverwrites -} - -func (c *GuildTextChannel) PermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake) discord.PermissionOverwrite { - return getPermissionOverwrite(c, overwriteType, id) -} - -func (c *GuildTextChannel) RolePermissionOverwrite(id snowflake.Snowflake) *discord.RolePermissionOverwrite { - if overwrite := getPermissionOverwrite(c, discord.PermissionOverwriteTypeRole, id); overwrite != nil { - return overwrite.(*discord.RolePermissionOverwrite) - } - return nil -} - -func (c *GuildTextChannel) MemberPermissionOverwrite(id snowflake.Snowflake) *discord.MemberPermissionOverwrite { - if overwrite := getPermissionOverwrite(c, discord.PermissionOverwriteTypeMember, id); overwrite != nil { - return overwrite.(*discord.MemberPermissionOverwrite) - } - return nil -} - -func (c *GuildTextChannel) SetPermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return setPermissionOverwrite(c.Bot, c.ID(), overwriteType, id, allow, deny, opts...) -} - -func (c *GuildTextChannel) UpdatePermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return updatePermissionOverwrite(c.Bot, c, overwriteType, id, allow, deny, opts...) -} - -func (c *GuildTextChannel) DeletePermissionOverwrite(id snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deletePermissionOverwrite(c.Bot, c.ID(), id, opts...) -} - -func (c *GuildTextChannel) GetMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - return getMessage(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildTextChannel) GetMessages(around snowflake.Snowflake, before snowflake.Snowflake, after snowflake.Snowflake, limit int, opts ...rest.RequestOpt) ([]*Message, error) { - return getMessages(c.Bot, c.ID(), around, before, after, limit, opts...) -} - -func (c *GuildTextChannel) CreateMessage(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - return createMessage(c.Bot, c.ID(), messageCreate, opts...) -} - -func (c *GuildTextChannel) UpdateMessage(messageID snowflake.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateMessage(c.Bot, c.ID(), messageID, messageUpdate, opts...) -} - -func (c *GuildTextChannel) DeleteMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deleteMessage(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildTextChannel) BulkDeleteMessages(messageIDs []snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bulkDeleteMessages(c.Bot, c.ID(), messageIDs, opts...) -} - -func (c *GuildTextChannel) SendTyping(opts ...rest.RequestOpt) error { - return sendTying(c.Bot, c.ID(), opts...) -} - -func (c *GuildTextChannel) AddReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return addReaction(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildTextChannel) RemoveOwnReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return removeOwnReaction(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildTextChannel) RemoveUserReaction(messageID snowflake.Snowflake, emoji string, userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeUserReaction(c.Bot, c.ID(), messageID, emoji, userID, opts...) -} - -func (c *GuildTextChannel) RemoveAllReactions(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeAllReactions(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildTextChannel) RemoveAllReactionsForEmoji(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return removeAllReactionsForEmoji(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildTextChannel) GetWebhooks(opts ...rest.RequestOpt) ([]Webhook, error) { - return getWebhooks(c.Bot, c.ID(), opts...) -} - -func (c *GuildTextChannel) CreateWebhook(webhookCreate discord.WebhookCreate, opts ...rest.RequestOpt) (Webhook, error) { - return createWebhook(c.Bot, c.ID(), webhookCreate, opts...) -} - -func (c *GuildTextChannel) DeleteWebhook(webhookID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deleteWebhook(c.Bot, webhookID, opts...) -} - -func (c *GuildTextChannel) Threads() []GuildThread { - var threads []GuildThread - c.Bot.Caches.Channels().ForAll(func(channel Channel) { - if thread, ok := channel.(GuildThread); ok && thread.ParentID() == c.ID() { - threads = append(threads, thread) - } - }) - return threads -} - -func (c *GuildTextChannel) Thread(threadID snowflake.Snowflake) GuildThread { - if thread, ok := c.Bot.Caches.Channels().Get(threadID).(GuildThread); ok { - return thread - } - return nil -} - -func (c *GuildTextChannel) PrivateThreads() []*GuildPrivateThread { - var threads []*GuildPrivateThread - c.Bot.Caches.Channels().ForAll(func(channel Channel) { - if thread, ok := channel.(*GuildPrivateThread); ok && thread.ParentID() == c.ID() { - threads = append(threads, thread) - } - }) - return threads -} - -func (c *GuildTextChannel) PublicThreads() []*GuildPublicThread { - var threads []*GuildPublicThread - c.Bot.Caches.Channels().ForAll(func(channel Channel) { - if thread, ok := channel.(*GuildPublicThread); ok && thread.ParentID() == c.ID() { - threads = append(threads, thread) - } - }) - return threads -} - -func (c *GuildTextChannel) CreateThread(theadCreate discord.ThreadCreate, opts ...rest.RequestOpt) (GuildThread, error) { - return createThread(c.Bot, c.ID(), theadCreate, opts...) -} - -func (c *GuildTextChannel) CreateThreadWithMessage(messageID snowflake.Snowflake, threadCreateWithMessage discord.ThreadCreateWithMessage, opts ...rest.RequestOpt) (GuildThread, error) { - return createThreadWithMessage(c.Bot, c.ID(), messageID, threadCreateWithMessage, opts...) -} - -func createThreadMembers(bot *Bot, members []discord.ThreadMember) map[snowflake.Snowflake]*ThreadMember { - threadMembers := make(map[snowflake.Snowflake]*ThreadMember, len(members)) - for i := range members { - threadMembers[members[i].ThreadID] = bot.EntityBuilder.CreateThreadMember(members[i], CacheStrategyNo) - } - return threadMembers -} - -func (c *GuildTextChannel) GetPublicArchivedThreads(before discord.Time, limit int, opts ...rest.RequestOpt) ([]GuildThread, map[snowflake.Snowflake]*ThreadMember, bool, error) { - return getPublicArchivedThreads(c.Bot, c.ID(), before, limit, opts...) -} - -func createGuildPrivateThreads(bot *Bot, threads []discord.GuildThread) []*GuildPrivateThread { - privateThreads := make([]*GuildPrivateThread, len(threads)) - for i := range threads { - privateThreads[i] = bot.EntityBuilder.CreateChannel(threads[i], CacheStrategyNo).(*GuildPrivateThread) - } - return privateThreads -} - -func (c *GuildTextChannel) GetPrivateArchivedThreads(before discord.Time, limit int, opts ...rest.RequestOpt) ([]*GuildPrivateThread, map[snowflake.Snowflake]*ThreadMember, bool, error) { - getThreads, err := c.Bot.RestServices.ThreadService().GetPrivateArchivedThreads(c.ID(), before, limit, opts...) - if err != nil { - return nil, nil, false, err - } - - return createGuildPrivateThreads(c.Bot, getThreads.Threads), createThreadMembers(c.Bot, getThreads.Members), getThreads.HasMore, nil -} - -func (c *GuildTextChannel) GetJoinedPrivateAchievedThreads(before discord.Time, limit int, opts ...rest.RequestOpt) ([]*GuildPrivateThread, map[snowflake.Snowflake]*ThreadMember, bool, error) { - getThreads, err := c.Bot.RestServices.ThreadService().GetJoinedPrivateArchivedThreads(c.ID(), before, limit, opts...) - if err != nil { - return nil, nil, false, err - } - - return createGuildPrivateThreads(c.Bot, getThreads.Threads), createThreadMembers(c.Bot, getThreads.Members), getThreads.HasMore, nil -} - -func (c *GuildTextChannel) Guild() *Guild { - return channelGuild(c.Bot, c.GuildID()) -} - -func (c *GuildTextChannel) Parent() *GuildCategoryChannel { - if c.ParentID == nil { - return nil - } - return c.Bot.Caches.Channels().Get(*c.ParentID).(*GuildCategoryChannel) -} - -func (c *GuildTextChannel) Members() []*Member { - return viewMembers(c.Bot, c) -} - -var ( - _ Channel = (*DMChannel)(nil) - _ MessageChannel = (*DMChannel)(nil) -) - -type DMChannel struct { - discord.DMChannel - Bot *Bot - RecipientIDs []snowflake.Snowflake -} - -func (c *DMChannel) set(channel Channel) Channel { - switch ch := channel.(type) { - case *DMChannel: - *c = *ch - return c - - default: - return c - } -} - -func (c *DMChannel) Delete(opts ...rest.RequestOpt) error { - return deleteChannel(c.Bot, c.ID(), opts...) -} - -func (c *DMChannel) GetMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - return getMessage(c.Bot, c.ID(), messageID, opts...) -} - -func (c *DMChannel) GetMessages(around snowflake.Snowflake, before snowflake.Snowflake, after snowflake.Snowflake, limit int, opts ...rest.RequestOpt) ([]*Message, error) { - return getMessages(c.Bot, c.ID(), around, before, after, limit, opts...) -} - -func (c *DMChannel) CreateMessage(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - return createMessage(c.Bot, c.ID(), messageCreate, opts...) -} - -func (c *DMChannel) UpdateMessage(messageID snowflake.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateMessage(c.Bot, c.ID(), messageID, messageUpdate, opts...) -} - -func (c *DMChannel) DeleteMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deleteMessage(c.Bot, c.ID(), messageID, opts...) -} - -func (c *DMChannel) BulkDeleteMessages(messageIDs []snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bulkDeleteMessages(c.Bot, c.ID(), messageIDs, opts...) -} - -func (c *DMChannel) SendTyping(opts ...rest.RequestOpt) error { - return sendTying(c.Bot, c.ID(), opts...) -} - -func (c *DMChannel) AddReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return addReaction(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *DMChannel) RemoveOwnReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return removeOwnReaction(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *DMChannel) RemoveUserReaction(messageID snowflake.Snowflake, emoji string, userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeUserReaction(c.Bot, c.ID(), messageID, emoji, userID, opts...) -} - -func (c *DMChannel) RemoveAllReactions(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeAllReactions(c.Bot, c.ID(), messageID, opts...) -} - -func (c *DMChannel) RemoveAllReactionsForEmoji(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return removeAllReactionsForEmoji(c.Bot, c.ID(), messageID, emoji, opts...) -} - -var ( - _ Channel = (*GuildVoiceChannel)(nil) - _ GuildChannel = (*GuildVoiceChannel)(nil) - _ GuildAudioChannel = (*GuildVoiceChannel)(nil) -) - -type GuildVoiceChannel struct { - discord.GuildVoiceChannel - Bot *Bot - ConnectedMemberIDs map[snowflake.Snowflake]struct{} -} - -func (c *GuildVoiceChannel) set(channel Channel) Channel { - switch ch := channel.(type) { - case *GuildVoiceChannel: - *c = *ch - return c - - default: - return c - } -} - -func (c *GuildVoiceChannel) UpdateGuildChannel(guildChannelUpdate discord.GuildChannelUpdate, opts ...rest.RequestOpt) (GuildChannel, error) { - channel, err := updateChannel(c.Bot, c.ID(), guildChannelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(GuildChannel), nil -} - -// Update updates the GuildNewsChannel which can return either a GuildNewsChannel or a GuildTextChannel -func (c *GuildVoiceChannel) Update(channelUpdate discord.GuildVoiceChannelUpdate, opts ...rest.RequestOpt) (*GuildVoiceChannel, error) { - channel, err := c.UpdateGuildChannel(channelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(*GuildVoiceChannel), nil -} - -func (c *GuildVoiceChannel) Delete(opts ...rest.RequestOpt) error { - return deleteChannel(c.Bot, c.ID(), opts...) -} - -func (c *GuildVoiceChannel) PermissionOverwrites() []discord.PermissionOverwrite { - return c.ChannelPermissionOverwrites -} - -func (c *GuildVoiceChannel) PermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake) discord.PermissionOverwrite { - return getPermissionOverwrite(c, overwriteType, id) -} - -func (c *GuildVoiceChannel) RolePermissionOverwrite(id snowflake.Snowflake) *discord.RolePermissionOverwrite { - return getPermissionOverwrite(c, discord.PermissionOverwriteTypeRole, id).(*discord.RolePermissionOverwrite) -} - -func (c *GuildVoiceChannel) MemberPermissionOverwrite(id snowflake.Snowflake) *discord.MemberPermissionOverwrite { - return getPermissionOverwrite(c, discord.PermissionOverwriteTypeMember, id).(*discord.MemberPermissionOverwrite) -} - -func (c *GuildVoiceChannel) SetPermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return setPermissionOverwrite(c.Bot, c.ID(), overwriteType, id, allow, deny, opts...) -} - -func (c *GuildVoiceChannel) UpdatePermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return updatePermissionOverwrite(c.Bot, c, overwriteType, id, allow, deny, opts...) -} - -func (c *GuildVoiceChannel) DeletePermissionOverwrite(id snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deletePermissionOverwrite(c.Bot, c.ID(), id, opts...) -} - -func (c *GuildVoiceChannel) Guild() *Guild { - return channelGuild(c.Bot, c.GuildID()) -} - -func (c *GuildVoiceChannel) Parent() *GuildCategoryChannel { - if c.ParentID == nil { - return nil - } - return c.Bot.Caches.Channels().Get(*c.ParentID).(*GuildCategoryChannel) -} - -func (c *GuildVoiceChannel) Connect(ctx context.Context) error { - return c.Bot.AudioController.Connect(ctx, c.GuildID(), c.ID()) -} - -func (c *GuildVoiceChannel) Members() []*Member { - return connectedMembers(c.Bot, c) -} - -func (c *GuildVoiceChannel) connectedMembers() map[snowflake.Snowflake]struct{} { - return c.ConnectedMemberIDs -} - -var ( - _ Channel = (*GroupDMChannel)(nil) - //_ MessageChannel = (*GroupDMChannel)(nil) -) - -type GroupDMChannel struct { - discord.GroupDMChannel - Bot *Bot - RecipientIDs []snowflake.Snowflake -} - -func (c *GroupDMChannel) set(channel Channel) Channel { - switch ch := channel.(type) { - case *GroupDMChannel: - *c = *ch - return c - - default: - return c - } -} - -func (c *GroupDMChannel) Update(channelUpdate discord.GroupDMChannelUpdate, opts ...rest.RequestOpt) (*GroupDMChannel, error) { - channel, err := updateChannel(c.Bot, c.ID(), channelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(*GroupDMChannel), nil -} - -func (c *GroupDMChannel) Delete(opts ...rest.RequestOpt) error { - return deleteChannel(c.Bot, c.ID(), opts...) -} - -// GetIconURL returns the Icon URL of this channel. -func (c *GroupDMChannel) GetIconURL(size int) *string { - return discord.FormatAssetURL(route.ChannelIcon, c.ID(), c.Icon, size) -} - -var ( - _ Channel = (*GuildCategoryChannel)(nil) - _ GuildChannel = (*GuildCategoryChannel)(nil) -) - -type GuildCategoryChannel struct { - discord.GuildCategoryChannel - Bot *Bot -} - -func (c *GuildCategoryChannel) set(channel Channel) Channel { - switch ch := channel.(type) { - case *GuildCategoryChannel: - *c = *ch - return c - - default: - return c - } -} - -func (c *GuildCategoryChannel) UpdateGuildChannel(guildChannelUpdate discord.GuildChannelUpdate, opts ...rest.RequestOpt) (GuildChannel, error) { - channel, err := updateChannel(c.Bot, c.ID(), guildChannelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(GuildChannel), nil -} - -// Update updates the GuildNewsChannel which can return either a GuildNewsChannel or a GuildTextChannel -func (c *GuildCategoryChannel) Update(channelUpdate discord.GuildCategoryChannelUpdate, opts ...rest.RequestOpt) (*GuildCategoryChannel, error) { - channel, err := c.UpdateGuildChannel(channelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(*GuildCategoryChannel), nil -} - -func (c *GuildCategoryChannel) Delete(opts ...rest.RequestOpt) error { - return deleteChannel(c.Bot, c.ChannelID, opts...) -} - -func (c *GuildCategoryChannel) PermissionOverwrites() []discord.PermissionOverwrite { - return c.ChannelPermissionOverwrites -} - -func (c *GuildCategoryChannel) PermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake) discord.PermissionOverwrite { - return getPermissionOverwrite(c, overwriteType, id) -} - -func (c *GuildCategoryChannel) RolePermissionOverwrite(id snowflake.Snowflake) *discord.RolePermissionOverwrite { - return getPermissionOverwrite(c, discord.PermissionOverwriteTypeRole, id).(*discord.RolePermissionOverwrite) -} - -func (c *GuildCategoryChannel) MemberPermissionOverwrite(id snowflake.Snowflake) *discord.MemberPermissionOverwrite { - return getPermissionOverwrite(c, discord.PermissionOverwriteTypeMember, id).(*discord.MemberPermissionOverwrite) -} - -func (c *GuildCategoryChannel) SetPermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return setPermissionOverwrite(c.Bot, c.ChannelID, overwriteType, id, allow, deny, opts...) -} - -func (c *GuildCategoryChannel) UpdatePermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return updatePermissionOverwrite(c.Bot, c, overwriteType, id, allow, deny, opts...) -} - -func (c *GuildCategoryChannel) DeletePermissionOverwrite(id snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deletePermissionOverwrite(c.Bot, c.ChannelID, id, opts...) -} - -func (c *GuildCategoryChannel) Guild() *Guild { - return channelGuild(c.Bot, c.GuildID()) -} - -func (c *GuildCategoryChannel) Channels() []GuildChannel { - channels := c.Bot.Caches.Channels().FindAll(func(channel Channel) bool { - switch ch := channel.(type) { - case *GuildTextChannel: - return ch.ParentID != nil && *ch.ParentID == c.ChannelID - - default: - return false - } - }) - guildChannels := make([]GuildChannel, len(channels)) - for i := range channels { - guildChannels[i] = channels[i].(GuildChannel) - } - return guildChannels -} - -func (c *GuildCategoryChannel) Members() []*Member { - var members []*Member - memberIds := make(map[snowflake.Snowflake]struct{}) - for _, channel := range c.Channels() { - for _, member := range channel.Members() { - if _, ok := memberIds[member.User.ID]; ok { - continue - } - members = append(members, member) - memberIds[member.User.ID] = struct{}{} - } - } - return members -} - -var ( - _ Channel = (*GuildNewsChannel)(nil) - _ GuildChannel = (*GuildNewsChannel)(nil) - _ MessageChannel = (*GuildNewsChannel)(nil) - _ GuildMessageChannel = (*GuildNewsChannel)(nil) -) - -type GuildNewsChannel struct { - discord.GuildNewsChannel - Bot *Bot -} - -func (c *GuildNewsChannel) set(channel Channel) Channel { - switch ch := channel.(type) { - case *GuildNewsChannel: - *c = *ch - return c - - default: - return c - } -} - -func (c *GuildNewsChannel) UpdateGuildChannel(guildChannelUpdate discord.GuildChannelUpdate, opts ...rest.RequestOpt) (GuildChannel, error) { - channel, err := updateChannel(c.Bot, c.ID(), guildChannelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(GuildChannel), nil -} - -// Update updates the GuildNewsChannel which can return either a GuildNewsChannel or a GuildTextChannel -func (c *GuildNewsChannel) Update(channelUpdate discord.GuildNewsChannelUpdate, opts ...rest.RequestOpt) (GuildMessageChannel, error) { - channel, err := c.UpdateGuildChannel(channelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(GuildMessageChannel), nil -} - -func (c *GuildNewsChannel) Delete(opts ...rest.RequestOpt) error { - return deleteChannel(c.Bot, c.ID(), opts...) -} - -func (c *GuildNewsChannel) PermissionOverwrites() []discord.PermissionOverwrite { - return c.ChannelPermissionOverwrites -} - -func (c *GuildNewsChannel) PermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake) discord.PermissionOverwrite { - return getPermissionOverwrite(c, overwriteType, id) -} - -func (c *GuildNewsChannel) RolePermissionOverwrite(id snowflake.Snowflake) *discord.RolePermissionOverwrite { - return getPermissionOverwrite(c, discord.PermissionOverwriteTypeRole, id).(*discord.RolePermissionOverwrite) -} - -func (c *GuildNewsChannel) MemberPermissionOverwrite(id snowflake.Snowflake) *discord.MemberPermissionOverwrite { - return getPermissionOverwrite(c, discord.PermissionOverwriteTypeMember, id).(*discord.MemberPermissionOverwrite) -} - -func (c *GuildNewsChannel) SetPermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return setPermissionOverwrite(c.Bot, c.ID(), overwriteType, id, allow, deny, opts...) -} - -func (c *GuildNewsChannel) UpdatePermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return updatePermissionOverwrite(c.Bot, c, overwriteType, id, allow, deny, opts...) -} - -func (c *GuildNewsChannel) DeletePermissionOverwrite(id snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deletePermissionOverwrite(c.Bot, c.ID(), id, opts...) -} - -func (c *GuildNewsChannel) GetMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - return getMessage(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildNewsChannel) GetMessages(around snowflake.Snowflake, before snowflake.Snowflake, after snowflake.Snowflake, limit int, opts ...rest.RequestOpt) ([]*Message, error) { - return getMessages(c.Bot, c.ID(), around, before, after, limit, opts...) -} - -func (c *GuildNewsChannel) CreateMessage(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - return createMessage(c.Bot, c.ID(), messageCreate, opts...) -} - -func (c *GuildNewsChannel) UpdateMessage(messageID snowflake.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateMessage(c.Bot, c.ID(), messageID, messageUpdate, opts...) -} - -func (c *GuildNewsChannel) DeleteMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deleteMessage(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildNewsChannel) BulkDeleteMessages(messageIDs []snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bulkDeleteMessages(c.Bot, c.ID(), messageIDs, opts...) -} - -func (c *GuildNewsChannel) CrosspostMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - message, err := c.Bot.RestServices.ChannelService().CrosspostMessage(c.ID(), messageID, opts...) - if err != nil { - return nil, err - } - return c.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -func (c *GuildNewsChannel) SendTyping(opts ...rest.RequestOpt) error { - return sendTying(c.Bot, c.ID(), opts...) -} - -func (c *GuildNewsChannel) AddReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return addReaction(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildNewsChannel) RemoveOwnReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return removeOwnReaction(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildNewsChannel) RemoveUserReaction(messageID snowflake.Snowflake, emoji string, userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeUserReaction(c.Bot, c.ID(), messageID, emoji, userID, opts...) -} - -func (c *GuildNewsChannel) RemoveAllReactions(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeAllReactions(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildNewsChannel) RemoveAllReactionsForEmoji(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return removeAllReactionsForEmoji(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildNewsChannel) GetWebhooks(opts ...rest.RequestOpt) ([]Webhook, error) { - return getWebhooks(c.Bot, c.ID(), opts...) -} - -func (c *GuildNewsChannel) CreateWebhook(webhookCreate discord.WebhookCreate, opts ...rest.RequestOpt) (Webhook, error) { - return createWebhook(c.Bot, c.ID(), webhookCreate, opts...) -} - -func (c *GuildNewsChannel) DeleteWebhook(webhookID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deleteWebhook(c.Bot, webhookID, opts...) -} - -func (c *GuildNewsChannel) Threads() []GuildThread { - var threads []GuildThread - c.Bot.Caches.Channels().ForAll(func(channel Channel) { - if thread, ok := channel.(*GuildNewsThread); ok && thread.ParentID() == c.ID() { - threads = append(threads, thread) - } - }) - return threads -} - -func (c *GuildNewsChannel) NewsThreads() []*GuildNewsThread { - var threads []*GuildNewsThread - c.Bot.Caches.Channels().ForAll(func(channel Channel) { - if thread, ok := channel.(*GuildNewsThread); ok && thread.ParentID() == c.ID() { - threads = append(threads, thread) - } - }) - return threads -} - -func (c *GuildNewsChannel) Thread(threadID snowflake.Snowflake) GuildThread { - if thread, ok := c.Bot.Caches.Channels().Get(threadID).(GuildThread); ok { - return thread - } - return nil -} - -func (c *GuildNewsChannel) PrivateThreads() []*GuildPrivateThread { - var threads []*GuildPrivateThread - c.Bot.Caches.Channels().ForAll(func(channel Channel) { - if thread, ok := channel.(*GuildPrivateThread); ok && thread.ParentID() == c.ID() { - threads = append(threads, thread) - } - }) - return threads -} - -func (c *GuildNewsChannel) PublicThreads() []*GuildPublicThread { - var threads []*GuildPublicThread - c.Bot.Caches.Channels().ForAll(func(channel Channel) { - if thread, ok := channel.(*GuildPublicThread); ok && thread.ParentID() == c.ID() { - threads = append(threads, thread) - } - }) - return threads -} - -func (c *GuildNewsChannel) CreateThread(theadCreate discord.ThreadCreate, opts ...rest.RequestOpt) (GuildThread, error) { - return createThread(c.Bot, c.ID(), theadCreate, opts...) -} - -func (c *GuildNewsChannel) CreateThreadWithMessage(messageID snowflake.Snowflake, threadCreateWithMessage discord.ThreadCreateWithMessage, opts ...rest.RequestOpt) (GuildThread, error) { - return createThreadWithMessage(c.Bot, c.ID(), messageID, threadCreateWithMessage, opts...) -} - -func (c *GuildNewsChannel) GetPublicArchivedThreads(before discord.Time, limit int, opts ...rest.RequestOpt) ([]GuildThread, map[snowflake.Snowflake]*ThreadMember, bool, error) { - return getPublicArchivedThreads(c.Bot, c.ID(), before, limit, opts...) -} - -func (c *GuildNewsChannel) Guild() *Guild { - return channelGuild(c.Bot, c.GuildID()) -} - -func (c *GuildNewsChannel) Parent() *GuildCategoryChannel { - if c.ParentID == nil { - return nil - } - return c.Bot.Caches.Channels().Get(*c.ParentID).(*GuildCategoryChannel) -} - -func (c *GuildNewsChannel) Members() []*Member { - return viewMembers(c.Bot, c) -} - -var ( - _ Channel = (*GuildStoreChannel)(nil) - _ GuildChannel = (*GuildStoreChannel)(nil) -) - -type GuildStoreChannel struct { - discord.GuildStoreChannel - Bot *Bot -} - -func (c *GuildStoreChannel) set(channel Channel) Channel { - switch ch := channel.(type) { - case *GuildStoreChannel: - *c = *ch - return c - - default: - return c - } -} - -func (c *GuildStoreChannel) UpdateGuildChannel(guildChannelUpdate discord.GuildChannelUpdate, opts ...rest.RequestOpt) (GuildChannel, error) { - channel, err := updateChannel(c.Bot, c.ID(), guildChannelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(GuildChannel), nil -} - -// Update updates the GuildNewsChannel which can return either a GuildNewsChannel or a GuildTextChannel -func (c *GuildStoreChannel) Update(channelUpdate discord.GuildStoreChannelUpdate, opts ...rest.RequestOpt) (*GuildStoreChannel, error) { - channel, err := c.UpdateGuildChannel(channelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(*GuildStoreChannel), nil -} - -func (c *GuildStoreChannel) Delete(opts ...rest.RequestOpt) error { - return deleteChannel(c.Bot, c.ID(), opts...) -} - -func (c *GuildStoreChannel) PermissionOverwrites() []discord.PermissionOverwrite { - return c.ChannelPermissionOverwrites -} - -func (c *GuildStoreChannel) PermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake) discord.PermissionOverwrite { - return getPermissionOverwrite(c, overwriteType, id) -} - -func (c *GuildStoreChannel) RolePermissionOverwrite(id snowflake.Snowflake) *discord.RolePermissionOverwrite { - return getPermissionOverwrite(c, discord.PermissionOverwriteTypeRole, id).(*discord.RolePermissionOverwrite) -} - -func (c *GuildStoreChannel) MemberPermissionOverwrite(id snowflake.Snowflake) *discord.MemberPermissionOverwrite { - return getPermissionOverwrite(c, discord.PermissionOverwriteTypeMember, id).(*discord.MemberPermissionOverwrite) -} - -func (c *GuildStoreChannel) SetPermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return setPermissionOverwrite(c.Bot, c.ID(), overwriteType, id, allow, deny, opts...) -} - -func (c *GuildStoreChannel) UpdatePermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return updatePermissionOverwrite(c.Bot, c, overwriteType, id, allow, deny, opts...) -} - -func (c *GuildStoreChannel) DeletePermissionOverwrite(id snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deletePermissionOverwrite(c.Bot, c.ID(), id, opts...) -} - -func (c *GuildStoreChannel) Guild() *Guild { - return channelGuild(c.Bot, c.GuildID()) -} - -func (c *GuildStoreChannel) Parent() *GuildCategoryChannel { - if c.ParentID == nil { - return nil - } - return c.Bot.Caches.Channels().Get(*c.ParentID).(*GuildCategoryChannel) -} - -func (c *GuildStoreChannel) Members() []*Member { - return viewMembers(c.Bot, c) -} - -var ( - _ Channel = (*GuildNewsThread)(nil) - _ GuildChannel = (*GuildNewsThread)(nil) - _ MessageChannel = (*GuildNewsThread)(nil) - _ BaseGuildMessageChannel = (*GuildNewsThread)(nil) - _ GuildThread = (*GuildNewsThread)(nil) -) - -type GuildNewsThread struct { - discord.GuildNewsThread - Bot *Bot -} - -func (c *GuildNewsThread) set(channel Channel) Channel { - switch ch := channel.(type) { - case *GuildNewsThread: - *c = *ch - return c - - default: - return c - } -} - -func (c *GuildNewsThread) UpdateGuildChannel(guildChannelUpdate discord.GuildChannelUpdate, opts ...rest.RequestOpt) (GuildChannel, error) { - channel, err := updateChannel(c.Bot, c.ID(), guildChannelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(GuildChannel), nil -} - -func (c *GuildNewsThread) Update(channelUpdate discord.GuildNewsThreadUpdate, opts ...rest.RequestOpt) (*GuildNewsThread, error) { - channel, err := c.UpdateGuildChannel(channelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(*GuildNewsThread), nil -} - -func (c *GuildNewsThread) Delete(opts ...rest.RequestOpt) error { - return deleteChannel(c.Bot, c.ID(), opts...) -} - -func (c *GuildNewsThread) PermissionOverwrites() []discord.PermissionOverwrite { - if parent := c.Parent(); parent != nil { - return parent.PermissionOverwrites() - } - return nil -} - -func (c *GuildNewsThread) PermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake) discord.PermissionOverwrite { - if parent := c.Parent(); parent != nil { - return getPermissionOverwrite(parent, overwriteType, id) - } - return nil -} - -func (c *GuildNewsThread) RolePermissionOverwrite(id snowflake.Snowflake) *discord.RolePermissionOverwrite { - if parent := c.Parent(); parent != nil { - return getPermissionOverwrite(parent, discord.PermissionOverwriteTypeRole, id).(*discord.RolePermissionOverwrite) - } - return nil -} - -func (c *GuildNewsThread) MemberPermissionOverwrite(id snowflake.Snowflake) *discord.MemberPermissionOverwrite { - if parent := c.Parent(); parent != nil { - return getPermissionOverwrite(parent, discord.PermissionOverwriteTypeMember, id).(*discord.MemberPermissionOverwrite) - } - return nil -} - -func (c *GuildNewsThread) SetPermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return setPermissionOverwrite(c.Bot, c.ID(), overwriteType, id, allow, deny, opts...) -} - -func (c *GuildNewsThread) UpdatePermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - if parent := c.Parent(); parent != nil { - return updatePermissionOverwrite(c.Bot, c.Parent(), overwriteType, id, allow, deny, opts...) - } - // TODO return error here - return nil -} - -func (c *GuildNewsThread) DeletePermissionOverwrite(id snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deletePermissionOverwrite(c.Bot, c.ID(), id, opts...) -} - -func (c *GuildNewsThread) GetMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - return getMessage(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildNewsThread) GetMessages(around snowflake.Snowflake, before snowflake.Snowflake, after snowflake.Snowflake, limit int, opts ...rest.RequestOpt) ([]*Message, error) { - return getMessages(c.Bot, c.ID(), around, before, after, limit, opts...) -} - -func (c *GuildNewsThread) CreateMessage(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - return createMessage(c.Bot, c.ID(), messageCreate, opts...) -} - -func (c *GuildNewsThread) UpdateMessage(messageID snowflake.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateMessage(c.Bot, c.ID(), messageID, messageUpdate, opts...) -} - -func (c *GuildNewsThread) DeleteMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deleteMessage(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildNewsThread) BulkDeleteMessages(messageIDs []snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bulkDeleteMessages(c.Bot, c.ID(), messageIDs, opts...) -} - -func (c *GuildNewsThread) SendTyping(opts ...rest.RequestOpt) error { - return sendTying(c.Bot, c.ID(), opts...) -} - -func (c *GuildNewsThread) AddReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return addReaction(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildNewsThread) RemoveOwnReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return removeOwnReaction(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildNewsThread) RemoveUserReaction(messageID snowflake.Snowflake, emoji string, userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeUserReaction(c.Bot, c.ID(), messageID, emoji, userID, opts...) -} - -func (c *GuildNewsThread) RemoveAllReactions(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeAllReactions(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildNewsThread) RemoveAllReactionsForEmoji(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return removeAllReactionsForEmoji(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildNewsThread) Guild() *Guild { - return channelGuild(c.Bot, c.GuildID()) -} - -func (c *GuildNewsThread) ParentMessageChannel() GuildMessageChannel { - return c.Bot.Caches.Channels().Get(c.ParentID()).(GuildMessageChannel) -} - -func (c *GuildNewsThread) Parent() *GuildNewsChannel { - return c.Bot.Caches.Channels().Get(c.ParentID()).(*GuildNewsChannel) -} - -func (c *GuildNewsThread) Members() []*Member { - return c.Bot.Caches.Members().FindAll(func(member *Member) bool { - return member.ChannelPermissions(c).Has(discord.PermissionViewChannel) - }) -} - -func (c *GuildNewsThread) SelfThreadMember() *ThreadMember { - return c.ThreadMember(c.Bot.ApplicationID) -} - -func (c *GuildNewsThread) ThreadMember(userID snowflake.Snowflake) *ThreadMember { - return c.Bot.Caches.ThreadMembers().Get(c.ID(), userID) -} - -func (c *GuildNewsThread) ThreadMembers() []*ThreadMember { - return c.Bot.Caches.ThreadMembers().ThreadAll(c.ID()) -} - -func (c *GuildNewsThread) Join(opts ...rest.RequestOpt) error { - return join(c.Bot, c.ID(), opts...) -} - -func (c *GuildNewsThread) Leave(opts ...rest.RequestOpt) error { - return leave(c.Bot, c.ID(), opts...) -} - -func (c *GuildNewsThread) AddThreadMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return addThreadMember(c.Bot, c.ID(), userID, opts...) -} - -func (c *GuildNewsThread) RemoveThreadMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeThreadMember(c.Bot, c.ID(), userID, opts...) -} - -func (c *GuildNewsThread) GetThreadMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) (*ThreadMember, error) { - return getThreadMember(c.Bot, c.ID(), userID, opts...) -} - -func (c *GuildNewsThread) GetThreadMembers(opts ...rest.RequestOpt) ([]*ThreadMember, error) { - return getThreadMembers(c.Bot, c.ID(), opts...) -} - -var ( - _ Channel = (*GuildPublicThread)(nil) - _ GuildChannel = (*GuildPublicThread)(nil) - _ MessageChannel = (*GuildPublicThread)(nil) - _ BaseGuildMessageChannel = (*GuildPublicThread)(nil) - _ GuildThread = (*GuildPublicThread)(nil) -) - -type GuildPublicThread struct { - discord.GuildPublicThread - Bot *Bot -} - -func (c *GuildPublicThread) set(channel Channel) Channel { - switch ch := channel.(type) { - case *GuildPublicThread: - *c = *ch - return c - - default: - return c - } -} - -func (c *GuildPublicThread) UpdateGuildChannel(guildChannelUpdate discord.GuildChannelUpdate, opts ...rest.RequestOpt) (GuildChannel, error) { - channel, err := updateChannel(c.Bot, c.ID(), guildChannelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(GuildChannel), nil -} - -func (c *GuildPublicThread) Update(channelUpdate discord.GuildNewsThreadUpdate, opts ...rest.RequestOpt) (*GuildPublicThread, error) { - channel, err := c.UpdateGuildChannel(channelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(*GuildPublicThread), nil -} - -func (c *GuildPublicThread) Delete(opts ...rest.RequestOpt) error { - return deleteChannel(c.Bot, c.ID(), opts...) -} - -func (c *GuildPublicThread) PermissionOverwrites() []discord.PermissionOverwrite { - if parent := c.Parent(); parent != nil { - return parent.PermissionOverwrites() - } - return nil -} - -func (c *GuildPublicThread) PermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake) discord.PermissionOverwrite { - if parent := c.Parent(); parent != nil { - return getPermissionOverwrite(parent, overwriteType, id) - } - return nil -} - -func (c *GuildPublicThread) RolePermissionOverwrite(id snowflake.Snowflake) *discord.RolePermissionOverwrite { - if parent := c.Parent(); parent != nil { - return getPermissionOverwrite(parent, discord.PermissionOverwriteTypeRole, id).(*discord.RolePermissionOverwrite) - } - return nil -} - -func (c *GuildPublicThread) MemberPermissionOverwrite(id snowflake.Snowflake) *discord.MemberPermissionOverwrite { - if parent := c.Parent(); parent != nil { - return getPermissionOverwrite(parent, discord.PermissionOverwriteTypeMember, id).(*discord.MemberPermissionOverwrite) - } - return nil -} - -func (c *GuildPublicThread) SetPermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return setPermissionOverwrite(c.Bot, c.ID(), overwriteType, id, allow, deny, opts...) -} - -func (c *GuildPublicThread) UpdatePermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - if parent := c.Parent(); parent != nil { - return updatePermissionOverwrite(c.Bot, c.Parent(), overwriteType, id, allow, deny, opts...) - } - // TODO return error here - return nil -} - -func (c *GuildPublicThread) DeletePermissionOverwrite(id snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deletePermissionOverwrite(c.Bot, c.ID(), id, opts...) -} - -func (c *GuildPublicThread) GetMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - return getMessage(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildPublicThread) GetMessages(around snowflake.Snowflake, before snowflake.Snowflake, after snowflake.Snowflake, limit int, opts ...rest.RequestOpt) ([]*Message, error) { - return getMessages(c.Bot, c.ID(), around, before, after, limit, opts...) -} - -func (c *GuildPublicThread) CreateMessage(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - return createMessage(c.Bot, c.ID(), messageCreate, opts...) -} - -func (c *GuildPublicThread) UpdateMessage(messageID snowflake.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateMessage(c.Bot, c.ID(), messageID, messageUpdate, opts...) -} - -func (c *GuildPublicThread) DeleteMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deleteMessage(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildPublicThread) BulkDeleteMessages(messageIDs []snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bulkDeleteMessages(c.Bot, c.ID(), messageIDs, opts...) -} - -func (c *GuildPublicThread) SendTyping(opts ...rest.RequestOpt) error { - return sendTying(c.Bot, c.ID(), opts...) -} - -func (c *GuildPublicThread) AddReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return addReaction(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildPublicThread) RemoveOwnReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return removeOwnReaction(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildPublicThread) RemoveUserReaction(messageID snowflake.Snowflake, emoji string, userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeUserReaction(c.Bot, c.ID(), messageID, emoji, userID, opts...) -} - -func (c *GuildPublicThread) RemoveAllReactions(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeAllReactions(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildPublicThread) RemoveAllReactionsForEmoji(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return removeAllReactionsForEmoji(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildPublicThread) Guild() *Guild { - return channelGuild(c.Bot, c.GuildID()) -} - -func (c *GuildPublicThread) Parent() *GuildTextChannel { - return c.Bot.Caches.Channels().Get(c.ParentID()).(*GuildTextChannel) -} - -func (c *GuildPublicThread) ParentMessageChannel() GuildMessageChannel { - return c.Bot.Caches.Channels().Get(c.ParentID()).(GuildMessageChannel) -} - -func (c *GuildPublicThread) Members() []*Member { - return c.Bot.Caches.Members().FindAll(func(member *Member) bool { - return member.ChannelPermissions(c).Has(discord.PermissionViewChannel) - }) -} - -func (c *GuildPublicThread) SelfThreadMember() *ThreadMember { - return c.ThreadMember(c.Bot.ApplicationID) -} - -func (c *GuildPublicThread) ThreadMember(userID snowflake.Snowflake) *ThreadMember { - return c.Bot.Caches.ThreadMembers().Get(c.ID(), userID) -} - -func (c *GuildPublicThread) ThreadMembers() []*ThreadMember { - return c.Bot.Caches.ThreadMembers().ThreadAll(c.ID()) -} - -func (c *GuildPublicThread) Join(opts ...rest.RequestOpt) error { - return join(c.Bot, c.ID(), opts...) -} - -func (c *GuildPublicThread) Leave(opts ...rest.RequestOpt) error { - return leave(c.Bot, c.ID(), opts...) -} - -func (c *GuildPublicThread) AddThreadMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return addThreadMember(c.Bot, c.ID(), userID, opts...) -} - -func (c *GuildPublicThread) RemoveThreadMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeThreadMember(c.Bot, c.ID(), userID, opts...) -} - -func (c *GuildPublicThread) GetThreadMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) (*ThreadMember, error) { - return getThreadMember(c.Bot, c.ID(), userID, opts...) -} - -func (c *GuildPublicThread) GetThreadMembers(opts ...rest.RequestOpt) ([]*ThreadMember, error) { - return getThreadMembers(c.Bot, c.ID(), opts...) -} - -var ( - _ Channel = (*GuildPrivateThread)(nil) - _ GuildChannel = (*GuildPrivateThread)(nil) - _ MessageChannel = (*GuildPrivateThread)(nil) - _ BaseGuildMessageChannel = (*GuildPrivateThread)(nil) - _ GuildThread = (*GuildPrivateThread)(nil) -) - -type GuildPrivateThread struct { - discord.GuildPrivateThread - Bot *Bot -} - -func (c *GuildPrivateThread) set(channel Channel) Channel { - switch ch := channel.(type) { - case *GuildPrivateThread: - *c = *ch - return c - - default: - return c - } -} - -func (c *GuildPrivateThread) UpdateGuildChannel(guildChannelUpdate discord.GuildChannelUpdate, opts ...rest.RequestOpt) (GuildChannel, error) { - channel, err := updateChannel(c.Bot, c.ID(), guildChannelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(GuildChannel), nil -} - -func (c *GuildPrivateThread) Update(channelUpdate discord.GuildNewsThreadUpdate, opts ...rest.RequestOpt) (*GuildPrivateThread, error) { - channel, err := c.UpdateGuildChannel(channelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(*GuildPrivateThread), nil -} - -func (c *GuildPrivateThread) Delete(opts ...rest.RequestOpt) error { - return deleteChannel(c.Bot, c.ID(), opts...) -} - -func (c *GuildPrivateThread) PermissionOverwrites() []discord.PermissionOverwrite { - if parent := c.Parent(); parent != nil { - return parent.PermissionOverwrites() - } - return nil -} - -func (c *GuildPrivateThread) PermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake) discord.PermissionOverwrite { - if parent := c.Parent(); parent != nil { - return getPermissionOverwrite(parent, overwriteType, id) - } - return nil -} - -func (c *GuildPrivateThread) RolePermissionOverwrite(id snowflake.Snowflake) *discord.RolePermissionOverwrite { - if parent := c.Parent(); parent != nil { - return getPermissionOverwrite(parent, discord.PermissionOverwriteTypeRole, id).(*discord.RolePermissionOverwrite) - } - return nil -} - -func (c *GuildPrivateThread) MemberPermissionOverwrite(id snowflake.Snowflake) *discord.MemberPermissionOverwrite { - if parent := c.Parent(); parent != nil { - return getPermissionOverwrite(parent, discord.PermissionOverwriteTypeMember, id).(*discord.MemberPermissionOverwrite) - } - return nil -} - -func (c *GuildPrivateThread) SetPermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return setPermissionOverwrite(c.Bot, c.ID(), overwriteType, id, allow, deny, opts...) -} - -func (c *GuildPrivateThread) UpdatePermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - if parent := c.Parent(); parent != nil { - return updatePermissionOverwrite(c.Bot, c.Parent(), overwriteType, id, allow, deny, opts...) - } - // TODO return error here - return nil -} - -func (c *GuildPrivateThread) DeletePermissionOverwrite(id snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deletePermissionOverwrite(c.Bot, c.ID(), id, opts...) -} - -func (c *GuildPrivateThread) GetMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - return getMessage(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildPrivateThread) GetMessages(around snowflake.Snowflake, before snowflake.Snowflake, after snowflake.Snowflake, limit int, opts ...rest.RequestOpt) ([]*Message, error) { - return getMessages(c.Bot, c.ID(), around, before, after, limit, opts...) -} - -func (c *GuildPrivateThread) CreateMessage(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - return createMessage(c.Bot, c.ID(), messageCreate, opts...) -} - -func (c *GuildPrivateThread) UpdateMessage(messageID snowflake.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return updateMessage(c.Bot, c.ID(), messageID, messageUpdate, opts...) -} - -func (c *GuildPrivateThread) DeleteMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deleteMessage(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildPrivateThread) BulkDeleteMessages(messageIDs []snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bulkDeleteMessages(c.Bot, c.ID(), messageIDs, opts...) -} - -func (c *GuildPrivateThread) SendTyping(opts ...rest.RequestOpt) error { - return sendTying(c.Bot, c.ID(), opts...) -} - -func (c *GuildPrivateThread) AddReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return addReaction(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildPrivateThread) RemoveOwnReaction(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return removeOwnReaction(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildPrivateThread) RemoveUserReaction(messageID snowflake.Snowflake, emoji string, userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeUserReaction(c.Bot, c.ID(), messageID, emoji, userID, opts...) -} - -func (c *GuildPrivateThread) RemoveAllReactions(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeAllReactions(c.Bot, c.ID(), messageID, opts...) -} - -func (c *GuildPrivateThread) RemoveAllReactionsForEmoji(messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return removeAllReactionsForEmoji(c.Bot, c.ID(), messageID, emoji, opts...) -} - -func (c *GuildPrivateThread) Guild() *Guild { - return channelGuild(c.Bot, c.GuildID()) -} - -func (c *GuildPrivateThread) Parent() *GuildTextChannel { - return c.Bot.Caches.Channels().Get(c.ParentID()).(*GuildTextChannel) -} - -func (c *GuildPrivateThread) ParentMessageChannel() GuildMessageChannel { - return c.Bot.Caches.Channels().Get(c.ParentID()).(GuildMessageChannel) -} - -func (c *GuildPrivateThread) Members() []*Member { - return c.Bot.Caches.Members().FindAll(func(member *Member) bool { - return member.ChannelPermissions(c).Has(discord.PermissionViewChannel) - }) -} - -func (c *GuildPrivateThread) SelfThreadMember() *ThreadMember { - return c.ThreadMember(c.Bot.ApplicationID) -} - -func (c *GuildPrivateThread) ThreadMember(userID snowflake.Snowflake) *ThreadMember { - return c.Bot.Caches.ThreadMembers().Get(c.ID(), userID) -} - -func (c *GuildPrivateThread) ThreadMembers() []*ThreadMember { - return c.Bot.Caches.ThreadMembers().ThreadAll(c.ID()) -} - -func (c *GuildPrivateThread) Join(opts ...rest.RequestOpt) error { - return join(c.Bot, c.ID(), opts...) -} - -func (c *GuildPrivateThread) Leave(opts ...rest.RequestOpt) error { - return leave(c.Bot, c.ID(), opts...) -} - -func (c *GuildPrivateThread) AddThreadMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return addThreadMember(c.Bot, c.ID(), userID, opts...) -} - -func (c *GuildPrivateThread) RemoveThreadMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return removeThreadMember(c.Bot, c.ID(), userID, opts...) -} - -func (c *GuildPrivateThread) GetThreadMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) (*ThreadMember, error) { - return getThreadMember(c.Bot, c.ID(), userID, opts...) -} - -func (c *GuildPrivateThread) GetThreadMembers(opts ...rest.RequestOpt) ([]*ThreadMember, error) { - return getThreadMembers(c.Bot, c.ID(), opts...) -} - -var ( - _ Channel = (*GuildStageVoiceChannel)(nil) - _ GuildChannel = (*GuildStageVoiceChannel)(nil) - _ GuildAudioChannel = (*GuildStageVoiceChannel)(nil) -) - -type GuildStageVoiceChannel struct { - discord.GuildStageVoiceChannel - Bot *Bot - StageInstanceID *snowflake.Snowflake - ConnectedMemberIDs map[snowflake.Snowflake]struct{} -} - -func (c *GuildStageVoiceChannel) set(channel Channel) Channel { - switch ch := channel.(type) { - case *GuildStageVoiceChannel: - *c = *ch - return c - - default: - return c - } -} - -func (c *GuildStageVoiceChannel) UpdateGuildChannel(guildChannelUpdate discord.GuildChannelUpdate, opts ...rest.RequestOpt) (GuildChannel, error) { - channel, err := updateChannel(c.Bot, c.ID(), guildChannelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(GuildChannel), nil -} - -// Update updates the GuildNewsChannel which can return either a GuildNewsChannel or a GuildTextChannel -func (c *GuildStageVoiceChannel) Update(channelUpdate discord.GuildStageVoiceChannelUpdate, opts ...rest.RequestOpt) (*GuildStageVoiceChannel, error) { - channel, err := c.UpdateGuildChannel(channelUpdate, opts...) - if err != nil { - return nil, err - } - return channel.(*GuildStageVoiceChannel), nil -} - -func (c *GuildStageVoiceChannel) Delete(opts ...rest.RequestOpt) error { - return deleteChannel(c.Bot, c.ID(), opts...) -} - -func (c *GuildStageVoiceChannel) PermissionOverwrites() []discord.PermissionOverwrite { - return c.ChannelPermissionOverwrites -} - -func (c *GuildStageVoiceChannel) PermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake) discord.PermissionOverwrite { - return getPermissionOverwrite(c, overwriteType, id) -} - -func (c *GuildStageVoiceChannel) RolePermissionOverwrite(id snowflake.Snowflake) *discord.RolePermissionOverwrite { - return getPermissionOverwrite(c, discord.PermissionOverwriteTypeRole, id).(*discord.RolePermissionOverwrite) -} - -func (c *GuildStageVoiceChannel) MemberPermissionOverwrite(id snowflake.Snowflake) *discord.MemberPermissionOverwrite { - return getPermissionOverwrite(c, discord.PermissionOverwriteTypeMember, id).(*discord.MemberPermissionOverwrite) -} - -func (c *GuildStageVoiceChannel) SetPermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return setPermissionOverwrite(c.Bot, c.ID(), overwriteType, id, allow, deny, opts...) -} - -func (c *GuildStageVoiceChannel) UpdatePermissionOverwrite(overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - return updatePermissionOverwrite(c.Bot, c, overwriteType, id, allow, deny, opts...) -} - -func (c *GuildStageVoiceChannel) DeletePermissionOverwrite(id snowflake.Snowflake, opts ...rest.RequestOpt) error { - return deletePermissionOverwrite(c.Bot, c.ID(), id, opts...) -} - -func (c *GuildStageVoiceChannel) Guild() *Guild { - return channelGuild(c.Bot, c.GuildID()) -} - -func (c *GuildStageVoiceChannel) Parent() *GuildCategoryChannel { - if c.ParentID == nil { - return nil - } - return c.Bot.Caches.Channels().Get(*c.ParentID).(*GuildCategoryChannel) -} - -func (c *GuildStageVoiceChannel) Connect(ctx context.Context) error { - return c.Bot.AudioController.Connect(ctx, c.GuildID(), c.ID()) -} - -func (c *GuildStageVoiceChannel) Members() []*Member { - return connectedMembers(c.Bot, c) -} - -func (c *GuildStageVoiceChannel) connectedMembers() map[snowflake.Snowflake]struct{} { - return c.ConnectedMemberIDs -} - -func (c *GuildStageVoiceChannel) IsModerator(member *Member) bool { - return member.Permissions().Has(discord.PermissionsStageModerator) -} - -func (c *GuildStageVoiceChannel) StageInstance() *StageInstance { - if c.StageInstanceID == nil { - return nil - } - return c.Bot.Caches.StageInstances().Get(*c.StageInstanceID) -} - -func (c *GuildStageVoiceChannel) CreateStageInstance(stageInstanceCreate discord.StageInstanceCreate, opts ...rest.RequestOpt) (*StageInstance, error) { - stageInstance, err := c.Bot.RestServices.StageInstanceService().CreateStageInstance(stageInstanceCreate, opts...) - if err != nil { - return nil, err - } - return c.Bot.EntityBuilder.CreateStageInstance(*stageInstance, CacheStrategyNoWs), nil -} - -func (c *GuildStageVoiceChannel) UpdateStageInstance(stageInstanceUpdate discord.StageInstanceUpdate, opts ...rest.RequestOpt) (*StageInstance, error) { - stageInstance, err := c.Bot.RestServices.StageInstanceService().UpdateStageInstance(c.ID(), stageInstanceUpdate, opts...) - if err != nil { - return nil, err - } - return c.Bot.EntityBuilder.CreateStageInstance(*stageInstance, CacheStrategyNoWs), nil -} - -func (c *GuildStageVoiceChannel) DeleteStageInstance(opts ...rest.RequestOpt) error { - return c.Bot.RestServices.StageInstanceService().DeleteStageInstance(c.ID(), opts...) -} - -//-------------------------------------------- - -func getPermissionOverwrite(channel GuildChannel, overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake) discord.PermissionOverwrite { - for _, overwrite := range channel.PermissionOverwrites() { - if overwrite.Type() == overwriteType && overwrite.ID() == id { - return overwrite - } - } - return nil -} - -func setPermissionOverwrite(bot *Bot, channelID snowflake.Snowflake, overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - var overwrite discord.PermissionOverwrite - switch overwriteType { - case discord.PermissionOverwriteTypeRole: - overwrite = discord.RolePermissionOverwrite{ - RoleID: id, - Allow: allow, - Deny: deny, - } - - case discord.PermissionOverwriteTypeMember: - overwrite = discord.MemberPermissionOverwrite{ - UserID: id, - Allow: allow, - Deny: deny, - } - - default: - return errors.New("unknown permission overwrite type") - } - return bot.RestServices.ChannelService().UpdatePermissionOverwrite(channelID, id, overwrite, opts...) -} - -func updatePermissionOverwrite(bot *Bot, channel GuildChannel, overwriteType discord.PermissionOverwriteType, id snowflake.Snowflake, allow discord.Permissions, deny discord.Permissions, opts ...rest.RequestOpt) error { - var overwriteUpdate discord.PermissionOverwriteUpdate - overwrite := getPermissionOverwrite(channel, overwriteType, id) - switch overwriteType { - case discord.PermissionOverwriteTypeRole: - if overwrite != nil { - o := overwrite.(discord.RolePermissionOverwrite) - allow = o.Allow.Add(allow) - deny = o.Deny.Add(deny) - } - overwriteUpdate = discord.RolePermissionOverwriteUpdate{ - Allow: allow, - Deny: deny, - } - - case discord.PermissionOverwriteTypeMember: - if overwrite != nil { - o := overwrite.(discord.MemberPermissionOverwrite) - allow = o.Allow.Add(allow) - deny = o.Deny.Add(deny) - } - overwriteUpdate = discord.MemberPermissionOverwriteUpdate{ - Allow: allow, - Deny: deny, - } - - default: - return errors.New("unknown permission overwrite type") - } - - return bot.RestServices.ChannelService().UpdatePermissionOverwrite(channel.ID(), id, overwriteUpdate, opts...) -} - -func deletePermissionOverwrite(bot *Bot, channelID snowflake.Snowflake, id snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bot.RestServices.ChannelService().DeletePermissionOverwrite(channelID, id, opts...) -} - -func channelGuild(bot *Bot, guildID snowflake.Snowflake) *Guild { - return bot.Caches.Guilds().Get(guildID) -} - -func createThread(bot *Bot, channelID snowflake.Snowflake, threadCreate discord.ThreadCreate, opts ...rest.RequestOpt) (GuildThread, error) { - channel, err := bot.RestServices.ThreadService().CreateThread(channelID, threadCreate, opts...) - if err != nil { - return nil, err - } - return bot.EntityBuilder.CreateChannel(channel, CacheStrategyNo).(GuildThread), nil -} - -func createThreadWithMessage(bot *Bot, channelID snowflake.Snowflake, messageID snowflake.Snowflake, threadCreateWithMessage discord.ThreadCreateWithMessage, opts ...rest.RequestOpt) (GuildThread, error) { - channel, err := bot.RestServices.ThreadService().CreateThreadWithMessage(channelID, messageID, threadCreateWithMessage, opts...) - if err != nil { - return nil, err - } - return bot.EntityBuilder.CreateChannel(channel, CacheStrategyNo).(GuildThread), nil -} - -func join(bot *Bot, threadID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bot.RestServices.ThreadService().JoinThread(threadID, opts...) -} - -func leave(bot *Bot, threadID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bot.RestServices.ThreadService().LeaveThread(threadID, opts...) -} - -func addThreadMember(bot *Bot, threadID snowflake.Snowflake, userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bot.RestServices.ThreadService().AddThreadMember(threadID, userID, opts...) -} - -func removeThreadMember(bot *Bot, threadID snowflake.Snowflake, userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bot.RestServices.ThreadService().RemoveThreadMember(threadID, userID, opts...) -} - -func getThreadMember(bot *Bot, threadID snowflake.Snowflake, userID snowflake.Snowflake, opts ...rest.RequestOpt) (*ThreadMember, error) { - threadMember, err := bot.RestServices.ThreadService().GetThreadMember(threadID, userID, opts...) - if err != nil { - return nil, err - } - return bot.EntityBuilder.CreateThreadMember(*threadMember, CacheStrategyNo), nil -} - -func getThreadMembers(bot *Bot, threadID snowflake.Snowflake, opts ...rest.RequestOpt) ([]*ThreadMember, error) { - members, err := bot.RestServices.ThreadService().GetThreadMembers(threadID, opts...) - if err != nil { - return nil, err - } - threadMembers := make([]*ThreadMember, len(members)) - for i := range members { - threadMembers[i] = bot.EntityBuilder.CreateThreadMember(members[i], CacheStrategyNo) - } - return threadMembers, nil -} - -func getPublicArchivedThreads(bot *Bot, channelID snowflake.Snowflake, before discord.Time, limit int, opts ...rest.RequestOpt) ([]GuildThread, map[snowflake.Snowflake]*ThreadMember, bool, error) { - getThreads, err := bot.RestServices.ThreadService().GetPublicArchivedThreads(channelID, before, limit, opts...) - if err != nil { - return nil, nil, false, err - } - - threads := make([]GuildThread, len(getThreads.Threads)) - for i := range getThreads.Threads { - threads[i] = bot.EntityBuilder.CreateChannel(getThreads.Threads[i], CacheStrategyNo).(GuildThread) - } - - return threads, createThreadMembers(bot, getThreads.Members), getThreads.HasMore, nil -} - -func createMessage(bot *Bot, channelID snowflake.Snowflake, messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - message, err := bot.RestServices.ChannelService().CreateMessage(channelID, messageCreate, opts...) - if err != nil { - return nil, err - } - return bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -func updateMessage(bot *Bot, channelID snowflake.Snowflake, messageID snowflake.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - message, err := bot.RestServices.ChannelService().UpdateMessage(channelID, messageID, messageUpdate, opts...) - if err != nil { - return nil, err - } - return bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -func deleteMessage(bot *Bot, channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bot.RestServices.ChannelService().DeleteMessage(channelID, messageID, opts...) -} - -func bulkDeleteMessages(bot *Bot, channelID snowflake.Snowflake, messageIDs []snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bot.RestServices.ChannelService().BulkDeleteMessages(channelID, messageIDs, opts...) -} - -func sendTying(bot *Bot, channelID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bot.RestServices.ChannelService().SendTyping(channelID, opts...) -} - -func getMessage(bot *Bot, channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - message, err := bot.RestServices.ChannelService().GetMessage(channelID, messageID, opts...) - if err != nil { - return nil, err - } - return bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -func getMessages(bot *Bot, channelID snowflake.Snowflake, around snowflake.Snowflake, before snowflake.Snowflake, after snowflake.Snowflake, limit int, opts ...rest.RequestOpt) ([]*Message, error) { - messages, err := bot.RestServices.ChannelService().GetMessages(channelID, around, before, after, limit, opts...) - if err != nil { - return nil, err - } - coreMessages := make([]*Message, len(messages)) - for i, message := range messages { - coreMessages[i] = bot.EntityBuilder.CreateMessage(message, CacheStrategyNoWs) - } - return coreMessages, nil -} - -func updateChannel(bot *Bot, channelID snowflake.Snowflake, channelUpdate discord.ChannelUpdate, opts ...rest.RequestOpt) (Channel, error) { - channel, err := bot.RestServices.ChannelService().UpdateChannel(channelID, channelUpdate, opts...) - if err != nil { - return nil, err - } - return bot.EntityBuilder.CreateChannel(channel, CacheStrategyNoWs), nil -} - -func deleteChannel(bot *Bot, channelID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bot.RestServices.ChannelService().DeleteChannel(channelID, opts...) -} - -func addReaction(bot *Bot, channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return bot.RestServices.ChannelService().AddReaction(channelID, messageID, emoji, opts...) -} - -func removeOwnReaction(bot *Bot, channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return bot.RestServices.ChannelService().RemoveOwnReaction(channelID, messageID, emoji, opts...) -} - -func removeUserReaction(bot *Bot, channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bot.RestServices.ChannelService().RemoveUserReaction(channelID, messageID, emoji, userID, opts...) -} - -func removeAllReactions(bot *Bot, channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bot.RestServices.ChannelService().RemoveAllReactions(channelID, messageID, opts...) -} - -func removeAllReactionsForEmoji(bot *Bot, channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, opts ...rest.RequestOpt) error { - return bot.RestServices.ChannelService().RemoveAllReactionsForEmoji(channelID, messageID, emoji, opts...) -} - -func getWebhooks(bot *Bot, channelID snowflake.Snowflake, opts ...rest.RequestOpt) ([]Webhook, error) { - webhooks, err := bot.RestServices.ChannelService().GetWebhooks(channelID, opts...) - if err != nil { - return nil, err - } - coreWebhooks := make([]Webhook, len(webhooks)) - for i := range webhooks { - coreWebhooks[i] = bot.EntityBuilder.CreateWebhook(webhooks[i], CacheStrategyNoWs) - } - return coreWebhooks, nil -} - -func createWebhook(bot *Bot, channelID snowflake.Snowflake, webhookCreate discord.WebhookCreate, opts ...rest.RequestOpt) (Webhook, error) { - webhook, err := bot.RestServices.ChannelService().CreateWebhook(channelID, webhookCreate, opts...) - if err != nil { - return nil, err - } - return bot.EntityBuilder.CreateWebhook(webhook, CacheStrategyNoWs), nil -} - -func deleteWebhook(bot *Bot, webhookID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return bot.RestServices.WebhookService().DeleteWebhook(webhookID, opts...) -} - -func viewMembers(bot *Bot, guildChannel GuildChannel) []*Member { - return bot.Caches.Members().FindAll(func(member *Member) bool { - return member.ChannelPermissions(guildChannel).Has(discord.PermissionViewChannel) - }) -} - -func connectedMembers(bot *Bot, audioChannel GuildAudioChannel) []*Member { - return bot.Caches.Members().FindAll(func(member *Member) bool { - _, ok := audioChannel.connectedMembers()[member.User.ID] - return ok - }) -} - -func LastPinTimestamp(channel MessageChannel) *discord.Time { - if channel == nil { - return nil - } - switch ch := channel.(type) { - case *GuildTextChannel: - return ch.LastPinTimestamp - - case *DMChannel: - return ch.LastPinTimestamp - - case *GuildNewsChannel: - return ch.LastPinTimestamp - - case *GuildNewsThread: - return ch.LastPinTimestamp - - case *GuildPrivateThread: - return ch.LastPinTimestamp - - case *GuildPublicThread: - return ch.LastPinTimestamp - - default: - panic("unknown channel type") - } -} diff --git a/core/collectors.go b/core/collectors.go deleted file mode 100644 index 7b5f1aee..00000000 --- a/core/collectors.go +++ /dev/null @@ -1,60 +0,0 @@ -package core - -var _ Collectors = (*collectorsImpl)(nil) - -type Collectors interface { - NewMessageCollector(filter MessageFilter) (<-chan *Message, func()) - NewMessageReactionAddCollector(filter MessageReactionAddFilter) (<-chan *MessageReactionAdd, func()) - NewMessageReactionRemoveCollector(filter MessageReactionRemoveFilter) (<-chan *MessageReactionRemove, func()) - NewInteractionCollector(filter InteractionFilter) (<-chan Interaction, func()) - NewApplicationCommandInteractionCollector(filter ApplicationCommandInteractionFilter) (<-chan *ApplicationCommandInteraction, func()) - NewComponentInteractionCollector(filter ComponentInteractionFilter) (<-chan *ComponentInteraction, func()) - NewAutocompleteCollector(filter AutocompleteInteractionFilter) (<-chan *AutocompleteInteraction, func()) -} - -func NewCollectors(bot *Bot, config CollectorsConfig) Collectors { - return &collectorsImpl{Bot: bot, CollectorsConfig: config} -} - -type CollectorsConfig struct { - NewMessageCollectorFunc func(bot *Bot, filter MessageFilter) (<-chan *Message, func()) - NewMessageReactionAddCollectorFunc func(bot *Bot, filter MessageReactionAddFilter) (<-chan *MessageReactionAdd, func()) - NewMessageReactionRemoveCollectorFunc func(bot *Bot, filter MessageReactionRemoveFilter) (<-chan *MessageReactionRemove, func()) - NewInteractionCollectorFunc func(bot *Bot, filter InteractionFilter) (<-chan Interaction, func()) - NewApplicationCommandInteractionCollectorFunc func(bot *Bot, filter ApplicationCommandInteractionFilter) (<-chan *ApplicationCommandInteraction, func()) - NewComponentInteractionCollectorFunc func(bot *Bot, filter ComponentInteractionFilter) (<-chan *ComponentInteraction, func()) - NewAutocompleteCollectorFunc func(bot *Bot, filter AutocompleteInteractionFilter) (<-chan *AutocompleteInteraction, func()) -} - -type collectorsImpl struct { - Bot *Bot - CollectorsConfig -} - -func (c *collectorsImpl) NewMessageCollector(filter MessageFilter) (<-chan *Message, func()) { - return c.NewMessageCollectorFunc(c.Bot, filter) -} - -func (c *collectorsImpl) NewMessageReactionAddCollector(filter MessageReactionAddFilter) (<-chan *MessageReactionAdd, func()) { - return c.NewMessageReactionAddCollectorFunc(c.Bot, filter) -} - -func (c *collectorsImpl) NewMessageReactionRemoveCollector(filter MessageReactionRemoveFilter) (<-chan *MessageReactionRemove, func()) { - return c.NewMessageReactionRemoveCollectorFunc(c.Bot, filter) -} - -func (c *collectorsImpl) NewInteractionCollector(filter InteractionFilter) (<-chan Interaction, func()) { - return c.NewInteractionCollectorFunc(c.Bot, filter) -} - -func (c *collectorsImpl) NewApplicationCommandInteractionCollector(filter ApplicationCommandInteractionFilter) (<-chan *ApplicationCommandInteraction, func()) { - return c.NewApplicationCommandInteractionCollectorFunc(c.Bot, filter) -} - -func (c *collectorsImpl) NewComponentInteractionCollector(filter ComponentInteractionFilter) (<-chan *ComponentInteraction, func()) { - return c.NewComponentInteractionCollectorFunc(c.Bot, filter) -} - -func (c *collectorsImpl) NewAutocompleteCollector(filter AutocompleteInteractionFilter) (<-chan *AutocompleteInteraction, func()) { - return c.NewAutocompleteCollectorFunc(c.Bot, filter) -} diff --git a/core/collectors/application_command_interaction_collector.go b/core/collectors/application_command_interaction_collector.go deleted file mode 100644 index c8ed5c00..00000000 --- a/core/collectors/application_command_interaction_collector.go +++ /dev/null @@ -1,42 +0,0 @@ -package collectors - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" -) - -// NewApplicationCommandInteractionCollector gives you a channel to receive on and a function to close the collector -//goland:noinspection GoUnusedExportedFunction -func NewApplicationCommandInteractionCollector(disgo *core.Bot, filter core.ApplicationCommandInteractionFilter) (<-chan *core.ApplicationCommandInteraction, func()) { - ch := make(chan *core.ApplicationCommandInteraction) - - col := &ApplicationCommandInteractionCollector{ - Filter: filter, - Chan: ch, - } - cls := func() { - close(ch) - disgo.EventManager.RemoveEventListeners(col) - } - col.Close = cls - disgo.EventManager.AddEventListeners(col) - - return ch, cls -} - -// ApplicationCommandInteractionCollector used to collect core.ApplicationCommandInteractionApplicationCommandInteraction(s) from a core.Message using a ButtonFilter function -type ApplicationCommandInteractionCollector struct { - Filter core.ApplicationCommandInteractionFilter - Chan chan<- *core.ApplicationCommandInteraction - Close func() -} - -// OnEvent used to get events for the ButtonCollector -func (c *ApplicationCommandInteractionCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.ApplicationCommandInteractionEvent); ok { - if !c.Filter(event.ApplicationCommandInteraction) { - return - } - c.Chan <- event.ApplicationCommandInteraction - } -} diff --git a/core/collectors/autocomplete_interaction_collector.go b/core/collectors/autocomplete_interaction_collector.go deleted file mode 100644 index 5f46cacb..00000000 --- a/core/collectors/autocomplete_interaction_collector.go +++ /dev/null @@ -1,42 +0,0 @@ -package collectors - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" -) - -// NewAutocompleteInteractionCollector gives you a channel to receive on and a function to close the collector -//goland:noinspection GoUnusedExportedFunction -func NewAutocompleteInteractionCollector(disgo *core.Bot, filter core.AutocompleteInteractionFilter) (<-chan *core.AutocompleteInteraction, func()) { - ch := make(chan *core.AutocompleteInteraction) - - col := &AutocompleteInteractionCollector{ - Filter: filter, - Chan: ch, - } - cls := func() { - close(ch) - disgo.EventManager.RemoveEventListeners(col) - } - col.Close = cls - disgo.EventManager.AddEventListeners(col) - - return ch, cls -} - -// AutocompleteInteractionCollector used to collect core.AutocompleteInteraction(s) from a core.Message using a ButtonFilter function -type AutocompleteInteractionCollector struct { - Filter core.AutocompleteInteractionFilter - Chan chan<- *core.AutocompleteInteraction - Close func() -} - -// OnEvent used to get events for the ButtonCollector -func (c *AutocompleteInteractionCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.AutocompleteInteractionEvent); ok { - if !c.Filter(event.AutocompleteInteraction) { - return - } - c.Chan <- event.AutocompleteInteraction - } -} diff --git a/core/collectors/component_interaction_collector.go b/core/collectors/component_interaction_collector.go deleted file mode 100644 index e5455895..00000000 --- a/core/collectors/component_interaction_collector.go +++ /dev/null @@ -1,42 +0,0 @@ -package collectors - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" -) - -// NewComponentInteractionCollector gives you a channel to receive on and a function to close the collector -//goland:noinspection GoUnusedExportedFunction -func NewComponentInteractionCollector(disgo *core.Bot, filter core.ComponentInteractionFilter) (<-chan *core.ComponentInteraction, func()) { - ch := make(chan *core.ComponentInteraction) - - col := &ComponentInteractionCollector{ - Filter: filter, - Chan: ch, - } - cls := func() { - close(ch) - disgo.EventManager.RemoveEventListeners(col) - } - col.Close = cls - disgo.EventManager.AddEventListeners(col) - - return ch, cls -} - -// ComponentInteractionCollector used to collect core.ComponentInteractionComponentInteraction(s) from a core.Message using a ButtonFilter function -type ComponentInteractionCollector struct { - Filter core.ComponentInteractionFilter - Chan chan<- *core.ComponentInteraction - Close func() -} - -// OnEvent used to get events for the ButtonCollector -func (c *ComponentInteractionCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.ComponentInteractionEvent); ok { - if !c.Filter(event.ComponentInteraction) { - return - } - c.Chan <- event.ComponentInteraction - } -} diff --git a/core/collectors/config.go b/core/collectors/config.go deleted file mode 100644 index 3283b33d..00000000 --- a/core/collectors/config.go +++ /dev/null @@ -1,13 +0,0 @@ -package collectors - -import "github.com/DisgoOrg/disgo/core" - -var DefaultConfig = core.CollectorsConfig{ - NewMessageCollectorFunc: NewMessageCollector, - NewMessageReactionAddCollectorFunc: NewMessageReactionAddCollector, - NewMessageReactionRemoveCollectorFunc: NewMessageReactionRemoveCollector, - NewInteractionCollectorFunc: NewInteractionCollector, - NewApplicationCommandInteractionCollectorFunc: NewApplicationCommandInteractionCollector, - NewComponentInteractionCollectorFunc: NewComponentInteractionCollector, - NewAutocompleteCollectorFunc: NewAutocompleteInteractionCollector, -} diff --git a/core/collectors/interaction_create_collector.go b/core/collectors/interaction_create_collector.go deleted file mode 100644 index dd703397..00000000 --- a/core/collectors/interaction_create_collector.go +++ /dev/null @@ -1,42 +0,0 @@ -package collectors - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" -) - -// NewInteractionCollector gives you a channel to receive on and a function to close the collector -//goland:noinspection GoUnusedExportedFunction -func NewInteractionCollector(disgo *core.Bot, filter core.InteractionFilter) (<-chan core.Interaction, func()) { - ch := make(chan core.Interaction) - - col := &InteractionCollector{ - Filter: filter, - Chan: ch, - } - cls := func() { - close(ch) - disgo.EventManager.RemoveEventListeners(col) - } - col.Close = cls - disgo.EventManager.AddEventListeners(col) - - return ch, cls -} - -// InteractionCollector used to collect core.InteractionInteraction(s) from a core.Message using a ButtonFilter function -type InteractionCollector struct { - Filter core.InteractionFilter - Chan chan<- core.Interaction - Close func() -} - -// OnEvent used to get events for the ButtonCollector -func (c *InteractionCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.InteractionEvent); ok { - if !c.Filter(event.Interaction) { - return - } - c.Chan <- event.Interaction - } -} diff --git a/core/collectors/message_collector.go b/core/collectors/message_collector.go deleted file mode 100644 index 7daed6c4..00000000 --- a/core/collectors/message_collector.go +++ /dev/null @@ -1,41 +0,0 @@ -package collectors - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" -) - -// NewMessageCollector gives you a channel to receive on and a function to close the collector -func NewMessageCollector(disgo *core.Bot, filter core.MessageFilter) (<-chan *core.Message, func()) { - ch := make(chan *core.Message) - - collector := &MessageCollector{ - Filter: filter, - Chan: ch, - } - cls := func() { - close(ch) - disgo.EventManager.RemoveEventListeners(collector) - } - collector.Close = cls - disgo.EventManager.AddEventListeners(collector) - - return ch, cls -} - -// MessageCollector collects Message(s) using a MessageFilter function -type MessageCollector struct { - Filter core.MessageFilter - Chan chan<- *core.Message - Close func() -} - -// OnEvent used to get events for the MessageCollector -func (c *MessageCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.MessageCreateEvent); ok { - if !c.Filter(event.Message) { - return - } - c.Chan <- event.Message - } -} diff --git a/core/collectors/reaction_add_collector.go b/core/collectors/reaction_add_collector.go deleted file mode 100644 index 6c5b842b..00000000 --- a/core/collectors/reaction_add_collector.go +++ /dev/null @@ -1,49 +0,0 @@ -package collectors - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" -) - -// NewMessageReactionAddCollector gives you a channel to receive on and a function to close the collector -func NewMessageReactionAddCollector(disgo *core.Bot, filter core.MessageReactionAddFilter) (<-chan *core.MessageReactionAdd, func()) { - ch := make(chan *core.MessageReactionAdd) - - col := &MessageReactionAddCollector{ - Filter: filter, - Chan: ch, - } - cls := func() { - close(ch) - disgo.EventManager.RemoveEventListeners(col) - } - col.Close = cls - disgo.EventManager.AddEventListeners(col) - - return ch, cls -} - -// MessageReactionAddCollector used to collect discord.MessageReaction(s) from a core.Message using an events.MessageReactionAddFilter function -type MessageReactionAddCollector struct { - Filter core.MessageReactionAddFilter - Chan chan *core.MessageReactionAdd - Close func() -} - -// OnEvent used to get events for the ReactionCollector -func (c *MessageReactionAddCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.MessageReactionAddEvent); ok { - messageReactionAdd := &core.MessageReactionAdd{ - UserID: event.UserID, - ChannelID: event.ChannelID, - MessageID: event.MessageID, - GuildID: event.GuildID, - Member: event.Member, - Emoji: event.Emoji, - } - if !c.Filter(messageReactionAdd) { - return - } - c.Chan <- messageReactionAdd - } -} diff --git a/core/collectors/reaction_remove_collector.go b/core/collectors/reaction_remove_collector.go deleted file mode 100644 index 2c58b0f8..00000000 --- a/core/collectors/reaction_remove_collector.go +++ /dev/null @@ -1,48 +0,0 @@ -package collectors - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" -) - -// NewMessageReactionRemoveCollector gives you a channel to receive on and a function to close the collector -func NewMessageReactionRemoveCollector(disgo *core.Bot, filter core.MessageReactionRemoveFilter) (<-chan *core.MessageReactionRemove, func()) { - ch := make(chan *core.MessageReactionRemove) - - col := &MessageReactionRemoveCollector{ - Filter: filter, - Chan: ch, - } - cls := func() { - close(ch) - disgo.EventManager.RemoveEventListeners(col) - } - col.Close = cls - disgo.EventManager.RemoveEventListeners(col) - - return ch, cls -} - -// MessageReactionRemoveCollector used to collect discord.MessageReaction(s) from a core.Message using an events.MessageReactionRemoveFilter function -type MessageReactionRemoveCollector struct { - Filter core.MessageReactionRemoveFilter - Chan chan *core.MessageReactionRemove - Close func() -} - -// OnEvent used to get events for the ReactionCollector -func (c *MessageReactionRemoveCollector) OnEvent(e core.Event) { - if event, ok := e.(*events.MessageReactionRemoveEvent); ok { - messageReactionRemove := &core.MessageReactionRemove{ - UserID: event.UserID, - ChannelID: event.ChannelID, - MessageID: event.MessageID, - GuildID: event.GuildID, - Emoji: event.Emoji, - } - if !c.Filter(messageReactionRemove) { - return - } - c.Chan <- messageReactionRemove - } -} diff --git a/core/component_interaction.go b/core/component_interaction.go deleted file mode 100644 index fe7f53fb..00000000 --- a/core/component_interaction.go +++ /dev/null @@ -1,103 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" -) - -type ComponentInteractionFilter func(interaction *ComponentInteraction) bool - -var _ Interaction = (*ComponentInteraction)(nil) - -// ComponentInteraction represents a generic ComponentInteraction received from discord -type ComponentInteraction struct { - CreateInteraction - Data ComponentInteractionData - Message *Message -} - -func (i ComponentInteraction) interaction() {} -func (i ComponentInteraction) Type() discord.InteractionType { - return discord.InteractionTypeComponent -} - -func (i ComponentInteraction) ButtonInteractionData() ButtonInteractionData { - return i.Data.(ButtonInteractionData) -} - -func (i ComponentInteraction) SelectMenuInteractionData() SelectMenuInteractionData { - return i.Data.(SelectMenuInteractionData) -} - -func (i ComponentInteraction) UpdateMessage(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) error { - return i.Respond(discord.InteractionCallbackTypeUpdateMessage, messageUpdate, opts...) -} - -func (i ComponentInteraction) DeferUpdateMessage(opts ...rest.RequestOpt) error { - return i.Respond(discord.InteractionCallbackTypeDeferredUpdateMessage, nil, opts...) -} - -func (i ComponentInteraction) UpdateComponent(customID discord.CustomID, component discord.InteractiveComponent, opts ...rest.RequestOpt) error { - containerComponents := make([]discord.ContainerComponent, len(i.Message.Components)) - for ii := range i.Message.Components { - switch container := containerComponents[ii].(type) { - case discord.ActionRowComponent: - containerComponents[ii] = container.UpdateComponent(customID, component) - - default: - containerComponents[ii] = container - continue - } - } - - return i.UpdateMessage(discord.NewMessageUpdateBuilder().SetContainerComponents(containerComponents...).Build(), opts...) -} - -func (i ComponentInteraction) CreateModal(modalCreate discord.ModalCreate, opts ...rest.RequestOpt) error { - return i.Respond(discord.InteractionCallbackTypeModal, modalCreate, opts...) -} - -type ComponentInteractionData interface { - discord.ComponentInteractionData -} - -type ButtonInteractionData struct { - discord.ButtonInteractionData - interaction *ComponentInteraction -} - -// UpdateButton updates the clicked ButtonComponent with a new ButtonComponent -func (d *ButtonInteractionData) UpdateButton(button discord.ButtonComponent, opts ...rest.RequestOpt) error { - return d.interaction.UpdateComponent(d.CustomID, button, opts...) -} - -// ButtonComponent returns the ButtonComponent which issued this ButtonInteraction -func (d *ButtonInteractionData) ButtonComponent() discord.ButtonComponent { - // this should never be nil - return *d.interaction.Message.ButtonByID(d.CustomID) -} - -type SelectMenuInteractionData struct { - discord.SelectMenuInteractionData - interaction *ComponentInteraction -} - -// SelectMenuComponent returns the SelectMenuComponent which issued this SelectMenuInteraction -func (d *SelectMenuInteractionData) SelectMenuComponent() discord.SelectMenuComponent { - // this should never be nil - return *d.interaction.Message.SelectMenuByID(d.CustomID) -} - -// SelectedOptions returns the selected SelectMenuOption(s) -func (d *SelectMenuInteractionData) SelectedOptions() []discord.SelectMenuOption { - options := make([]discord.SelectMenuOption, len(d.Values)) - for ii, option := range d.SelectMenuComponent().Options { - for _, value := range d.Values { - if value == option.Value { - options[ii] = option - break - } - } - } - return options -} diff --git a/core/emoji.go b/core/emoji.go deleted file mode 100644 index bcba76e9..00000000 --- a/core/emoji.go +++ /dev/null @@ -1,66 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" -) - -// NewEmote creates a new custom Emoji with the given parameters -//goland:noinspection GoUnusedExportedFunction -func NewEmote(name string, emoteID snowflake.Snowflake, animated bool) *Emoji { - return &Emoji{ - Emoji: discord.Emoji{ - Name: name, - ID: emoteID, - Animated: animated, - }, - } -} - -// NewEmoji creates a new emoji with the given unicode -//goland:noinspection GoUnusedExportedFunction -func NewEmoji(name string) *Emoji { - return &Emoji{ - Emoji: discord.Emoji{ - Name: name, - }, - } -} - -type Emoji struct { - discord.Emoji - Bot *Bot -} - -func (e *Emoji) URL(size int) string { - fileExtension := route.PNG - if e.Animated { - fileExtension = route.PNG - } - compiledRoute, _ := route.CustomEmoji.Compile(nil, fileExtension, size, e.ID) - return compiledRoute.URL() -} - -// Guild returns the Guild of the Emoji from the Caches -func (e *Emoji) Guild() *Guild { - return e.Bot.Caches.Guilds().Get(e.GuildID) -} - -func (e *Emoji) Update(emojiUpdate discord.EmojiUpdate, opts ...rest.RequestOpt) (*Emoji, error) { - emoji, err := e.Bot.RestServices.EmojiService().UpdateEmoji(e.GuildID, e.ID, emojiUpdate, opts...) - if err != nil { - return nil, err - } - return e.Bot.EntityBuilder.CreateEmoji(e.GuildID, *emoji, CacheStrategyNoWs), nil -} - -func (e *Emoji) Delete(opts ...rest.RequestOpt) error { - return e.Bot.RestServices.EmojiService().DeleteEmoji(e.GuildID, e.ID, opts...) -} - -// Reaction returns the identifier used for adding and removing reactions for messages in discord -func (e *Emoji) Reaction() string { - return ":" + e.Name + ":" + e.ID.String() -} diff --git a/core/entity_builder.go b/core/entity_builder.go deleted file mode 100644 index ac111c89..00000000 --- a/core/entity_builder.go +++ /dev/null @@ -1,829 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" -) - -// CacheStrategy is used to determine whether something should be cached when making an api request. When using the -// gateway, you'll receive the event shortly afterwards if you have the correct GatewayIntents. -type CacheStrategy func(bot *Bot) bool - -// Default caches strategy choices -var ( - CacheStrategyYes CacheStrategy = func(bot *Bot) bool { return true } - CacheStrategyNo CacheStrategy = func(bot *Bot) bool { return true } - CacheStrategyNoWs CacheStrategy = func(bot *Bot) bool { return bot.HasGateway() } -) - -var _ EntityBuilder = (*entityBuilderImpl)(nil) - -func NewEntityBuilder(bot *Bot) EntityBuilder { - return &entityBuilderImpl{bot: bot} -} - -// EntityBuilder is used to create structs for disgo's caches -type EntityBuilder interface { - Bot() *Bot - - CreateInteraction(interaction discord.Interaction, responseChannel chan<- discord.InteractionResponse, updateCache CacheStrategy) Interaction - - CreateUser(user discord.User, updateCache CacheStrategy) *User - CreateSelfUser(selfUser discord.OAuth2User, updateCache CacheStrategy) *SelfUser - CreatePresence(presence discord.Presence, updateCache CacheStrategy) *Presence - - CreateMessage(message discord.Message, updateCache CacheStrategy) *Message - - CreateGuild(guild discord.Guild, updateCache CacheStrategy) *Guild - CreateGuildTemplate(guildTemplate discord.GuildTemplate, updateCache CacheStrategy) *GuildTemplate - CreateStageInstance(stageInstance discord.StageInstance, updateCache CacheStrategy) *StageInstance - - CreateGuildScheduledEvent(guildScheduledEvent discord.GuildScheduledEvent, updateCache CacheStrategy) *GuildScheduledEvent - CreateGuildScheduledEventUser(guildID snowflake.Snowflake, guildScheduledEventUser discord.GuildScheduledEventUser, updateCache CacheStrategy) *GuildScheduledEventUser - - CreateRole(guildID snowflake.Snowflake, role discord.Role, updateCache CacheStrategy) *Role - CreateMember(guildID snowflake.Snowflake, member discord.Member, updateCache CacheStrategy) *Member - CreateBan(guildID snowflake.Snowflake, ban discord.Ban, updateCache CacheStrategy) *Ban - CreateVoiceState(voiceState discord.VoiceState, updateCache CacheStrategy) *VoiceState - - CreateApplicationCommand(applicationCommand discord.ApplicationCommand) ApplicationCommand - CreateApplicationCommandPermissions(guildCommandPermissions discord.ApplicationCommandPermissions) *ApplicationCommandPermissions - - CreateAuditLog(guildID snowflake.Snowflake, auditLog discord.AuditLog, filterOptions AuditLogFilterOptions, updateCache CacheStrategy) *AuditLog - CreateIntegration(guildID snowflake.Snowflake, integration discord.Integration, updateCache CacheStrategy) Integration - - CreateChannel(channel discord.Channel, updateCache CacheStrategy) Channel - CreateThreadMember(threadMember discord.ThreadMember, updateCache CacheStrategy) *ThreadMember - - CreateInvite(invite discord.Invite, updateCache CacheStrategy) *Invite - - CreateEmoji(guildID snowflake.Snowflake, emoji discord.Emoji, updateCache CacheStrategy) *Emoji - CreateStickerPack(stickerPack discord.StickerPack, updateCache CacheStrategy) *StickerPack - CreateSticker(sticker discord.Sticker, updateCache CacheStrategy) *Sticker - CreateMessageSticker(sticker discord.MessageSticker) *MessageSticker - - CreateWebhook(webhook discord.Webhook, updateCache CacheStrategy) Webhook -} - -// entityBuilderImpl is used for creating structs used by Disgo -type entityBuilderImpl struct { - bot *Bot -} - -// Bot returns the discord.Bot client -func (b *entityBuilderImpl) Bot() *Bot { - return b.bot -} - -func (b *entityBuilderImpl) baseInteraction(baseInteraction discord.BaseInteraction, c chan<- discord.InteractionResponse, updateCache CacheStrategy) *BaseInteraction { - member, user := b.parseMemberOrUser(baseInteraction.GuildID, baseInteraction.Member, baseInteraction.User, updateCache) - return &BaseInteraction{ - ID: baseInteraction.ID, - ApplicationID: baseInteraction.ApplicationID, - Token: baseInteraction.Token, - Version: baseInteraction.Version, - GuildID: baseInteraction.GuildID, - ChannelID: baseInteraction.ChannelID, - Locale: baseInteraction.Locale, - GuildLocale: baseInteraction.GuildLocale, - Member: member, - User: user, - ResponseChannel: c, - Acknowledged: false, - Bot: b.bot, - } -} - -// CreateInteraction creates an Interaction from the discord.Interaction response -func (b *entityBuilderImpl) CreateInteraction(interaction discord.Interaction, c chan<- discord.InteractionResponse, updateCache CacheStrategy) Interaction { - switch i := interaction.(type) { - case discord.ApplicationCommandInteraction: - var interactionData ApplicationCommandInteractionData - switch d := i.Data.(type) { - case discord.SlashCommandInteractionData: - data := SlashCommandInteractionData{ - SlashCommandInteractionData: d, - Resolved: &SlashCommandResolved{ - Users: map[snowflake.Snowflake]*User{}, - Members: map[snowflake.Snowflake]*Member{}, - Roles: map[snowflake.Snowflake]*Role{}, - Channels: map[snowflake.Snowflake]Channel{}, - }, - } - for id, u := range d.Resolved.Users { - data.Resolved.Users[id] = b.CreateUser(u, updateCache) - } - - for id, m := range d.Resolved.Members { - // discord omits the user field Oof - m.User = d.Resolved.Users[id] - data.Resolved.Members[id] = b.CreateMember(*i.GuildID, m, updateCache) - } - - for id, r := range d.Resolved.Roles { - data.Resolved.Roles[id] = b.CreateRole(*i.GuildID, r, updateCache) - } - - for id, c := range d.Resolved.Channels { - data.Resolved.Channels[id] = b.CreateChannel(c, updateCache) - } - - unmarshalOptions := d.Options - if len(unmarshalOptions) > 0 { - unmarshalOption := unmarshalOptions[0] - if option, ok := unmarshalOption.(discord.SlashCommandOptionSubCommandGroup); ok { - data.SubCommandGroupName = &option.OptionName - unmarshalOptions = make([]discord.SlashCommandOption, len(option.Options)) - for ii := range option.Options { - unmarshalOptions[ii] = option.Options[ii] - } - unmarshalOption = option.Options[0] - } - if option, ok := unmarshalOption.(discord.SlashCommandOptionSubCommand); ok { - data.SubCommandName = &option.OptionName - unmarshalOptions = option.Options - } - } - - data.Options = make(map[string]SlashCommandOption, len(unmarshalOptions)) - for _, option := range unmarshalOptions { - var slashCommandOption SlashCommandOption - switch o := option.(type) { - case discord.SlashCommandOptionString: - slashCommandOption = SlashCommandOptionString{ - SlashCommandOptionString: o, - Resolved: data.Resolved, - } - - case discord.SlashCommandOptionInt: - slashCommandOption = SlashCommandOptionInt{ - SlashCommandOptionInt: o, - } - - case discord.SlashCommandOptionBool: - slashCommandOption = SlashCommandOptionBool{ - SlashCommandOptionBool: o, - } - - case discord.SlashCommandOptionUser: - slashCommandOption = SlashCommandOptionUser{ - SlashCommandOptionUser: o, - Resolved: data.Resolved, - } - - case discord.SlashCommandOptionChannel: - slashCommandOption = SlashCommandOptionChannel{ - SlashCommandOptionChannel: o, - Resolved: data.Resolved, - } - - case discord.SlashCommandOptionRole: - slashCommandOption = SlashCommandOptionRole{ - SlashCommandOptionRole: o, - Resolved: data.Resolved, - } - - case discord.SlashCommandOptionMentionable: - slashCommandOption = SlashCommandOptionMentionable{ - SlashCommandOptionMentionable: o, - Resolved: data.Resolved, - } - - case discord.SlashCommandOptionFloat: - slashCommandOption = SlashCommandOptionFloat{ - SlashCommandOptionFloat: o, - } - - case discord.SlashCommandOptionAttachment: - slashCommandOption = SlashCommandOptionAttachment{ - SlashCommandOptionAttachment: o, - Resolved: data.Resolved, - } - - default: - b.Bot().Logger.Errorf("unknown slash command option with type %d received", option.Type()) - continue - } - data.Options[option.Name()] = slashCommandOption - } - interactionData = data - - case discord.UserCommandInteractionData: - data := UserCommandInteractionData{ - UserCommandInteractionData: d, - Resolved: &UserCommandResolved{ - Users: map[snowflake.Snowflake]*User{}, - Members: map[snowflake.Snowflake]*Member{}, - }, - } - for id, u := range d.Resolved.Users { - data.Resolved.Users[id] = b.CreateUser(u, updateCache) - } - - for id, m := range d.Resolved.Members { - // discord omits the user field Oof - m.User = d.Resolved.Users[id] - data.Resolved.Members[id] = b.CreateMember(*i.GuildID, m, updateCache) - } - interactionData = data - - case discord.MessageCommandInteractionData: - data := MessageCommandInteractionData{ - MessageCommandInteractionData: d, - Resolved: &MessageCommandResolved{ - Messages: map[snowflake.Snowflake]*Message{}, - }, - } - for id, message := range d.Resolved.Messages { - data.Resolved.Messages[id] = b.CreateMessage(message, updateCache) - } - interactionData = data - } - baseInteraction := b.baseInteraction(i.BaseInteraction, c, updateCache) - return &ApplicationCommandInteraction{ - CreateInteraction: CreateInteraction{BaseInteraction: baseInteraction}, - Data: interactionData, - } - - case discord.ComponentInteraction: - baseInteraction := b.baseInteraction(i.BaseInteraction, c, updateCache) - componentInteraction := &ComponentInteraction{ - CreateInteraction: CreateInteraction{BaseInteraction: baseInteraction}, - Message: b.CreateMessage(i.Message, updateCache), - } - switch d := i.Data.(type) { - case discord.ButtonInteractionData: - componentInteraction.Data = ButtonInteractionData{ - ButtonInteractionData: d, - interaction: componentInteraction, - } - - case discord.SelectMenuInteractionData: - componentInteraction.Data = SelectMenuInteractionData{ - SelectMenuInteractionData: d, - interaction: componentInteraction, - } - } - return componentInteraction - - case discord.AutocompleteInteraction: - autocompleteInteraction := &AutocompleteInteraction{ - BaseInteraction: b.baseInteraction(i.BaseInteraction, c, updateCache), - Data: AutocompleteInteractionData{ - AutocompleteInteractionData: i.Data, - }, - } - - unmarshalOptions := i.Data.Options - if len(unmarshalOptions) > 0 { - unmarshalOption := unmarshalOptions[0] - if option, ok := unmarshalOption.(discord.AutocompleteOptionSubCommandGroup); ok { - autocompleteInteraction.Data.SubCommandGroupName = &option.GroupName - unmarshalOptions = make([]discord.AutocompleteOption, len(option.Options)) - for i := range option.Options { - unmarshalOptions[i] = option.Options[i] - } - unmarshalOption = option.Options[0] - } - if option, ok := unmarshalOption.(discord.AutocompleteOptionSubCommand); ok { - autocompleteInteraction.Data.SubCommandName = &option.CommandName - unmarshalOptions = option.Options - } - } - - autocompleteInteraction.Data.Options = make(map[string]discord.AutocompleteOption, len(unmarshalOptions)) - for _, option := range unmarshalOptions { - autocompleteInteraction.Data.Options[option.Name()] = option - } - - return autocompleteInteraction - - case discord.ModalSubmitInteraction: - baseInteraction := b.baseInteraction(i.BaseInteraction, c, updateCache) - - componentsMap := ModalComponentsMap{} - - for j := range i.Data.Components { - for k := range i.Data.Components[j].Components() { - component := i.Data.Components[j].Components()[k] - if inputComponent, ok := component.(discord.InputComponent); ok { - componentsMap[inputComponent.ID()] = inputComponent - } - } - } - - modalSubmitInteraction := &ModalSubmitInteraction{ - CreateInteraction: CreateInteraction{BaseInteraction: baseInteraction}, - Data: ModalSubmitInteractionData{ - ModalSubmitInteractionData: i.Data, - Components: componentsMap, - }, - } - - return modalSubmitInteraction - - default: - b.Bot().Logger.Error("unknown interaction type %d received", interaction.Type()) - return nil - } -} - -func (b *entityBuilderImpl) parseMemberOrUser(guildID *snowflake.Snowflake, member *discord.Member, user *discord.User, updateCache CacheStrategy) (rMember *Member, rUser *User) { - if member != nil { - rMember = b.CreateMember(*guildID, *member, updateCache) - rUser = rMember.User - } else { - rUser = b.CreateUser(*user, updateCache) - } - return -} - -// CreateUser returns a new User entity -func (b *entityBuilderImpl) CreateUser(user discord.User, updateCache CacheStrategy) *User { - coreUser := &User{ - User: user, - Bot: b.Bot(), - } - if updateCache(b.Bot()) { - return b.Bot().Caches.Users().Set(coreUser) - } - return coreUser -} - -// CreateSelfUser returns a new SelfUser entity -func (b *entityBuilderImpl) CreateSelfUser(selfUser discord.OAuth2User, updateCache CacheStrategy) *SelfUser { - coreSelfUser := &SelfUser{ - OAuth2User: selfUser, - Bot: b.Bot(), - User: b.CreateUser(selfUser.User, updateCache), - } - b.Bot().SelfUser = coreSelfUser - return coreSelfUser -} - -func (b *entityBuilderImpl) CreatePresence(presence discord.Presence, updateCache CacheStrategy) *Presence { - corePresence := &Presence{ - Presence: presence, - Bot: b.Bot(), - } - - if updateCache(b.Bot()) { - return b.Bot().Caches.Presences().Set(corePresence) - } - return corePresence -} - -// CreateMessage returns a new discord.Message entity -func (b *entityBuilderImpl) CreateMessage(message discord.Message, updateCache CacheStrategy) *Message { - coreMsg := &Message{ - Message: message, - Bot: b.Bot(), - } - - if message.Member != nil { - message.Member.User = message.Author // set the underlying discord data which is stored in caches - coreMsg.Member = b.CreateMember(*message.GuildID, *message.Member, updateCache) - coreMsg.Author = coreMsg.Member.User - } else { - coreMsg.Author = b.CreateUser(message.Author, updateCache) - } - - if len(message.Stickers) > 0 { - coreMsg.Stickers = make([]*MessageSticker, len(message.Stickers)) - } - - for i, sticker := range message.Stickers { - coreMsg.Stickers[i] = b.CreateMessageSticker(sticker) - } - - // TODO: should we caches mentioned users, members, etc? - if updateCache(b.Bot()) { - return b.Bot().Caches.Messages().Set(coreMsg) - } - return coreMsg -} - -// CreateGuildTemplate returns a new discord.GuildTemplate entity -func (b *entityBuilderImpl) CreateGuildTemplate(guildTemplate discord.GuildTemplate, updateCache CacheStrategy) *GuildTemplate { - coreTemplate := &GuildTemplate{ - GuildTemplate: guildTemplate, - } - - if coreTemplate.Creator != nil { - coreTemplate.Creator = b.CreateUser(guildTemplate.Creator, updateCache) - } - return coreTemplate -} - -// CreateGuild returns a new discord.Guild entity -func (b *entityBuilderImpl) CreateGuild(guild discord.Guild, updateCache CacheStrategy) *Guild { - coreGuild := &Guild{ - Guild: guild, - Bot: b.Bot(), - } - - if updateCache(b.Bot()) { - return b.Bot().Caches.Guilds().Set(coreGuild) - } - return coreGuild -} - -// CreateMember returns a new discord.Member entity -func (b *entityBuilderImpl) CreateMember(guildID snowflake.Snowflake, member discord.Member, updateCache CacheStrategy) *Member { - coreMember := &Member{ - Member: member, - Bot: b.Bot(), - } - - coreMember.GuildID = guildID - coreMember.User = b.CreateUser(member.User, updateCache) - if updateCache(b.Bot()) { - return b.Bot().Caches.Members().Set(coreMember) - } - return coreMember -} - -func (b *entityBuilderImpl) CreateBan(guildID snowflake.Snowflake, ban discord.Ban, updateCache CacheStrategy) *Ban { - return &Ban{ - Ban: ban, - Bot: b.Bot(), - User: b.CreateUser(ban.User, updateCache), - GuildID: guildID, - } -} - -// CreateVoiceState returns a new discord.VoiceState entity -func (b *entityBuilderImpl) CreateVoiceState(voiceState discord.VoiceState, updateCache CacheStrategy) *VoiceState { - coreState := &VoiceState{ - VoiceState: voiceState, - Bot: b.Bot(), - } - if voiceState.Member != nil { - coreState.Member = b.CreateMember(voiceState.GuildID, *voiceState.Member, updateCache) - } - - if updateCache(b.Bot()) { - return b.Bot().Caches.VoiceStates().Set(coreState) - } - return coreState -} - -// CreateApplicationCommand returns a new discord.ApplicationCommand entity -func (b *entityBuilderImpl) CreateApplicationCommand(applicationCommand discord.ApplicationCommand) ApplicationCommand { - switch c := applicationCommand.(type) { - case discord.SlashCommand: - return &SlashCommand{ - SlashCommand: c, - Bot: b.Bot(), - } - - case discord.UserCommand: - return &UserCommand{ - UserCommand: c, - Bot: b.Bot(), - } - - case discord.MessageCommand: - return &MessageCommand{ - MessageCommand: c, - Bot: b.Bot(), - } - default: - b.Bot().Logger.Errorf("unknown application command type %d received", applicationCommand.Type()) - return nil - } -} - -// CreateApplicationCommandPermissions returns a new discord.ApplicationCommandPermissions entity -func (b *entityBuilderImpl) CreateApplicationCommandPermissions(guildCommandPermissions discord.ApplicationCommandPermissions) *ApplicationCommandPermissions { - coreGuildCommandPermissions := &ApplicationCommandPermissions{ - ApplicationCommandPermissions: guildCommandPermissions, - Bot: b.Bot(), - } - - return coreGuildCommandPermissions -} - -// CreateRole returns a new discord.Role entity -func (b *entityBuilderImpl) CreateRole(guildID snowflake.Snowflake, role discord.Role, updateCache CacheStrategy) *Role { - coreRole := &Role{ - Role: role, - } - - coreRole.GuildID = guildID - - if updateCache(b.Bot()) { - return b.Bot().Caches.Roles().Set(coreRole) - } - return coreRole -} - -// CreateAuditLog returns a new discord.AuditLog entity -func (b *entityBuilderImpl) CreateAuditLog(guildID snowflake.Snowflake, auditLog discord.AuditLog, filterOptions AuditLogFilterOptions, updateCache CacheStrategy) *AuditLog { - coreAuditLog := &AuditLog{ - AuditLog: auditLog, - GuildID: guildID, - FilterOptions: filterOptions, - Bot: b.Bot(), - } - for _, guildScheduledEvent := range auditLog.GuildScheduledEvents { - coreAuditLog.GuildScheduledEvents[guildScheduledEvent.ID] = b.CreateGuildScheduledEvent(guildScheduledEvent, updateCache) - } - for _, integration := range auditLog.Integrations { - coreAuditLog.Integrations[integration.ID()] = b.CreateIntegration(guildID, integration, updateCache) - } - for _, thread := range auditLog.Threads { - coreAuditLog.Threads[thread.ID()] = b.CreateChannel(thread, updateCache).(GuildThread) - } - for _, user := range auditLog.Users { - coreAuditLog.Users[user.ID] = b.CreateUser(user, updateCache) - } - for _, webhook := range auditLog.Webhooks { - coreAuditLog.Webhooks[webhook.ID()] = b.CreateWebhook(webhook, updateCache) - } - return coreAuditLog -} - -// CreateIntegration returns a new discord.Integration entity -func (b *entityBuilderImpl) CreateIntegration(guildID snowflake.Snowflake, integration discord.Integration, updateCache CacheStrategy) Integration { - var coreIntegration Integration - - switch i := integration.(type) { - case discord.TwitchIntegration: - coreIntegration = &TwitchIntegration{ - TwitchIntegration: i, - Bot: b.Bot(), - GuildID: guildID, - User: b.CreateUser(i.User, updateCache), - } - - case discord.YouTubeIntegration: - coreIntegration = &YouTubeIntegration{ - YouTubeIntegration: i, - Bot: b.Bot(), - GuildID: guildID, - User: b.CreateUser(i.User, updateCache), - } - - case discord.BotIntegration: - coreIntegration = &BotIntegration{ - BotIntegration: i, - Bot: b.Bot(), - GuildID: guildID, - Application: &IntegrationApplication{ - IntegrationApplication: i.Application, - Bot: b.CreateUser(i.Application.Bot, updateCache), - }, - } - - default: - b.Bot().Logger.Errorf("unknown integration type %d received", integration.Type()) - return nil - } - - return coreIntegration -} - -// CreateWebhook returns a new Webhook entity -func (b *entityBuilderImpl) CreateWebhook(webhook discord.Webhook, updateCache CacheStrategy) Webhook { - var coreWebhook Webhook - - switch w := webhook.(type) { - case discord.IncomingWebhook: - coreWebhook = &IncomingWebhook{ - IncomingWebhook: w, - Bot: b.Bot(), - User: b.CreateUser(w.User, updateCache), - } - - case discord.ChannelFollowerWebhook: - coreWebhook = &ChannelFollowerWebhook{ - ChannelFollowerWebhook: w, - Bot: b.Bot(), - User: b.CreateUser(w.User, updateCache), - } - - case discord.ApplicationWebhook: - coreWebhook = &ApplicationWebhook{ - ApplicationWebhook: w, - Bot: b.Bot(), - } - - default: - b.Bot().Logger.Errorf("unknown webhook type %d received", webhook.Type()) - return nil - } - - return coreWebhook -} - -// CreateChannel returns a new Channel entity -func (b *entityBuilderImpl) CreateChannel(channel discord.Channel, updateCache CacheStrategy) Channel { - var c Channel - switch ch := channel.(type) { - case discord.GuildTextChannel: - c = &GuildTextChannel{ - GuildTextChannel: ch, - Bot: b.Bot(), - } - - case discord.DMChannel: - c = &DMChannel{ - DMChannel: ch, - Bot: b.Bot(), - } - - case discord.GuildVoiceChannel: - c = &GuildVoiceChannel{ - GuildVoiceChannel: ch, - Bot: b.Bot(), - ConnectedMemberIDs: map[snowflake.Snowflake]struct{}{}, - } - - case discord.GroupDMChannel: - c = &GroupDMChannel{ - GroupDMChannel: ch, - Bot: b.Bot(), - } - - case discord.GuildCategoryChannel: - c = &GuildCategoryChannel{ - GuildCategoryChannel: ch, - Bot: b.Bot(), - } - - case discord.GuildNewsChannel: - c = &GuildNewsChannel{ - GuildNewsChannel: ch, - Bot: b.Bot(), - } - - case discord.GuildStoreChannel: - c = &GuildStoreChannel{ - GuildStoreChannel: ch, - Bot: b.Bot(), - } - - case discord.GuildNewsThread: - c = &GuildNewsThread{ - GuildNewsThread: ch, - Bot: b.Bot(), - } - - case discord.GuildPrivateThread: - c = &GuildPrivateThread{ - GuildPrivateThread: ch, - Bot: b.Bot(), - } - - case discord.GuildPublicThread: - c = &GuildPublicThread{ - GuildPublicThread: ch, - Bot: b.Bot(), - } - - case discord.GuildStageVoiceChannel: - c = &GuildStageVoiceChannel{ - GuildStageVoiceChannel: ch, - Bot: b.Bot(), - StageInstanceID: nil, - ConnectedMemberIDs: map[snowflake.Snowflake]struct{}{}, - } - - default: - panic("unknown channel type") - } - - if updateCache(b.Bot()) { - return b.Bot().Caches.Channels().Set(c) - } - return c -} - -func (b *entityBuilderImpl) CreateThreadMember(threadMember discord.ThreadMember, updateCache CacheStrategy) *ThreadMember { - coreThreadMember := &ThreadMember{ - ThreadMember: threadMember, - Bot: b.Bot(), - } - - if updateCache(b.Bot()) { - return b.Bot().Caches.ThreadMembers().Set(coreThreadMember) - } - return coreThreadMember -} - -func (b *entityBuilderImpl) CreateStageInstance(stageInstance discord.StageInstance, updateCache CacheStrategy) *StageInstance { - coreStageInstance := &StageInstance{ - StageInstance: stageInstance, - Bot: b.Bot(), - } - - if channel := b.Bot().Caches.Channels().Get(stageInstance.ChannelID); channel != nil { - if ch, ok := channel.(*GuildStageVoiceChannel); ok { - ch.StageInstanceID = &stageInstance.ID - } - } - - if updateCache(b.Bot()) { - return b.Bot().Caches.StageInstances().Set(coreStageInstance) - } - return coreStageInstance -} - -func (b *entityBuilderImpl) CreateGuildScheduledEvent(guildScheduledEvent discord.GuildScheduledEvent, updateCache CacheStrategy) *GuildScheduledEvent { - coreGuildScheduledEvent := &GuildScheduledEvent{ - GuildScheduledEvent: guildScheduledEvent, - Creator: b.CreateUser(guildScheduledEvent.Creator, updateCache), - Bot: b.Bot(), - } - - if updateCache(b.Bot()) { - return b.Bot().Caches.GuildScheduledEvents().Set(coreGuildScheduledEvent) - } - return coreGuildScheduledEvent -} - -func (b *entityBuilderImpl) CreateGuildScheduledEventUser(guildID snowflake.Snowflake, guildScheduledEventUser discord.GuildScheduledEventUser, updateCache CacheStrategy) *GuildScheduledEventUser { - coreGuildScheduledEventUser := &GuildScheduledEventUser{ - GuildScheduledEventUser: guildScheduledEventUser, Bot: b.Bot(), - User: b.CreateUser(guildScheduledEventUser.User, updateCache), - } - if guildScheduledEventUser.Member != nil { - coreGuildScheduledEventUser.Member = b.CreateMember(guildID, *guildScheduledEventUser.Member, updateCache) - } - - return coreGuildScheduledEventUser -} - -func (b *entityBuilderImpl) CreateInvite(invite discord.Invite, updateCache CacheStrategy) *Invite { - coreInvite := &Invite{ - Invite: invite, - Bot: b.Bot(), - } - - if invite.Inviter != nil { - coreInvite.Inviter = b.CreateUser(*invite.Inviter, updateCache) - } - - if invite.TargetUser != nil { - coreInvite.TargetUser = b.CreateUser(*invite.TargetUser, updateCache) - } - - return coreInvite -} - -// CreateEmoji returns a new discord.Emoji entity -func (b *entityBuilderImpl) CreateEmoji(guildID snowflake.Snowflake, emoji discord.Emoji, updateCache CacheStrategy) *Emoji { - coreEmoji := &Emoji{ - Emoji: emoji, - Bot: b.Bot(), - } - if emoji.ID == "" { // return if emoji is no custom emote - return coreEmoji - } - - coreEmoji.GuildID = guildID - - if updateCache(b.Bot()) { - return b.Bot().Caches.Emojis().Set(coreEmoji) - } - return coreEmoji -} - -func (b *entityBuilderImpl) CreateStickerPack(stickerPack discord.StickerPack, updateCache CacheStrategy) *StickerPack { - coreStickerPack := &StickerPack{ - StickerPack: stickerPack, - Bot: b.Bot(), - Stickers: make([]*Sticker, len(stickerPack.Stickers)), - } - for i, sticker := range stickerPack.Stickers { - coreStickerPack.Stickers[i] = b.CreateSticker(sticker, updateCache) - } - - return coreStickerPack -} - -// CreateSticker returns a new discord.Sticker entity -func (b *entityBuilderImpl) CreateSticker(sticker discord.Sticker, updateCache CacheStrategy) *Sticker { - coreSticker := &Sticker{ - Sticker: sticker, - Bot: b.Bot(), - } - - if sticker.User != nil { - coreSticker.User = b.Bot().EntityBuilder.CreateUser(*sticker.User, CacheStrategyNo) - } - - if updateCache(b.Bot()) { - return b.Bot().Caches.Stickers().Set(coreSticker) - } - return coreSticker -} - -// CreateMessageSticker returns a new discord.Sticker entity -func (b *entityBuilderImpl) CreateMessageSticker(messageSticker discord.MessageSticker) *MessageSticker { - return &MessageSticker{ - MessageSticker: messageSticker, - Bot: b.Bot(), - } -} diff --git a/core/event_manager.go b/core/event_manager.go deleted file mode 100644 index f2c6ba17..00000000 --- a/core/event_manager.go +++ /dev/null @@ -1,153 +0,0 @@ -package core - -import ( - "io" - "runtime/debug" - - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/json" -) - -var ( - DefaultEventManagerConfig = EventManagerConfig{} -) - -type EventManagerConfig struct { - EventListeners []EventListener - RawEventsEnabled bool - AsyncEventsEnabled bool - - GatewayHandlers map[discord.GatewayEventType]GatewayEventHandler - HTTPServerHandler HTTPServerEventHandler -} - -var _ EventManager = (*eventManagerImpl)(nil) - -func NewEventManager(bot *Bot, config *EventManagerConfig) EventManager { - if config == nil { - config = &DefaultEventManagerConfig - } - - return &eventManagerImpl{ - bot: bot, - config: *config, - } -} - -// EventManager lets you listen for specific events triggered by raw gateway events -type EventManager interface { - Bot() *Bot - Config() EventManagerConfig - - AddEventListeners(eventListeners ...EventListener) - RemoveEventListeners(eventListeners ...EventListener) - HandleGateway(gatewayEventType discord.GatewayEventType, sequenceNumber discord.GatewaySequence, payload io.Reader) - HandleHTTP(responseChannel chan<- discord.InteractionResponse, payload io.Reader) - Dispatch(event Event) -} - -// EventListener is used to create new EventListener to listen to events -type EventListener interface { - OnEvent(event Event) -} - -// Event the basic interface each event implement -type Event interface { - Bot() *Bot - SequenceNumber() discord.GatewaySequence -} - -// GatewayEventHandler is used to handle Gateway Event(s) -type GatewayEventHandler interface { - EventType() discord.GatewayEventType - New() interface{} - HandleGatewayEvent(bot *Bot, sequenceNumber discord.GatewaySequence, v interface{}) -} - -// HTTPServerEventHandler is used to handle HTTP Event(s) -type HTTPServerEventHandler interface { - New() interface{} - HandleHTTPEvent(bot *Bot, responseChannel chan<- discord.InteractionResponse, v interface{}) -} - -// eventManagerImpl is the implementation of core.EventManager -type eventManagerImpl struct { - bot *Bot - config EventManagerConfig -} - -// Bot returns the core.Bot instance used by the core.EventManager -func (e *eventManagerImpl) Bot() *Bot { - return e.bot -} - -func (e *eventManagerImpl) Config() EventManagerConfig { - return e.config -} - -// HandleGateway calls the correct core.EventHandler -func (e *eventManagerImpl) HandleGateway(gatewayEventType discord.GatewayEventType, sequenceNumber discord.GatewaySequence, reader io.Reader) { - if handler, ok := e.config.GatewayHandlers[gatewayEventType]; ok { - v := handler.New() - if v != nil { - if err := json.NewDecoder(reader).Decode(&v); err != nil { - e.Bot().Logger.Errorf("error while unmarshalling event '%s'. error: %s", gatewayEventType, err.Error()) - return - } - } - handler.HandleGatewayEvent(e.Bot(), sequenceNumber, v) - } else { - e.Bot().Logger.Warnf("no handler for gateway event '%s' found", gatewayEventType) - } -} - -// HandleHTTP calls the correct core.EventHandler -func (e *eventManagerImpl) HandleHTTP(responseChannel chan<- discord.InteractionResponse, reader io.Reader) { - v := e.config.HTTPServerHandler.New() - if err := json.NewDecoder(reader).Decode(&v); err != nil { - e.Bot().Logger.Error("error while unmarshalling httpserver event. error: ", err) - } - e.config.HTTPServerHandler.HandleHTTPEvent(e.Bot(), responseChannel, v) -} - -// Dispatch dispatches a new event to the client -func (e *eventManagerImpl) Dispatch(event Event) { - defer func() { - if r := recover(); r != nil { - e.Bot().Logger.Errorf("recovered from panic in event listener: %+v\nstack: %s", r, string(debug.Stack())) - return - } - }() - for i := range e.config.EventListeners { - if e.Config().AsyncEventsEnabled { - go func() { - defer func() { - if r := recover(); r != nil { - e.Bot().Logger.Errorf("recovered from panic in event listener: %+v\nstack: %s", r, string(debug.Stack())) - return - } - }() - e.config.EventListeners[i].OnEvent(event) - }() - continue - } - e.config.EventListeners[i].OnEvent(event) - } -} - -// AddEventListeners adds one or more core.EventListener(s) to the core.EventManager -func (e *eventManagerImpl) AddEventListeners(listeners ...EventListener) { - e.config.EventListeners = append(e.config.EventListeners, listeners...) -} - -// RemoveEventListeners removes one or more core.EventListener(s) from the core.EventManager -func (e *eventManagerImpl) RemoveEventListeners(listeners ...EventListener) { - for _, listener := range listeners { - for i, l := range e.config.EventListeners { - if l == listener { - e.config.EventListeners = append(e.config.EventListeners[:i], e.config.EventListeners[i+1:]...) - break - } - } - } -} diff --git a/core/events/events_dm_channel.go b/core/events/events_dm_channel.go deleted file mode 100644 index e9a0d5aa..00000000 --- a/core/events/events_dm_channel.go +++ /dev/null @@ -1,55 +0,0 @@ -package events - -import ( - "time" - - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" -) - -// GenericDMChannelEvent is called upon receiving DMChannelCreateEvent, DMChannelUpdateEvent, DMChannelDeleteEvent or DMUserTypingStartEvent -type GenericDMChannelEvent struct { - *GenericEvent - Channel *core.DMChannel - ChannelID snowflake.Snowflake -} - -// DMChannelCreateEvent indicates that a new core.DMChannel got created -type DMChannelCreateEvent struct { - *GenericDMChannelEvent -} - -// DMChannelUpdateEvent indicates that a core.DMChannel got updated -type DMChannelUpdateEvent struct { - *GenericDMChannelEvent - OldChannel *core.DMChannel -} - -// DMChannelDeleteEvent indicates that a core.DMChannel got deleted -type DMChannelDeleteEvent struct { - *GenericDMChannelEvent -} - -type DMChannelPinsUpdateEvent struct { - *GenericEvent - ChannelID snowflake.Snowflake - NewLastPinTimestamp *discord.Time - OldLastPinTimestamp *discord.Time -} - -// DMUserTypingStartEvent indicates that a core.User started typing in a core.DMChannel(requires discord.GatewayIntentDirectMessageTyping) -type DMUserTypingStartEvent struct { - *GenericEvent - ChannelID snowflake.Snowflake - UserID snowflake.Snowflake - Timestamp time.Time -} - -// Channel returns the core.DMChannel the DMUserTypingStartEvent happened in -func (e DMUserTypingStartEvent) Channel() *core.DMChannel { - if ch := e.Bot().Caches.Channels().Get(e.ChannelID); ch != nil { - return ch.(*core.DMChannel) - } - return nil -} diff --git a/core/events/events_generic_event.go b/core/events/events_generic_event.go deleted file mode 100644 index c70ae091..00000000 --- a/core/events/events_generic_event.go +++ /dev/null @@ -1,26 +0,0 @@ -package events - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" -) - -// NewGenericEvent constructs a new GenericEvent with the provided Bot instance -func NewGenericEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence) *GenericEvent { - return &GenericEvent{bot: bot, sequenceNumber: sequenceNumber} -} - -// GenericEvent the base event structure -type GenericEvent struct { - bot *core.Bot - sequenceNumber discord.GatewaySequence -} - -func (e GenericEvent) Bot() *core.Bot { - return e.bot -} - -// SequenceNumber returns the sequence number of the gateway event -func (e GenericEvent) SequenceNumber() discord.GatewaySequence { - return e.sequenceNumber -} diff --git a/core/events/events_guild.go b/core/events/events_guild.go deleted file mode 100644 index 187af28d..00000000 --- a/core/events/events_guild.go +++ /dev/null @@ -1,64 +0,0 @@ -package events - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" -) - -// GenericGuildEvent is called upon receiving GuildUpdateEvent, GuildAvailableEvent, GuildUnavailableEvent, GuildJoinEvent, GuildLeaveEvent, GuildReadyEvent, GuildBanEvent, GuildUnbanEvent -type GenericGuildEvent struct { - *GenericEvent - GuildID snowflake.Snowflake - Guild *core.Guild -} - -// GuildUpdateEvent is called upon receiving core.Guild updates -type GuildUpdateEvent struct { - *GenericGuildEvent - OldGuild *core.Guild -} - -// GuildAvailableEvent is called when an unavailable core.Guild becomes available -type GuildAvailableEvent struct { - *GenericGuildEvent -} - -// GuildUnavailableEvent is called when an available core.Guild becomes unavailable -type GuildUnavailableEvent struct { - *GenericGuildEvent -} - -// GuildJoinEvent is called when the bot joins a core.Guild -type GuildJoinEvent struct { - *GenericGuildEvent -} - -// GuildLeaveEvent is called when the bot leaves a core.Guild -type GuildLeaveEvent struct { - *GenericGuildEvent -} - -// GuildReadyEvent is called when a core.Guild becomes loaded for the first time -type GuildReadyEvent struct { - *GenericGuildEvent -} - -// GuildsReadyEvent is called when all core.Guild(s) are loaded after logging in -type GuildsReadyEvent struct { - *GenericEvent - ShardID int -} - -// GuildBanEvent is called when a core.Member/core.User is banned from the core.Guild -type GuildBanEvent struct { - *GenericEvent - GuildID snowflake.Snowflake - User *core.User -} - -// GuildUnbanEvent is called when a core.Member/core.User is unbanned from the core.Guild -type GuildUnbanEvent struct { - *GenericEvent - GuildID snowflake.Snowflake - User *core.User -} diff --git a/core/events/events_guild_emoji.go b/core/events/events_guild_emoji.go deleted file mode 100644 index 74fb6bf4..00000000 --- a/core/events/events_guild_emoji.go +++ /dev/null @@ -1,29 +0,0 @@ -package events - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" -) - -// GenericEmojiEvent is called upon receiving EmojiCreateEvent, EmojiUpdateEvent or EmojiDeleteEvent (requires discord.GatewayIntentGuildEmojisAndStickers) -type GenericEmojiEvent struct { - *GenericEvent - GuildID snowflake.Snowflake - Emoji *core.Emoji -} - -// EmojiCreateEvent indicates that a new core.Emoji got created in a core.Guild (requires discord.GatewayIntentGuildEmojisAndStickers) -type EmojiCreateEvent struct { - *GenericEmojiEvent -} - -// EmojiUpdateEvent indicates that a core.Emoji got updated in a core.Guild (requires discord.GatewayIntentGuildEmojisAndStickers) -type EmojiUpdateEvent struct { - *GenericEmojiEvent - OldEmoji *core.Emoji -} - -// EmojiDeleteEvent indicates that a core.Emoji got deleted in a core.Guild (requires discord.GatewayIntentGuildEmojisAndStickers) -type EmojiDeleteEvent struct { - *GenericEmojiEvent -} diff --git a/core/events/events_guild_invite.go b/core/events/events_guild_invite.go deleted file mode 100644 index 18e6a255..00000000 --- a/core/events/events_guild_invite.go +++ /dev/null @@ -1,33 +0,0 @@ -package events - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" -) - -// GenericGuildInviteEvent is called upon receiving GuildInviteCreateEvent or GuildInviteDeleteEvent (requires discord.GatewayIntentGuildInvites) -type GenericGuildInviteEvent struct { - *GenericEvent - GuildID snowflake.Snowflake - ChannelID snowflake.Snowflake - Code string -} - -// Channel returns the Channel the GenericGuildInviteEvent happened in. -func (e GenericGuildInviteEvent) Channel() core.GuildChannel { - if ch := e.Bot().Caches.Channels().Get(e.ChannelID); ch != nil { - return ch.(core.GuildChannel) - } - return nil -} - -// GuildInviteCreateEvent is called upon creation of a new core.Invite in a core.Guild (requires discord.GatewayIntentGuildInvites) -type GuildInviteCreateEvent struct { - *GenericGuildInviteEvent - Invite *core.Invite -} - -// GuildInviteDeleteEvent is called upon deletion of a core.Invite in a core.Guild (requires discord.GatewayIntentGuildInvites) -type GuildInviteDeleteEvent struct { - *GenericGuildInviteEvent -} diff --git a/core/events/events_guild_member.go b/core/events/events_guild_member.go deleted file mode 100644 index 037aab2a..00000000 --- a/core/events/events_guild_member.go +++ /dev/null @@ -1,52 +0,0 @@ -package events - -import ( - "time" - - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" -) - -// GenericGuildMemberEvent generic core.Member event -type GenericGuildMemberEvent struct { - *GenericEvent - GuildID snowflake.Snowflake - Member *core.Member -} - -// GuildMemberJoinEvent indicates that a core.Member joined the core.Guild -type GuildMemberJoinEvent struct { - *GenericGuildMemberEvent -} - -// GuildMemberUpdateEvent indicates that a core.Member updated -type GuildMemberUpdateEvent struct { - *GenericGuildMemberEvent - OldMember *core.Member -} - -// GuildMemberLeaveEvent indicates that a core.Member left the core.Guild -type GuildMemberLeaveEvent struct { - *GenericEvent - GuildID snowflake.Snowflake - User *core.User - Member *core.Member -} - -// GuildMemberTypingStartEvent indicates that a core.Member started typing in a core.BaseGuildMessageChannel(requires discord.GatewayIntentGuildMessageTyping) -type GuildMemberTypingStartEvent struct { - *GenericEvent - ChannelID snowflake.Snowflake - UserID snowflake.Snowflake - GuildID snowflake.Snowflake - Timestamp time.Time - Member *core.Member -} - -// Channel returns the core.BaseGuildMessageChannel the GuildMemberTypingStartEvent happened in -func (e GuildMemberTypingStartEvent) Channel() core.BaseGuildMessageChannel { - if ch := e.Bot().Caches.Channels().Get(e.ChannelID); ch != nil { - return ch.(core.BaseGuildMessageChannel) - } - return nil -} diff --git a/core/events/events_guild_message.go b/core/events/events_guild_message.go deleted file mode 100644 index 1cb1b111..00000000 --- a/core/events/events_guild_message.go +++ /dev/null @@ -1,45 +0,0 @@ -package events - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" -) - -// GenericGuildMessageEvent is called upon receiving GuildMessageCreateEvent, GuildMessageUpdateEvent or GuildMessageDeleteEvent -type GenericGuildMessageEvent struct { - *GenericEvent - MessageID snowflake.Snowflake - Message *core.Message - ChannelID snowflake.Snowflake - GuildID snowflake.Snowflake -} - -// Guild returns the core.Guild the GenericGuildMessageEvent happened in. -// This will only check cached guilds! -func (e GenericGuildMessageEvent) Guild() *core.Guild { - return e.Bot().Caches.Guilds().Get(e.GuildID) -} - -// Channel returns the core.DMChannel where the GenericGuildMessageEvent happened -func (e GenericGuildMessageEvent) Channel() core.GuildMessageChannel { - if ch := e.Bot().Caches.Channels().Get(e.ChannelID); ch != nil { - return ch.(core.GuildMessageChannel) - } - return nil -} - -// GuildMessageCreateEvent is called upon receiving a core.Message in a Channel -type GuildMessageCreateEvent struct { - *GenericGuildMessageEvent -} - -// GuildMessageUpdateEvent is called upon editing a core.Message in a Channel -type GuildMessageUpdateEvent struct { - *GenericGuildMessageEvent - OldMessage *core.Message -} - -// GuildMessageDeleteEvent is called upon deleting a core.Message in a Channel -type GuildMessageDeleteEvent struct { - *GenericGuildMessageEvent -} diff --git a/core/events/events_guild_sticker.go b/core/events/events_guild_sticker.go deleted file mode 100644 index 2637e847..00000000 --- a/core/events/events_guild_sticker.go +++ /dev/null @@ -1,29 +0,0 @@ -package events - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" -) - -// GenericStickerEvent is called upon receiving StickerCreateEvent, StickerUpdateEvent or StickerDeleteEvent (requires discord.GatewayIntentGuildEmojisAndStickers) -type GenericStickerEvent struct { - *GenericEvent - GuildID snowflake.Snowflake - Sticker *core.Sticker -} - -// StickerCreateEvent indicates that a new core.Sticker got created in a core.Guild (requires discord.GatewayIntentGuildEmojisAndStickers) -type StickerCreateEvent struct { - *GenericStickerEvent -} - -// StickerUpdateEvent indicates that a core.Sticker got updated in a core.Guild (requires discord.GatewayIntentGuildEmojisAndStickers) -type StickerUpdateEvent struct { - *GenericStickerEvent - OldSticker *core.Sticker -} - -// StickerDeleteEvent indicates that a core.Sticker got deleted in a core.Guild (requires discord.GatewayIntentGuildEmojisAndStickers) -type StickerDeleteEvent struct { - *GenericStickerEvent -} diff --git a/core/events/events_guild_voice.go b/core/events/events_guild_voice.go deleted file mode 100644 index 45da6675..00000000 --- a/core/events/events_guild_voice.go +++ /dev/null @@ -1,40 +0,0 @@ -package events - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" -) - -// GenericGuildVoiceEvent is called upon receiving GuildVoiceJoinEvent, GuildVoiceMoveEvent, GuildVoiceLeaveEvent -type GenericGuildVoiceEvent struct { - *GenericEvent - VoiceState *core.VoiceState -} - -// GuildVoiceStateUpdateEvent indicates that the core.VoiceState of a core.Member has updated(requires core.GatewayIntentsGuildVoiceStates) -type GuildVoiceStateUpdateEvent struct { - *GenericGuildVoiceEvent - OldVoiceState *core.VoiceState -} - -// GuildVoiceJoinEvent indicates that a core.Member joined a core.Channel(requires core.GatewayIntentsGuildVoiceStates) -type GuildVoiceJoinEvent struct { - *GenericGuildVoiceEvent -} - -// GuildVoiceMoveEvent indicates that a core.Member moved a core.Channel(requires core.GatewayIntentsGuildVoiceStates) -type GuildVoiceMoveEvent struct { - *GenericGuildVoiceEvent - OldVoiceState *core.VoiceState -} - -// GuildVoiceLeaveEvent indicates that a core.Member left a core.Channel(requires core.GatewayIntentsGuildVoiceStates) -type GuildVoiceLeaveEvent struct { - *GenericGuildVoiceEvent - OldVoiceState *core.VoiceState -} - -type VoiceServerUpdateEvent struct { - *GenericEvent - VoiceServerUpdate discord.VoiceServerUpdate -} diff --git a/core/events/events_guild_webhooks_update.go b/core/events/events_guild_webhooks_update.go deleted file mode 100644 index d880eeb9..00000000 --- a/core/events/events_guild_webhooks_update.go +++ /dev/null @@ -1,25 +0,0 @@ -package events - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" -) - -type WebhooksUpdateEvent struct { - *GenericEvent - GuildId snowflake.Snowflake - ChannelID snowflake.Snowflake -} - -// Guild returns the Guild the webhook was updated in. -// This will only check cached guilds! -func (e *WebhooksUpdateEvent) Guild() *core.Guild { - return e.Bot().Caches.Guilds().Get(e.GuildId) -} - -func (e *WebhooksUpdateEvent) Channel() core.GuildMessageChannel { - if ch := e.Bot().Caches.Channels().Get(e.ChannelID); ch != nil { - return ch.(core.GuildMessageChannel) - } - return nil -} diff --git a/core/events/events_interactions.go b/core/events/events_interactions.go deleted file mode 100644 index d802e9cd..00000000 --- a/core/events/events_interactions.go +++ /dev/null @@ -1,28 +0,0 @@ -package events - -import "github.com/DisgoOrg/disgo/core" - -type InteractionEvent struct { - *GenericEvent - core.Interaction -} - -type ApplicationCommandInteractionEvent struct { - *GenericEvent - *core.ApplicationCommandInteraction -} - -type ComponentInteractionEvent struct { - *GenericEvent - *core.ComponentInteraction -} - -type AutocompleteInteractionEvent struct { - *GenericEvent - *core.AutocompleteInteraction -} - -type ModalSubmitInteractionEvent struct { - *GenericEvent - *core.ModalSubmitInteraction -} diff --git a/core/events/events_message.go b/core/events/events_message.go deleted file mode 100644 index ace2387f..00000000 --- a/core/events/events_message.go +++ /dev/null @@ -1,47 +0,0 @@ -package events - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" -) - -// GenericMessageEvent generic core.Message event -type GenericMessageEvent struct { - *GenericEvent - MessageID snowflake.Snowflake - Message *core.Message - ChannelID snowflake.Snowflake - GuildID *snowflake.Snowflake -} - -// Channel returns the core.Channel where the GenericMessageEvent happened -func (e *GenericMessageEvent) Channel() core.MessageChannel { - if ch := e.Bot().Caches.Channels().Get(e.ChannelID); ch != nil { - return ch.(core.MessageChannel) - } - return nil -} - -// Guild returns the core.Guild where the GenericMessageEvent happened or nil if it happened in DMs -func (e *GenericMessageEvent) Guild() *core.Guild { - if e.GuildID == nil { - return nil - } - return e.Bot().Caches.Guilds().Get(*e.GuildID) -} - -// MessageCreateEvent indicates that a core.Message got received -type MessageCreateEvent struct { - *GenericMessageEvent -} - -// MessageUpdateEvent indicates that a core.Message got update -type MessageUpdateEvent struct { - *GenericMessageEvent - OldMessage *core.Message -} - -// MessageDeleteEvent indicates that a core.Message got deleted -type MessageDeleteEvent struct { - *GenericMessageEvent -} diff --git a/core/events/events_message_reaction.go b/core/events/events_message_reaction.go deleted file mode 100644 index 7cc99588..00000000 --- a/core/events/events_message_reaction.go +++ /dev/null @@ -1,49 +0,0 @@ -package events - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" -) - -// GenericReactionEvent is called upon receiving MessageReactionAddEvent or MessageReactionRemoveEvent -type GenericReactionEvent struct { - *GenericEvent - UserID snowflake.Snowflake - ChannelID snowflake.Snowflake - MessageID snowflake.Snowflake - GuildID *snowflake.Snowflake - Emoji discord.ReactionEmoji -} - -func (e *GenericReactionEvent) User() *core.User { - return e.Bot().Caches.Users().Get(e.UserID) -} - -// MessageReactionAddEvent indicates that a core.User added a discord.MessageReaction to a core.Message in a core.Channel(this+++ requires the discord.GatewayIntentGuildMessageReactions and/or discord.GatewayIntentDirectMessageReactions) -type MessageReactionAddEvent struct { - *GenericReactionEvent - Member *core.Member -} - -// MessageReactionRemoveEvent indicates that a core.User removed a discord.MessageReaction from a core.Message in a core.GetChannel(requires the discord.GatewayIntentGuildMessageReactions and/or discord.GatewayIntentDirectMessageReactions) -type MessageReactionRemoveEvent struct { - *GenericReactionEvent -} - -// MessageReactionRemoveEmojiEvent indicates someone removed all discord.MessageReaction of a specific core.Emoji from a core.Message in a core.Channel(requires the discord.GatewayIntentGuildMessageReactions and/or discord.GatewayIntentDirectMessageReactions) -type MessageReactionRemoveEmojiEvent struct { - *GenericEvent - ChannelID snowflake.Snowflake - MessageID snowflake.Snowflake - GuildID *snowflake.Snowflake - Emoji discord.ReactionEmoji -} - -// MessageReactionRemoveAllEvent indicates someone removed all discord.MessageReaction(s) from a core.Message in a core.Channel(requires the discord.GatewayIntentGuildMessageReactions and/or discord.GatewayIntentDirectMessageReactions) -type MessageReactionRemoveAllEvent struct { - *GenericEvent - ChannelID snowflake.Snowflake - MessageID snowflake.Snowflake - GuildID *snowflake.Snowflake -} diff --git a/core/events/events_raw_event.go b/core/events/events_raw_event.go deleted file mode 100644 index 454c32aa..00000000 --- a/core/events/events_raw_event.go +++ /dev/null @@ -1,37 +0,0 @@ -package events - -import ( - "bytes" - "io" - "io/ioutil" - - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/json" - - "github.com/DisgoOrg/disgo/discord" -) - -func HandleRawEvent(bot *core.Bot, gatewayEventType discord.GatewayEventType, sequenceNumber discord.GatewaySequence, reader io.Reader) io.Reader { - if bot.EventManager.Config().RawEventsEnabled { - var buf bytes.Buffer - data, err := ioutil.ReadAll(io.TeeReader(reader, &buf)) - if err != nil { - bot.Logger.Error("error reading raw payload from event") - } - bot.EventManager.Dispatch(&RawEvent{ - GenericEvent: NewGenericEvent(bot, sequenceNumber), - Type: gatewayEventType, - RawPayload: data, - }) - - return &buf - } - return reader -} - -// RawEvent is called for any discord.GatewayEventType we receive if enabled in the bot.Config -type RawEvent struct { - *GenericEvent - Type discord.GatewayEventType - RawPayload json.RawMessage -} diff --git a/core/events/events_role.go b/core/events/events_role.go deleted file mode 100644 index 7464eeb9..00000000 --- a/core/events/events_role.go +++ /dev/null @@ -1,30 +0,0 @@ -package events - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" -) - -// GenericRoleEvent generic core.Role event -type GenericRoleEvent struct { - *GenericEvent - GuildID snowflake.Snowflake - RoleID snowflake.Snowflake - Role *core.Role -} - -// RoleCreateEvent indicates that a core.Role got created -type RoleCreateEvent struct { - *GenericRoleEvent -} - -// RoleUpdateEvent indicates that a core.Role got updated -type RoleUpdateEvent struct { - *GenericRoleEvent - OldRole *core.Role -} - -// RoleDeleteEvent indicates that a core.Role got deleted -type RoleDeleteEvent struct { - *GenericRoleEvent -} diff --git a/core/events/events_self_update.go b/core/events/events_self_update.go deleted file mode 100644 index 33eff3d5..00000000 --- a/core/events/events_self_update.go +++ /dev/null @@ -1,10 +0,0 @@ -package events - -import "github.com/DisgoOrg/disgo/core" - -// SelfUpdateEvent is called when something about this core.User updates -type SelfUpdateEvent struct { - *GenericEvent - SelfUser *core.SelfUser - OldSelfUser *core.SelfUser -} diff --git a/core/events/events_user.go b/core/events/events_user.go deleted file mode 100644 index 2357f7a8..00000000 --- a/core/events/events_user.go +++ /dev/null @@ -1,38 +0,0 @@ -package events - -import ( - "time" - - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" -) - -// GenericUserEvent is called upon receiving UserUpdateEvent or UserTypingStartEvent -type GenericUserEvent struct { - *GenericEvent - UserID snowflake.Snowflake - User *core.User -} - -// UserUpdateEvent indicates that a core.User updated -type UserUpdateEvent struct { - *GenericUserEvent - OldUser *core.User -} - -// UserTypingStartEvent indicates that a core.User started typing in a core.DMChannel or core.MessageChanel(requires the discord.GatewayIntentDirectMessageTyping and/or discord.GatewayIntentGuildMessageTyping) -type UserTypingStartEvent struct { - *GenericEvent - ChannelID snowflake.Snowflake - GuildID *snowflake.Snowflake - UserID snowflake.Snowflake - Timestamp time.Time -} - -// Channel returns the core.GetChannel the core.User started typing in -func (e *UserTypingStartEvent) Channel() core.MessageChannel { - if ch := e.Bot().Caches.Channels().Get(e.ChannelID); ch != nil { - return ch.(core.MessageChannel) - } - return nil -} diff --git a/core/events/events_user_status.go b/core/events/events_user_status.go deleted file mode 100644 index 305a6039..00000000 --- a/core/events/events_user_status.go +++ /dev/null @@ -1,35 +0,0 @@ -package events - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" -) - -// UserStatusUpdateEvent generic Status event -type UserStatusUpdateEvent struct { - *GenericEvent - UserID snowflake.Snowflake - OldStatus discord.OnlineStatus - Status discord.OnlineStatus -} - -// User returns the User that changed their Status. -// This will only check cached users! -func (g *UserStatusUpdateEvent) User() *core.User { - return g.Bot().Caches.Users().Get(g.UserID) -} - -// UserClientStatusUpdateEvent generic client-specific Status event -type UserClientStatusUpdateEvent struct { - *GenericEvent - UserID snowflake.Snowflake - OldClientStatus *discord.ClientStatus - ClientStatus discord.ClientStatus -} - -// User returns the User that changed their Status. -// This will only check cached users! -func (g *UserClientStatusUpdateEvent) User() *core.User { - return g.Bot().Caches.Users().Get(g.UserID) -} diff --git a/core/guild.go b/core/guild.go deleted file mode 100644 index f405e54c..00000000 --- a/core/guild.go +++ /dev/null @@ -1,462 +0,0 @@ -package core - -import ( - "context" - - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" -) - -type Guild struct { - discord.Guild - Bot *Bot -} - -// Update updates this Guild -func (g *Guild) Update(updateGuild discord.GuildUpdate, opts ...rest.RequestOpt) (*Guild, error) { - guild, err := g.Bot.RestServices.GuildService().UpdateGuild(g.ID, updateGuild, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateGuild(*guild, CacheStrategyNoWs), nil -} - -// Delete deletes the this Guild -func (g *Guild) Delete(opts ...rest.RequestOpt) error { - return g.Bot.RestServices.GuildService().DeleteGuild(g.ID, opts...) -} - -// CreateChannel creates a new GuildChannel in this Guild -func (g *Guild) CreateChannel(guildChannelCreate discord.GuildChannelCreate, opts ...rest.RequestOpt) (GuildChannel, error) { - channel, err := g.Bot.RestServices.GuildService().CreateChannel(g.ID, guildChannelCreate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateChannel(channel, CacheStrategyNoWs).(GuildChannel), nil -} - -// UpdateChannel updates a GuildChannel in this Guild -func (g *Guild) UpdateChannel(channelID snowflake.Snowflake, guildChannelUpdate discord.GuildChannelUpdate, opts ...rest.RequestOpt) (GuildChannel, error) { - channel, err := g.Bot.RestServices.ChannelService().UpdateChannel(channelID, guildChannelUpdate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateChannel(channel, CacheStrategyNoWs).(GuildChannel), nil -} - -// DeleteChannel deletes a GuildChannel in this Guild -func (g *Guild) DeleteChannel(channelID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return g.Bot.RestServices.ChannelService().DeleteChannel(channelID, opts...) -} - -// PublicRole returns the @everyone Role -func (g *Guild) PublicRole() *Role { - return g.Bot.Caches.Roles().Get(g.ID, g.ID) -} - -// CreateRole creates a new Role with the properties provided in discord.RoleCreate -func (g *Guild) CreateRole(roleCreate discord.RoleCreate, opts ...rest.RequestOpt) (*Role, error) { - role, err := g.Bot.RestServices.GuildService().CreateRole(g.ID, roleCreate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateRole(g.ID, *role, CacheStrategyNoWs), nil -} - -// UpdateRole updates a Role with the properties provided in discord.RoleUpdate -func (g *Guild) UpdateRole(roleID snowflake.Snowflake, roleUpdate discord.RoleUpdate, opts ...rest.RequestOpt) (*Role, error) { - role, err := g.Bot.RestServices.GuildService().UpdateRole(g.ID, roleID, roleUpdate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateRole(g.ID, *role, CacheStrategyNoWs), nil -} - -// DeleteRole deletes a Role -func (g *Guild) DeleteRole(roleID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return g.Bot.RestServices.GuildService().DeleteRole(g.ID, roleID, opts...) -} - -// Roles returns all Role(s) in this Guild -func (g *Guild) Roles() []*Role { - return g.Bot.Caches.Roles().GuildAll(g.ID) -} - -// RoleCache returns all Role(s) in this Guild -func (g *Guild) RoleCache() map[snowflake.Snowflake]*Role { - return g.Bot.Caches.Roles().GuildCache(g.ID) -} - -func (g *Guild) CreateGuildScheduledEvent(guildScheduledEventCreate discord.GuildScheduledEventCreate, opts ...rest.RequestOpt) (*GuildScheduledEvent, error) { - guildScheduledEvent, err := g.Bot.RestServices.GuildScheduledEventService().CreateGuildScheduledEvent(g.ID, guildScheduledEventCreate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateGuildScheduledEvent(*guildScheduledEvent, CacheStrategyNoWs), nil -} - -func (g *Guild) UpdateGuildScheduledEvent(guildScheduledEventID snowflake.Snowflake, guildScheduledEventUpdate discord.GuildScheduledEventUpdate, opts ...rest.RequestOpt) (*GuildScheduledEvent, error) { - guildScheduledEvent, err := g.Bot.RestServices.GuildScheduledEventService().UpdateGuildScheduledEvent(g.ID, guildScheduledEventID, guildScheduledEventUpdate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateGuildScheduledEvent(*guildScheduledEvent, CacheStrategyNoWs), nil -} - -func (g *Guild) DeleteGuildScheduledEvent(guildScheduledEventID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return g.Bot.RestServices.GuildScheduledEventService().DeleteGuildScheduledEvent(g.ID, guildScheduledEventID, opts...) -} - -func (g *Guild) GetGuildScheduledEventUsers(guildScheduledEventID snowflake.Snowflake, limit int, withMember bool, before snowflake.Snowflake, after snowflake.Snowflake, opts ...rest.RequestOpt) ([]*GuildScheduledEventUser, error) { - users, err := g.Bot.RestServices.GuildScheduledEventService().GetGuildScheduledEventUsers(g.ID, guildScheduledEventID, limit, withMember, before, after, opts...) - if err != nil { - return nil, err - } - eventUsers := make([]*GuildScheduledEventUser, len(users)) - for i := range users { - eventUsers[i] = g.Bot.EntityBuilder.CreateGuildScheduledEventUser(g.ID, users[i], CacheStrategyNoWs) - } - return eventUsers, nil -} - -// CreateEmoji creates a new Emoji with the properties provided in discord.EmojiCreate -func (g *Guild) CreateEmoji(emojiCreate discord.EmojiCreate, opts ...rest.RequestOpt) (*Emoji, error) { - emoji, err := g.Bot.RestServices.EmojiService().CreateEmoji(g.ID, emojiCreate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateEmoji(g.ID, *emoji, CacheStrategyNoWs), nil -} - -// UpdateEmoji creates an Emoji with the properties provided in discord.EmojiUpdate -func (g *Guild) UpdateEmoji(emojiID snowflake.Snowflake, emojiUpdate discord.EmojiUpdate, opts ...rest.RequestOpt) (*Emoji, error) { - emoji, err := g.Bot.RestServices.EmojiService().UpdateEmoji(g.ID, emojiID, emojiUpdate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateEmoji(g.ID, *emoji, CacheStrategyNoWs), nil -} - -// DeleteEmoji deletes an Emoji -func (g *Guild) DeleteEmoji(emojiID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return g.Bot.RestServices.EmojiService().DeleteEmoji(g.ID, emojiID, opts...) -} - -// CreateSticker creates a new Sticker with the properties provided in discord.StickerCreate -func (g *Guild) CreateSticker(stickerCreate discord.StickerCreate, opts ...rest.RequestOpt) (*Sticker, error) { - sticker, err := g.Bot.RestServices.StickerService().CreateSticker(g.ID, stickerCreate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateSticker(*sticker, CacheStrategyNoWs), nil -} - -// UpdateSticker updates a Sticker with the properties provided in discord.StickerCreate -func (g *Guild) UpdateSticker(stickerID snowflake.Snowflake, stickerUpdate discord.StickerUpdate, opts ...rest.RequestOpt) (*Sticker, error) { - sticker, err := g.Bot.RestServices.StickerService().UpdateSticker(g.ID, stickerID, stickerUpdate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateSticker(*sticker, CacheStrategyNoWs), nil -} - -// DeleteSticker deletes a Sticker -func (g *Guild) DeleteSticker(stickerID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return g.Bot.RestServices.StickerService().DeleteSticker(g.ID, stickerID, opts...) -} - -// SelfMember returns the Member for the current logged-in User for this Guild -func (g *Guild) SelfMember() *Member { - return g.Bot.Caches.Members().Get(g.ID, g.Bot.ClientID) -} - -// Leave leaves this Guild -func (g *Guild) Leave(opts ...rest.RequestOpt) error { - return g.Bot.RestServices.UserService().LeaveGuild(g.ID, opts...) -} - -// Disconnect sends a GatewayCommand to disconnect from this Guild -func (g *Guild) Disconnect(ctx context.Context) error { - return g.Bot.AudioController.Disconnect(ctx, g.ID) -} - -func (g *Guild) RequestMembers(userIDs ...snowflake.Snowflake) ([]*Member, error) { - return g.Bot.MemberChunkingManager.RequestMembers(g.ID, userIDs...) -} - -func (g *Guild) RequestMembersWithQuery(query string, limit int) ([]*Member, error) { - return g.Bot.MemberChunkingManager.RequestMembersWithQuery(g.ID, query, limit) -} - -func (g *Guild) RequestMembersWithFilter(memberFilterFunc func(member *Member) bool) ([]*Member, error) { - return g.Bot.MemberChunkingManager.RequestMembersWithFilter(g.ID, memberFilterFunc) -} - -func (g *Guild) RequestMembersCtx(ctx context.Context, userIDs ...snowflake.Snowflake) ([]*Member, error) { - return g.Bot.MemberChunkingManager.RequestMembersCtx(ctx, g.ID, userIDs...) -} - -func (g *Guild) RequestMembersWithQueryCtx(ctx context.Context, query string, limit int) ([]*Member, error) { - return g.Bot.MemberChunkingManager.RequestMembersWithQueryCtx(ctx, g.ID, query, limit) -} - -func (g *Guild) RequestMembersWithFilterCtx(ctx context.Context, memberFilterFunc func(member *Member) bool) ([]*Member, error) { - return g.Bot.MemberChunkingManager.RequestMembersWithFilterCtx(ctx, g.ID, memberFilterFunc) -} - -func (g *Guild) RequestMembersChan(userIDs []snowflake.Snowflake) (<-chan *Member, func(), error) { - return g.Bot.MemberChunkingManager.RequestMembersChan(g.ID, userIDs...) -} - -func (g *Guild) RequestMembersWithQueryChan(query string, limit int) (<-chan *Member, func(), error) { - return g.Bot.MemberChunkingManager.RequestMembersWithQueryChan(g.ID, query, limit) -} - -func (g *Guild) RequestMembersWithFilterChan(memberFilterFunc func(member *Member) bool) (<-chan *Member, func(), error) { - return g.Bot.MemberChunkingManager.RequestMembersWithFilterChan(g.ID, memberFilterFunc) -} - -// GetMember returns the specific Member for this Guild -func (g *Guild) GetMember(userID snowflake.Snowflake) *Member { - return g.Bot.Caches.Members().Get(g.ID, userID) -} - -// AddMember adds a member to the Guild with the oauth2 access token -func (g *Guild) AddMember(userID snowflake.Snowflake, memberAdd discord.MemberAdd, opts ...rest.RequestOpt) (*Member, error) { - member, err := g.Bot.RestServices.GuildService().AddMember(g.ID, userID, memberAdd, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateMember(g.ID, *member, CacheStrategyNoWs), nil -} - -// UpdateMember updates an existing member of the Guild -func (g *Guild) UpdateMember(userID snowflake.Snowflake, memberUpdate discord.MemberUpdate, opts ...rest.RequestOpt) (*Member, error) { - member, err := g.Bot.RestServices.GuildService().UpdateMember(g.ID, userID, memberUpdate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateMember(g.ID, *member, CacheStrategyNoWs), nil -} - -// KickMember kicks an existing member from the Guild -func (g *Guild) KickMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return g.Bot.RestServices.GuildService().RemoveMember(g.ID, userID, opts...) -} - -// BanMember bans a Member from the Guild -func (g *Guild) BanMember(userID snowflake.Snowflake, deleteMessageDays int, opts ...rest.RequestOpt) error { - return g.Bot.RestServices.GuildService().AddBan(g.ID, userID, deleteMessageDays, opts...) -} - -// UnbanMember unbans a Member from the Guild -func (g *Guild) UnbanMember(userID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return g.Bot.RestServices.GuildService().DeleteBan(g.ID, userID, opts...) -} - -// GetBans fetches all bans for this Guild -func (g *Guild) GetBans(opts ...rest.RequestOpt) ([]*Ban, error) { - guildBans, err := g.Bot.RestServices.GuildService().GetBans(g.ID, opts...) - if err != nil { - return nil, err - } - bans := make([]*Ban, len(guildBans)) - for i, guildBan := range guildBans { - bans[i] = g.Bot.EntityBuilder.CreateBan(g.ID, guildBan, CacheStrategyNoWs) - } - return bans, nil -} - -// GetBan fetches a ban for a User for this Guild -func (g *Guild) GetBan(userID snowflake.Snowflake, opts ...rest.RequestOpt) (*Ban, error) { - ban, err := g.Bot.RestServices.GuildService().GetBan(g.ID, userID, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateBan(g.ID, *ban, CacheStrategyNoWs), nil -} - -// IconURL returns the Icon of a Guild -func (g *Guild) IconURL(size int) *string { - return discord.FormatAssetURL(route.GuildIcon, g.ID, g.Icon, size) -} - -// GetAuditLogs gets AuditLog(s) for this Guild -func (g *Guild) GetAuditLogs(filterOptions AuditLogFilterOptions, opts ...rest.RequestOpt) (*AuditLog, error) { - auditLog, err := g.Bot.RestServices.AuditLogService().GetAuditLog(g.ID, filterOptions.UserID, filterOptions.ActionType, filterOptions.Before, filterOptions.Limit, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateAuditLog(g.ID, *auditLog, filterOptions, CacheStrategyNoWs), nil -} - -// GetIntegrations gets all Integration(s) from the Guild. Requires PermissionManageServer -func (g *Guild) GetIntegrations(opts ...rest.RequestOpt) ([]Integration, error) { - guildIntegrations, err := g.Bot.RestServices.GuildService().GetIntegrations(g.ID, opts...) - if err != nil { - return nil, err - } - integrations := make([]Integration, len(guildIntegrations)) - for i := range guildIntegrations { - integrations[i] = g.Bot.EntityBuilder.CreateIntegration(g.ID, guildIntegrations[i], CacheStrategyNoWs) - } - return integrations, nil -} - -// DeleteIntegration deletes a specific Integration from the Guild. Requires PermissionManageServer -func (g *Guild) DeleteIntegration(integrationID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return g.Bot.RestServices.GuildService().DeleteIntegration(g.ID, integrationID, opts...) -} - -// GetGuildCommand fetches a specific Guild discord.ApplicationCommand -func (g *Guild) GetGuildCommand(commandID snowflake.Snowflake, opts ...rest.RequestOpt) (ApplicationCommand, error) { - command, err := g.Bot.RestServices.ApplicationService().GetGuildCommand(g.Bot.ApplicationID, g.ID, commandID, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateApplicationCommand(command), nil -} - -// GetGuildCommands fetches all Guild discord.ApplicationCommand(s) -func (g *Guild) GetGuildCommands(opts ...rest.RequestOpt) ([]ApplicationCommand, error) { - cmds, err := g.Bot.RestServices.ApplicationService().GetGuildCommands(g.Bot.ApplicationID, g.ID, opts...) - if err != nil { - return nil, err - } - commands := make([]ApplicationCommand, len(cmds)) - for i, command := range cmds { - commands[i] = g.Bot.EntityBuilder.CreateApplicationCommand(command) - } - return commands, nil -} - -// CreateGuildCommand creates a new Guild discord.ApplicationCommand -func (g *Guild) CreateGuildCommand(commandCreate discord.ApplicationCommandCreate, opts ...rest.RequestOpt) (ApplicationCommand, error) { - command, err := g.Bot.RestServices.ApplicationService().CreateGuildCommand(g.Bot.ApplicationID, g.ID, commandCreate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateApplicationCommand(command), nil -} - -// UpdateGuildCommand edits a specific Guild discord.ApplicationCommand -func (g *Guild) UpdateGuildCommand(commandID snowflake.Snowflake, commandUpdate discord.ApplicationCommandUpdate, opts ...rest.RequestOpt) (ApplicationCommand, error) { - command, err := g.Bot.RestServices.ApplicationService().UpdateGuildCommand(g.Bot.ApplicationID, g.ID, commandID, commandUpdate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateApplicationCommand(command), nil -} - -// DeleteGuildCommand creates a new Guild discord.ApplicationCommand -func (g *Guild) DeleteGuildCommand(commandID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return g.Bot.RestServices.ApplicationService().DeleteGuildCommand(g.Bot.ApplicationID, g.ID, commandID, opts...) -} - -// SetGuildCommands overrides all Guild discord.ApplicationCommand(s) -func (g *Guild) SetGuildCommands(commandCreates []discord.ApplicationCommandCreate, opts ...rest.RequestOpt) ([]ApplicationCommand, error) { - cmds, err := g.Bot.RestServices.ApplicationService().SetGuildCommands(g.Bot.ApplicationID, g.ID, commandCreates, opts...) - if err != nil { - return nil, err - } - commands := make([]ApplicationCommand, len(cmds)) - for i, command := range cmds { - commands[i] = g.Bot.EntityBuilder.CreateApplicationCommand(command) - } - return commands, nil -} - -// GetGuildCommandsPermissions returns the core.ApplicationCommandPermissions for a all discord.ApplicationCommand(s) in an core.Guild -func (g *Guild) GetGuildCommandsPermissions(opts ...rest.RequestOpt) ([]*ApplicationCommandPermissions, error) { - perms, err := g.Bot.RestServices.ApplicationService().GetGuildCommandsPermissions(g.Bot.ApplicationID, g.ID, opts...) - if err != nil { - return nil, err - } - permissions := make([]*ApplicationCommandPermissions, len(perms)) - for i, permission := range perms { - permissions[i] = g.Bot.EntityBuilder.CreateApplicationCommandPermissions(permission) - } - return permissions, nil -} - -// GetGuildCommandPermissions returns the core.ApplicationCommandPermissions for a specific discord.ApplicationCommand in an core.Guild -func (g *Guild) GetGuildCommandPermissions(commandID snowflake.Snowflake, opts ...rest.RequestOpt) (*ApplicationCommandPermissions, error) { - permissions, err := g.Bot.RestServices.ApplicationService().GetGuildCommandPermissions(g.Bot.ApplicationID, g.ID, commandID, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateApplicationCommandPermissions(*permissions), nil -} - -// SetGuildCommandsPermissions sets the discord.ApplicationCommandPermissions for all discord.ApplicationCommand(s) -func (g *Guild) SetGuildCommandsPermissions(commandPermissions []discord.ApplicationCommandPermissionsSet, opts ...rest.RequestOpt) ([]*ApplicationCommandPermissions, error) { - perms, err := g.Bot.RestServices.ApplicationService().SetGuildCommandsPermissions(g.Bot.ApplicationID, g.ID, commandPermissions, opts...) - if err != nil { - return nil, err - } - permissions := make([]*ApplicationCommandPermissions, len(perms)) - for i, permission := range perms { - permissions[i] = g.Bot.EntityBuilder.CreateApplicationCommandPermissions(permission) - } - return permissions, nil -} - -// SetGuildCommandPermissions sets the core.ApplicationCommandPermissions for a specific discord.ApplicationCommand -func (g *Guild) SetGuildCommandPermissions(commandID snowflake.Snowflake, permissions []discord.ApplicationCommandPermission, opts ...rest.RequestOpt) (*ApplicationCommandPermissions, error) { - perms, err := g.Bot.RestServices.ApplicationService().SetGuildCommandPermissions(g.Bot.ApplicationID, g.ID, commandID, permissions, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateApplicationCommandPermissions(*perms), nil -} - -// GetTemplates gets a specific GuildTemplate -func (g *Guild) GetTemplates(opts ...rest.RequestOpt) ([]*GuildTemplate, error) { - guildTemplates, err := g.Bot.RestServices.GuildTemplateService().GetGuildTemplates(g.ID, opts...) - if err != nil { - return nil, err - } - templates := make([]*GuildTemplate, len(guildTemplates)) - for i, guildTemplate := range guildTemplates { - templates[i] = g.Bot.EntityBuilder.CreateGuildTemplate(guildTemplate, CacheStrategyNoWs) - } - return templates, nil -} - -// CreateTemplate creates a new GuildTemplate -func (g *Guild) CreateTemplate(guildTemplateCreate discord.GuildTemplateCreate, opts ...rest.RequestOpt) (*GuildTemplate, error) { - guildTemplate, err := g.Bot.RestServices.GuildTemplateService().CreateGuildTemplate(g.ID, guildTemplateCreate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateGuildTemplate(*guildTemplate, CacheStrategyNoWs), nil -} - -// SyncTemplate syncs the current Guild status to an existing GuildTemplate -func (g *Guild) SyncTemplate(templateCode string, opts ...rest.RequestOpt) (*GuildTemplate, error) { - guildTemplate, err := g.Bot.RestServices.GuildTemplateService().SyncGuildTemplate(g.ID, templateCode, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateGuildTemplate(*guildTemplate, CacheStrategyNoWs), nil -} - -// UpdateTemplate updates a specific GuildTemplate -func (g *Guild) UpdateTemplate(templateCode string, guildTemplateUpdate discord.GuildTemplateUpdate, opts ...rest.RequestOpt) (*GuildTemplate, error) { - guildTemplate, err := g.Bot.RestServices.GuildTemplateService().UpdateGuildTemplate(g.ID, templateCode, guildTemplateUpdate, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateGuildTemplate(*guildTemplate, CacheStrategyNoWs), nil -} - -// DeleteTemplate deletes a specific GuildTemplate -func (g *Guild) DeleteTemplate(templateCode string, opts ...rest.RequestOpt) (*GuildTemplate, error) { - guildTemplate, err := g.Bot.RestServices.GuildTemplateService().DeleteGuildTemplate(g.ID, templateCode, opts...) - if err != nil { - return nil, err - } - return g.Bot.EntityBuilder.CreateGuildTemplate(*guildTemplate, CacheStrategyNoWs), nil -} diff --git a/core/guild_scheduled_event.go b/core/guild_scheduled_event.go deleted file mode 100644 index f4bb305c..00000000 --- a/core/guild_scheduled_event.go +++ /dev/null @@ -1,94 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/snowflake" -) - -type GuildScheduledEvent struct { - discord.GuildScheduledEvent - Creator *User - Bot *Bot -} - -func (e *GuildScheduledEvent) Update(guildScheduledEventUpdate discord.GuildScheduledEventUpdate, opts ...rest.RequestOpt) (*GuildScheduledEvent, error) { - guildScheduledEvent, err := e.Bot.RestServices.GuildScheduledEventService().UpdateGuildScheduledEvent(e.GuildID, e.ID, guildScheduledEventUpdate, opts...) - if err != nil { - return nil, err - } - return e.Bot.EntityBuilder.CreateGuildScheduledEvent(*guildScheduledEvent, CacheStrategyNoWs), nil -} - -func (e *GuildScheduledEvent) Delete(opts ...rest.RequestOpt) error { - return e.Bot.RestServices.GuildScheduledEventService().DeleteGuildScheduledEvent(e.GuildID, e.ID, opts...) -} - -func (e *GuildScheduledEvent) AudioChannel() GuildAudioChannel { - if e.EntityType != discord.ScheduledEventEntityTypeVoice && e.EntityType != discord.ScheduledEventEntityTypeStageInstance { - return nil - } - if e.ChannelID == nil { - return nil - } - if ch := e.Bot.Caches.Channels().Get(*e.ChannelID); ch != nil { - return ch.(GuildAudioChannel) - } - return nil -} - -func (e *GuildScheduledEvent) VoiceChannelEntity() *GuildVoiceChannel { - if e.EntityType != discord.ScheduledEventEntityTypeVoice { - return nil - } - if e.EntityID == nil { - return nil - } - if ch := e.Bot.Caches.Channels().Get(*e.EntityID); ch != nil { - return ch.(*GuildVoiceChannel) - } - return nil -} - -func (e *GuildScheduledEvent) StageInstanceEntity() *StageInstance { - if e.EntityType != discord.ScheduledEventEntityTypeStageInstance { - return nil - } - if e.EntityID == nil { - return nil - } - return e.Bot.Caches.StageInstances().Get(*e.EntityID) -} - -func (e *GuildScheduledEvent) Guild() *Guild { - return e.Bot.Caches.Guilds().Get(e.GuildID) -} - -func (e *GuildScheduledEvent) Channel() GuildChannel { - if e.ChannelID == nil { - return nil - } - if channel := e.Bot.Caches.Channels().Get(*e.ChannelID); channel != nil { - return channel.(GuildChannel) - } - return nil -} - -func (e *GuildScheduledEvent) GetUsers(limit int, withMember bool, before snowflake.Snowflake, after snowflake.Snowflake, opts ...rest.RequestOpt) ([]*GuildScheduledEventUser, error) { - users, err := e.Bot.RestServices.GuildScheduledEventService().GetGuildScheduledEventUsers(e.GuildID, e.ID, limit, withMember, before, after, opts...) - if err != nil { - return nil, err - } - eventUsers := make([]*GuildScheduledEventUser, len(users)) - for i := range users { - eventUsers[i] = e.Bot.EntityBuilder.CreateGuildScheduledEventUser(e.GuildID, users[i], CacheStrategyNoWs) - } - return eventUsers, nil -} - -type GuildScheduledEventUser struct { - discord.GuildScheduledEventUser - User *User - Member *Member - Bot *Bot -} diff --git a/core/guild_template.go b/core/guild_template.go deleted file mode 100644 index 1508c95b..00000000 --- a/core/guild_template.go +++ /dev/null @@ -1,54 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" -) - -type GuildTemplate struct { - discord.GuildTemplate - Bot *Bot - Creator *User -} - -// Guild returns the Guild this GuildTemplate is for. -// This will only check cached guilds! -func (t *GuildTemplate) Guild() *Guild { - return t.Bot.Caches.Guilds().Get(t.GuildID) -} - -// Update updates the GuildTemplate with the provided discord.UpdateGuildTemplate -func (t *GuildTemplate) Update(guildTemplateUpdate discord.GuildTemplateUpdate, opts ...rest.RequestOpt) (*GuildTemplate, error) { - guildTemplate, err := t.Bot.RestServices.GuildTemplateService().UpdateGuildTemplate(t.GuildID, t.Code, guildTemplateUpdate, opts...) - if err != nil { - return nil, err - } - return t.Bot.EntityBuilder.CreateGuildTemplate(*guildTemplate, CacheStrategyNoWs), nil -} - -// Sync updates the GuildTemplate with the provided discord.UpdateGuildTemplate -func (t *GuildTemplate) Sync(opts ...rest.RequestOpt) (*GuildTemplate, error) { - guildTemplate, err := t.Bot.RestServices.GuildTemplateService().SyncGuildTemplate(t.GuildID, t.Code, opts...) - if err != nil { - return nil, err - } - return t.Bot.EntityBuilder.CreateGuildTemplate(*guildTemplate, CacheStrategyNoWs), nil -} - -// Delete deletes the GuildTemplate -func (t *GuildTemplate) Delete(opts ...rest.RequestOpt) (*GuildTemplate, error) { - guildTemplate, err := t.Bot.RestServices.GuildTemplateService().DeleteGuildTemplate(t.GuildID, t.Code, opts...) - if err != nil { - return nil, err - } - return t.Bot.EntityBuilder.CreateGuildTemplate(*guildTemplate, CacheStrategyNoWs), nil -} - -// CreateGuild creates a Guild from this discord.GuildTemplate -func (t *GuildTemplate) CreateGuild(createGuildFromTemplate discord.GuildFromTemplateCreate, opts ...rest.RequestOpt) (*Guild, error) { - guild, err := t.Bot.RestServices.GuildTemplateService().CreateGuildFromTemplate(t.Code, createGuildFromTemplate, opts...) - if err != nil { - return nil, err - } - return t.Bot.EntityBuilder.CreateGuild(*guild, CacheStrategyNoWs), nil -} diff --git a/core/handlers/gateway_handler_channel_create.go b/core/handlers/gateway_handler_channel_create.go deleted file mode 100644 index 4bfba6e4..00000000 --- a/core/handlers/gateway_handler_channel_create.go +++ /dev/null @@ -1,52 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerChannelCreate handles core.GatewayEventChannelCreate -type gatewayHandlerChannelCreate struct{} - -// EventType returns the core.GatewayGatewayEventType -func (h *gatewayHandlerChannelCreate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeChannelCreate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerChannelCreate) New() interface{} { - return &discord.UnmarshalChannel{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerChannelCreate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - channel := v.(*discord.UnmarshalChannel).Channel - - if ch, ok := channel.(discord.GuildChannel); ok { - var guildChannel core.GuildChannel - if c, ok := bot.EntityBuilder.CreateChannel(channel, core.CacheStrategyYes).(core.GuildChannel); ok { - guildChannel = c - } - bot.EventManager.Dispatch(&events.GuildChannelCreateEvent{ - GenericGuildChannelEvent: &events.GenericGuildChannelEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - ChannelID: channel.ID(), - Channel: guildChannel, - GuildID: ch.GuildID(), - }, - }) - } else { - var dmChannel *core.DMChannel - if c, ok := bot.EntityBuilder.CreateChannel(channel, core.CacheStrategyYes).(*core.DMChannel); ok { - dmChannel = c - } - bot.EventManager.Dispatch(&events.DMChannelCreateEvent{ - GenericDMChannelEvent: &events.GenericDMChannelEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - ChannelID: channel.ID(), - Channel: dmChannel, - }, - }) - } -} diff --git a/core/handlers/gateway_handler_channel_delete.go b/core/handlers/gateway_handler_channel_delete.go deleted file mode 100644 index 3e746ca8..00000000 --- a/core/handlers/gateway_handler_channel_delete.go +++ /dev/null @@ -1,48 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerChannelDelete handles discord.GatewayEventTypeChannelDelete -type gatewayHandlerChannelDelete struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerChannelDelete) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeChannelDelete -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerChannelDelete) New() interface{} { - return &discord.UnmarshalChannel{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerChannelDelete) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := v.(*discord.UnmarshalChannel).Channel - - bot.Caches.Channels().Remove(payload.ID()) - bot.Caches.Members().RemoveAll(payload.ID()) - channel := bot.EntityBuilder.CreateChannel(payload, core.CacheStrategyNo) - - if ch, ok := channel.(core.GuildChannel); ok { - bot.EventManager.Dispatch(&events.GuildChannelDeleteEvent{ - GenericGuildChannelEvent: &events.GenericGuildChannelEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - ChannelID: channel.ID(), - Channel: ch, - GuildID: ch.GuildID(), - }, - }) - } else if ch, ok := channel.(*core.DMChannel); ok { - bot.EventManager.Dispatch(&events.DMChannelDeleteEvent{ - GenericDMChannelEvent: &events.GenericDMChannelEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - ChannelID: channel.ID(), - Channel: ch, - }, - }) - } -} diff --git a/core/handlers/gateway_handler_channel_pins_update.go b/core/handlers/gateway_handler_channel_pins_update.go deleted file mode 100644 index f982b08d..00000000 --- a/core/handlers/gateway_handler_channel_pins_update.go +++ /dev/null @@ -1,71 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerChannelPinsUpdate handles discord.GatewayEventTypeChannelPinsUpdate -type gatewayHandlerChannelPinsUpdate struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerChannelPinsUpdate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeChannelPinsUpdate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerChannelPinsUpdate) New() interface{} { - return &discord.ChannelPinsUpdateGatewayEvent{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerChannelPinsUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.ChannelPinsUpdateGatewayEvent) - - channel := bot.Caches.Channels().Get(payload.ChannelID) - var oldTime *discord.Time - if channel != nil { - oldTime = core.LastPinTimestamp(channel.(core.MessageChannel)) - switch ch := channel.(type) { - case *core.GuildTextChannel: - ch.LastPinTimestamp = payload.LastPinTimestamp - - case *core.DMChannel: - ch.LastPinTimestamp = payload.LastPinTimestamp - - case *core.GroupDMChannel: - ch.LastPinTimestamp = payload.LastPinTimestamp - - case *core.GuildNewsChannel: - ch.LastPinTimestamp = payload.LastPinTimestamp - - case *core.GuildNewsThread: - ch.LastPinTimestamp = payload.LastPinTimestamp - - case *core.GuildPrivateThread: - ch.LastPinTimestamp = payload.LastPinTimestamp - - case *core.GuildPublicThread: - ch.LastPinTimestamp = payload.LastPinTimestamp - } - } - - if payload.GuildID == nil { - bot.EventManager.Dispatch(&events.DMChannelPinsUpdateEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - ChannelID: payload.ChannelID, - OldLastPinTimestamp: oldTime, - NewLastPinTimestamp: payload.LastPinTimestamp, - }) - } else { - bot.EventManager.Dispatch(&events.GuildChannelPinsUpdateEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: *payload.GuildID, - ChannelID: payload.ChannelID, - OldLastPinTimestamp: oldTime, - NewLastPinTimestamp: payload.LastPinTimestamp, - }) - } - -} diff --git a/core/handlers/gateway_handler_channel_update.go b/core/handlers/gateway_handler_channel_update.go deleted file mode 100644 index 8b4099e6..00000000 --- a/core/handlers/gateway_handler_channel_update.go +++ /dev/null @@ -1,87 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerChannelUpdate handles core.GatewayEventChannelUpdate -type gatewayHandlerChannelUpdate struct{} - -// EventType returns the core.GatewayGatewayEventType -func (h *gatewayHandlerChannelUpdate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeChannelUpdate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerChannelUpdate) New() interface{} { - return &discord.UnmarshalChannel{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerChannelUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - channel := v.(*discord.UnmarshalChannel).Channel - - oldChannel := bot.Caches.Channels().GetCopy(channel.ID()) - - if ch, ok := channel.(discord.GuildChannel); ok { - var ( - oldGuildChannel core.GuildChannel - guildChannel core.GuildChannel - ) - if c, ok := oldChannel.(core.GuildChannel); ok { - oldGuildChannel = c - } - if c, ok := bot.EntityBuilder.CreateChannel(channel, core.CacheStrategyNo).(core.GuildChannel); ok { - guildChannel = c - } - - bot.EventManager.Dispatch(&events.GuildChannelUpdateEvent{ - GenericGuildChannelEvent: &events.GenericGuildChannelEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - ChannelID: channel.ID(), - Channel: guildChannel, - GuildID: ch.GuildID(), - }, - OldChannel: oldGuildChannel, - }) - - if guild := guildChannel.Guild(); guild != nil { - if guildMessageChannel, ok := guildChannel.(core.GuildMessageChannel); ok && guild.SelfMember().ChannelPermissions(guildChannel).Missing(discord.PermissionViewChannel) { - for _, guildThread := range guildMessageChannel.Threads() { - bot.Caches.ThreadMembers().RemoveAll(guildThread.ID()) - bot.Caches.Channels().Remove(guildThread.ID()) - bot.EventManager.Dispatch(&events.ThreadHideEvent{ - GenericThreadEvent: &events.GenericThreadEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - Thread: guildThread, - ThreadID: guildThread.ID(), - GuildID: guildThread.GuildID(), - ParentID: guildThread.ParentID(), - }, - }) - } - } - } - } else { - var ( - oldDmChannel *core.DMChannel - dmChannel *core.DMChannel - ) - if c, ok := oldChannel.(*core.DMChannel); ok { - oldDmChannel = c - } - if c, ok := bot.EntityBuilder.CreateChannel(channel, core.CacheStrategyYes).(*core.DMChannel); ok { - dmChannel = c - } - bot.EventManager.Dispatch(&events.DMChannelUpdateEvent{ - GenericDMChannelEvent: &events.GenericDMChannelEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - ChannelID: channel.ID(), - Channel: dmChannel, - }, - OldChannel: oldDmChannel, - }) - } -} diff --git a/core/handlers/gateway_handler_guild_ban_add.go b/core/handlers/gateway_handler_guild_ban_add.go deleted file mode 100644 index 3b1b8c12..00000000 --- a/core/handlers/gateway_handler_guild_ban_add.go +++ /dev/null @@ -1,31 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerGuildBanAdd handles discord.GatewayEventTypeGuildBanAdd -type gatewayHandlerGuildBanAdd struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerGuildBanAdd) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeGuildBanAdd -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildBanAdd) New() interface{} { - return &discord.GuildBanAddGatewayEvent{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildBanAdd) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildBanAddGatewayEvent) - - bot.EventManager.Dispatch(&events.GuildBanEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - User: bot.EntityBuilder.CreateUser(payload.User, core.CacheStrategyNo), - }) -} diff --git a/core/handlers/gateway_handler_guild_ban_remove.go b/core/handlers/gateway_handler_guild_ban_remove.go deleted file mode 100644 index 086185ac..00000000 --- a/core/handlers/gateway_handler_guild_ban_remove.go +++ /dev/null @@ -1,31 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerGuildBanRemove handles discord.GatewayEventTypeGuildBanRemove -type gatewayHandlerGuildBanRemove struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerGuildBanRemove) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeGuildBanRemove -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildBanRemove) New() interface{} { - return &discord.GuildBanRemoveGatewayEvent{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildBanRemove) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildBanRemoveGatewayEvent) - - bot.EventManager.Dispatch(&events.GuildUnbanEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - User: bot.EntityBuilder.CreateUser(payload.User, core.CacheStrategyNo), - }) -} diff --git a/core/handlers/gateway_handler_guild_create.go b/core/handlers/gateway_handler_guild_create.go deleted file mode 100644 index 0f4a1fa6..00000000 --- a/core/handlers/gateway_handler_guild_create.go +++ /dev/null @@ -1,160 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" -) - -// gatewayHandlerGuildCreate handles core.GuildCreateGatewayEvent -type gatewayHandlerGuildCreate struct{} - -// EventType returns the core.GatewayGatewayEventType -func (h *gatewayHandlerGuildCreate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeGuildCreate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildCreate) New() interface{} { - return &discord.GatewayGuild{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildCreate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GatewayGuild) - - shard, _ := bot.Shard(payload.ID) - shardID := shard.ShardID() - - wasUnready := bot.Caches.Guilds().IsUnready(shardID, payload.ID) - wasUnavailable := bot.Caches.Guilds().IsUnavailable(payload.ID) - - guild := bot.EntityBuilder.CreateGuild(payload.Guild, core.CacheStrategyYes) - - for _, channel := range payload.Channels { - bot.EntityBuilder.CreateChannel(setGuildID(channel, payload.ID), core.CacheStrategyYes) - } - - for _, thread := range payload.Threads { - bot.EntityBuilder.CreateChannel(setGuildID(thread, payload.ID), core.CacheStrategyYes) - } - - for _, role := range payload.Roles { - role.GuildID = payload.ID - bot.EntityBuilder.CreateRole(payload.ID, role, core.CacheStrategyYes) - } - - for _, member := range payload.Members { - bot.EntityBuilder.CreateMember(payload.ID, member, core.CacheStrategyYes) - } - - for _, voiceState := range payload.VoiceStates { - voiceState.GuildID = payload.ID // populate unset field - vs := bot.EntityBuilder.CreateVoiceState(voiceState, core.CacheStrategyYes) - if channel := vs.Channel(); channel != nil { - if ch, ok := channel.(*core.GuildVoiceChannel); ok { - ch.ConnectedMemberIDs[voiceState.UserID] = struct{}{} - } else if ch, ok := channel.(*core.GuildStageVoiceChannel); ok { - ch.ConnectedMemberIDs[voiceState.UserID] = struct{}{} - } - } - } - - for _, emote := range payload.Emojis { - bot.EntityBuilder.CreateEmoji(payload.ID, emote, core.CacheStrategyYes) - } - - for _, sticker := range payload.Stickers { - bot.EntityBuilder.CreateSticker(sticker, core.CacheStrategyYes) - } - - for _, stageInstance := range payload.StageInstances { - bot.EntityBuilder.CreateStageInstance(stageInstance, core.CacheStrategyYes) - } - - for _, guildScheduledEvent := range payload.GuildScheduledEvents { - bot.EntityBuilder.CreateGuildScheduledEvent(guildScheduledEvent, core.CacheStrategyYes) - } - - for _, presence := range payload.Presences { - bot.EntityBuilder.CreatePresence(presence, core.CacheStrategyYes) - } - - genericGuildEvent := &events.GenericGuildEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.ID, - Guild: guild, - } - - if wasUnready { - bot.Caches.Guilds().SetReady(shardID, payload.ID) - bot.EventManager.Dispatch(&events.GuildReadyEvent{ - GenericGuildEvent: genericGuildEvent, - }) - if len(bot.Caches.Guilds().UnreadyGuilds(shardID)) == 0 { - bot.EventManager.Dispatch(&events.GuildsReadyEvent{ - GenericEvent: events.NewGenericEvent(bot, -1), - ShardID: shardID, - }) - } - if bot.MemberChunkingManager.MemberChunkingFilter()(payload.ID) { - go func() { - if _, err := bot.MemberChunkingManager.RequestMembersWithQuery(payload.ID, "", 0); err != nil { - bot.Logger.Error("failed to chunk guild on guild_create. error: ", err) - } - }() - } - - } else if wasUnavailable { - bot.Caches.Guilds().SetAvailable(payload.ID) - bot.EventManager.Dispatch(&events.GuildAvailableEvent{ - GenericGuildEvent: genericGuildEvent, - }) - } else { - bot.EventManager.Dispatch(&events.GuildJoinEvent{ - GenericGuildEvent: genericGuildEvent, - }) - } -} - -func setGuildID(channel discord.GuildChannel, guildID snowflake.Snowflake) discord.GuildChannel { - switch ch := channel.(type) { - case discord.GuildTextChannel: - ch.ChannelGuildID = guildID - return ch - - case discord.GuildVoiceChannel: - ch.ChannelGuildID = guildID - return ch - - case discord.GuildCategoryChannel: - ch.ChannelGuildID = guildID - return ch - - case discord.GuildNewsChannel: - ch.ChannelGuildID = guildID - return ch - - case discord.GuildStoreChannel: - ch.ChannelGuildID = guildID - return ch - - case discord.GuildNewsThread: - ch.ChannelGuildID = guildID - return ch - - case discord.GuildPrivateThread: - ch.ChannelGuildID = guildID - return ch - - case discord.GuildPublicThread: - ch.ChannelGuildID = guildID - return ch - - case discord.GuildStageVoiceChannel: - ch.ChannelGuildID = guildID - return ch - } - return nil -} diff --git a/core/handlers/gateway_handler_guild_delete.go b/core/handlers/gateway_handler_guild_delete.go deleted file mode 100644 index 115e8a48..00000000 --- a/core/handlers/gateway_handler_guild_delete.go +++ /dev/null @@ -1,46 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerGuildDelete handles discord.GatewayEventTypeGuildDelete -type gatewayHandlerGuildDelete struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerGuildDelete) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeGuildDelete -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildDelete) New() interface{} { - return &discord.UnavailableGuild{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildDelete) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.UnavailableGuild) - - guild := bot.Caches.Guilds().Get(payload.ID) - - if payload.Unavailable { - bot.Caches.Guilds().SetUnavailable(payload.ID) - } - - genericGuildEvent := &events.GenericGuildEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - Guild: guild, - } - - if payload.Unavailable { - bot.EventManager.Dispatch(&events.GuildUnavailableEvent{ - GenericGuildEvent: genericGuildEvent, - }) - } else { - bot.EventManager.Dispatch(&events.GuildLeaveEvent{ - GenericGuildEvent: genericGuildEvent, - }) - } -} diff --git a/core/handlers/gateway_handler_guild_emojis_update.go b/core/handlers/gateway_handler_guild_emojis_update.go deleted file mode 100644 index d3665c74..00000000 --- a/core/handlers/gateway_handler_guild_emojis_update.go +++ /dev/null @@ -1,91 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" - "github.com/google/go-cmp/cmp" -) - -// gatewayHandlerGuildEmojisUpdate handles discord.GatewayEventTypeGuildEmojisUpdate -type gatewayHandlerGuildEmojisUpdate struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerGuildEmojisUpdate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeGuildEmojisUpdate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildEmojisUpdate) New() interface{} { - return &discord.GuildEmojisUpdateGatewayEvent{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildEmojisUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildEmojisUpdateGatewayEvent) - - if bot.Caches.Config().CacheFlags.Missing(core.CacheFlagEmojis) { - return - } - - var ( - emojiCache = bot.Caches.Emojis().GuildCache(payload.GuildID) - oldEmojis = map[snowflake.Snowflake]*core.Emoji{} - newEmojis = map[snowflake.Snowflake]*core.Emoji{} - updatedEmojis = map[snowflake.Snowflake]*core.Emoji{} - ) - - oldEmojis = make(map[snowflake.Snowflake]*core.Emoji, len(emojiCache)) - for key, value := range emojiCache { - va := *value - oldEmojis[key] = &va - } - - for _, current := range payload.Emojis { - emoji, ok := emojiCache[current.ID] - if ok { - delete(oldEmojis, current.ID) - if !cmp.Equal(emoji, current) { - updatedEmojis[current.ID] = bot.EntityBuilder.CreateEmoji(payload.GuildID, current, core.CacheStrategyYes) - } - } else { - newEmojis[current.ID] = bot.EntityBuilder.CreateEmoji(payload.GuildID, current, core.CacheStrategyYes) - } - } - - for emojiID := range oldEmojis { - bot.Caches.Emojis().Remove(payload.GuildID, emojiID) - } - - for _, emoji := range newEmojis { - bot.EventManager.Dispatch(&events.EmojiCreateEvent{ - GenericEmojiEvent: &events.GenericEmojiEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - Emoji: emoji, - }, - }) - } - - for _, emoji := range updatedEmojis { - bot.EventManager.Dispatch(&events.EmojiUpdateEvent{ - GenericEmojiEvent: &events.GenericEmojiEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - Emoji: emoji, - }, - }) - } - - for _, emoji := range oldEmojis { - bot.EventManager.Dispatch(&events.EmojiDeleteEvent{ - GenericEmojiEvent: &events.GenericEmojiEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - Emoji: emoji, - }, - }) - } - -} diff --git a/core/handlers/gateway_handler_guild_member_add.go b/core/handlers/gateway_handler_guild_member_add.go deleted file mode 100644 index ecfdab9f..00000000 --- a/core/handlers/gateway_handler_guild_member_add.go +++ /dev/null @@ -1,37 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerGuildMemberAdd handles discord.GatewayEventTypeGuildMemberAdd -type gatewayHandlerGuildMemberAdd struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerGuildMemberAdd) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeGuildMemberAdd -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildMemberAdd) New() interface{} { - return &discord.Member{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildMemberAdd) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.Member) - - if guild := bot.Caches.Guilds().Get(payload.GuildID); guild != nil { - guild.MemberCount++ - } - - bot.EventManager.Dispatch(&events.GuildMemberJoinEvent{ - GenericGuildMemberEvent: &events.GenericGuildMemberEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - Member: bot.EntityBuilder.CreateMember(payload.GuildID, payload, core.CacheStrategyYes), - }, - }) -} diff --git a/core/handlers/gateway_handler_guild_member_remove.go b/core/handlers/gateway_handler_guild_member_remove.go deleted file mode 100644 index 4551c8ca..00000000 --- a/core/handlers/gateway_handler_guild_member_remove.go +++ /dev/null @@ -1,42 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerGuildMemberRemove handles discord.GatewayEventTypeGuildMemberRemove -type gatewayHandlerGuildMemberRemove struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerGuildMemberRemove) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeGuildMemberRemove -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildMemberRemove) New() interface{} { - return &discord.GuildMemberRemoveGatewayEvent{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildMemberRemove) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildMemberRemoveGatewayEvent) - - if guild := bot.Caches.Guilds().Get(payload.GuildID); guild != nil { - guild.MemberCount-- - } - - member := bot.Caches.Members().GetCopy(payload.GuildID, payload.User.ID) - - bot.Caches.Members().Remove(payload.GuildID, payload.User.ID) - - user := bot.EntityBuilder.CreateUser(payload.User, core.CacheStrategyYes) - - bot.EventManager.Dispatch(&events.GuildMemberLeaveEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - User: user, - Member: member, - }) -} diff --git a/core/handlers/gateway_handler_guild_member_update.go b/core/handlers/gateway_handler_guild_member_update.go deleted file mode 100644 index 55713d6a..00000000 --- a/core/handlers/gateway_handler_guild_member_update.go +++ /dev/null @@ -1,36 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerGuildMemberUpdate handles discord.GatewayEventTypeGuildMemberUpdate -type gatewayHandlerGuildMemberUpdate struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerGuildMemberUpdate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeGuildMemberUpdate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildMemberUpdate) New() interface{} { - return &discord.Member{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildMemberUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.Member) - - oldCoreMember := bot.Caches.Members().GetCopy(payload.GuildID, payload.User.ID) - - bot.EventManager.Dispatch(&events.GuildMemberUpdateEvent{ - GenericGuildMemberEvent: &events.GenericGuildMemberEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - Member: bot.EntityBuilder.CreateMember(payload.GuildID, payload, core.CacheStrategyYes), - }, - OldMember: oldCoreMember, - }) -} diff --git a/core/handlers/gateway_handler_guild_role_create.go b/core/handlers/gateway_handler_guild_role_create.go deleted file mode 100644 index 17521002..00000000 --- a/core/handlers/gateway_handler_guild_role_create.go +++ /dev/null @@ -1,34 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerGuildRoleCreate handles discord.GatewayEventTypeGuildRoleCreate -type gatewayHandlerGuildRoleCreate struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerGuildRoleCreate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeGuildRoleCreate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildRoleCreate) New() interface{} { - return &discord.GuildRoleCreateGatewayEvent{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildRoleCreate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildRoleCreateGatewayEvent) - - bot.EventManager.Dispatch(&events.RoleCreateEvent{ - GenericRoleEvent: &events.GenericRoleEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - RoleID: payload.Role.ID, - Role: bot.EntityBuilder.CreateRole(payload.GuildID, payload.Role, core.CacheStrategyYes), - }, - }) -} diff --git a/core/handlers/gateway_handler_guild_role_delete.go b/core/handlers/gateway_handler_guild_role_delete.go deleted file mode 100644 index 418e8c85..00000000 --- a/core/handlers/gateway_handler_guild_role_delete.go +++ /dev/null @@ -1,38 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerGuildRoleDelete handles discord.GatewayEventTypeGuildRoleDelete -type gatewayHandlerGuildRoleDelete struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerGuildRoleDelete) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeGuildRoleDelete -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildRoleDelete) New() interface{} { - return &discord.GuildRoleDeleteGatewayEvent{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildRoleDelete) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildRoleDeleteGatewayEvent) - - role := bot.Caches.Roles().GetCopy(payload.GuildID, payload.RoleID) - - bot.Caches.Roles().Remove(payload.GuildID, payload.RoleID) - - bot.EventManager.Dispatch(&events.RoleDeleteEvent{ - GenericRoleEvent: &events.GenericRoleEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - RoleID: payload.RoleID, - Role: role, - }, - }) -} diff --git a/core/handlers/gateway_handler_guild_role_update.go b/core/handlers/gateway_handler_guild_role_update.go deleted file mode 100644 index dc5e953c..00000000 --- a/core/handlers/gateway_handler_guild_role_update.go +++ /dev/null @@ -1,37 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerGuildRoleUpdate handles discord.GatewayEventTypeGuildRoleUpdate -type gatewayHandlerGuildRoleUpdate struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerGuildRoleUpdate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeGuildRoleUpdate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildRoleUpdate) New() interface{} { - return &discord.GuildRoleUpdateGatewayEvent{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildRoleUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildRoleUpdateGatewayEvent) - - oldRole := bot.Caches.Roles().GetCopy(payload.GuildID, payload.Role.ID) - - bot.EventManager.Dispatch(&events.RoleUpdateEvent{ - GenericRoleEvent: &events.GenericRoleEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - RoleID: payload.Role.ID, - Role: bot.EntityBuilder.CreateRole(payload.GuildID, payload.Role, core.CacheStrategyYes), - }, - OldRole: oldRole, - }) -} diff --git a/core/handlers/gateway_handler_guild_stickers_update.go b/core/handlers/gateway_handler_guild_stickers_update.go deleted file mode 100644 index f7d60595..00000000 --- a/core/handlers/gateway_handler_guild_stickers_update.go +++ /dev/null @@ -1,91 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" - "github.com/google/go-cmp/cmp" -) - -// gatewayHandlerGuildStickersUpdate handles discord.GatewayEventTypeGuildStickersUpdate -type gatewayHandlerGuildStickersUpdate struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerGuildStickersUpdate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeGuildStickersUpdate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildStickersUpdate) New() interface{} { - return &discord.GuildStickersUpdateGatewayEvent{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildStickersUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildStickersUpdateGatewayEvent) - - if bot.Caches.Config().CacheFlags.Missing(core.CacheFlagStickers) { - return - } - - var ( - stickerCache = bot.Caches.Stickers().GuildCache(payload.GuildID) - oldStickers = map[snowflake.Snowflake]*core.Sticker{} - newStickers = map[snowflake.Snowflake]*core.Sticker{} - updatedStickers = map[snowflake.Snowflake]*core.Sticker{} - ) - - oldStickers = make(map[snowflake.Snowflake]*core.Sticker, len(stickerCache)) - for key, value := range stickerCache { - va := *value - oldStickers[key] = &va - } - - for _, current := range payload.Stickers { - sticker, ok := stickerCache[current.ID] - if ok { - delete(oldStickers, current.ID) - if !cmp.Equal(sticker, current) { - updatedStickers[current.ID] = bot.EntityBuilder.CreateSticker(current, core.CacheStrategyYes) - } - } else { - newStickers[current.ID] = bot.EntityBuilder.CreateSticker(current, core.CacheStrategyYes) - } - } - - for stickerID := range oldStickers { - bot.Caches.Stickers().Remove(payload.GuildID, stickerID) - } - - for _, sticker := range newStickers { - bot.EventManager.Dispatch(&events.StickerCreateEvent{ - GenericStickerEvent: &events.GenericStickerEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - Sticker: sticker, - }, - }) - } - - for _, sticker := range updatedStickers { - bot.EventManager.Dispatch(&events.StickerUpdateEvent{ - GenericStickerEvent: &events.GenericStickerEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - Sticker: sticker, - }, - }) - } - - for _, sticker := range oldStickers { - bot.EventManager.Dispatch(&events.StickerDeleteEvent{ - GenericStickerEvent: &events.GenericStickerEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - Sticker: sticker, - }, - }) - } - -} diff --git a/core/handlers/gateway_handler_integration_create.go b/core/handlers/gateway_handler_integration_create.go deleted file mode 100644 index 2ccc6a6f..00000000 --- a/core/handlers/gateway_handler_integration_create.go +++ /dev/null @@ -1,33 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerGuildBanAdd handles discord.GatewayEventTypeIntegrationCreate -type gatewayHandlerIntegrationCreate struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerIntegrationCreate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeIntegrationCreate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerIntegrationCreate) New() interface{} { - return &discord.IntegrationCreateGatewayEvent{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerIntegrationCreate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.IntegrationCreateGatewayEvent) - - bot.EventManager.Dispatch(&events.IntegrationCreateEvent{ - GenericIntegrationEvent: &events.GenericIntegrationEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - Integration: bot.EntityBuilder.CreateIntegration(payload.GuildID, payload.Integration, core.CacheStrategyYes), - }, - }) -} diff --git a/core/handlers/gateway_handler_integration_update.go b/core/handlers/gateway_handler_integration_update.go deleted file mode 100644 index fb69dc36..00000000 --- a/core/handlers/gateway_handler_integration_update.go +++ /dev/null @@ -1,33 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerGuildBanAdd handles discord.GatewayEventTypeIntegrationUpdate -type gatewayHandlerIntegrationUpdate struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerIntegrationUpdate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeIntegrationUpdate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerIntegrationUpdate) New() interface{} { - return &discord.IntegrationCreateGatewayEvent{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerIntegrationUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.IntegrationUpdateGatewayEvent) - - bot.EventManager.Dispatch(&events.IntegrationUpdateEvent{ - GenericIntegrationEvent: &events.GenericIntegrationEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: payload.GuildID, - Integration: bot.EntityBuilder.CreateIntegration(payload.GuildID, payload.Integration, core.CacheStrategyYes), - }, - }) -} diff --git a/core/handlers/gateway_handler_interaction_create.go b/core/handlers/gateway_handler_interaction_create.go deleted file mode 100644 index 428426a3..00000000 --- a/core/handlers/gateway_handler_interaction_create.go +++ /dev/null @@ -1,65 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerInteractionCreate handles core.InteractionCreateGatewayEvent -type gatewayHandlerInteractionCreate struct{} - -// EventType returns the core.GatewayGatewayEventType -func (h *gatewayHandlerInteractionCreate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeInteractionCreate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerInteractionCreate) New() interface{} { - return &discord.UnmarshalInteraction{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerInteractionCreate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - HandleInteraction(bot, sequenceNumber, nil, (*v.(*discord.UnmarshalInteraction)).Interaction) -} - -func HandleInteraction(bot *core.Bot, sequenceNumber discord.GatewaySequence, c chan<- discord.InteractionResponse, interaction discord.Interaction) { - coreInteraction := bot.EntityBuilder.CreateInteraction(interaction, c, core.CacheStrategyYes) - - genericEvent := events.NewGenericEvent(bot, sequenceNumber) - - bot.EventManager.Dispatch(&events.InteractionEvent{ - GenericEvent: genericEvent, - Interaction: coreInteraction, - }) - - switch i := coreInteraction.(type) { - case *core.ApplicationCommandInteraction: - bot.EventManager.Dispatch(&events.ApplicationCommandInteractionEvent{ - GenericEvent: genericEvent, - ApplicationCommandInteraction: i, - }) - - case *core.ComponentInteraction: - bot.EventManager.Dispatch(&events.ComponentInteractionEvent{ - GenericEvent: genericEvent, - ComponentInteraction: i, - }) - - case *core.AutocompleteInteraction: - bot.EventManager.Dispatch(&events.AutocompleteInteractionEvent{ - GenericEvent: genericEvent, - AutocompleteInteraction: i, - }) - - case *core.ModalSubmitInteraction: - bot.EventManager.Dispatch(&events.ModalSubmitInteractionEvent{ - GenericEvent: genericEvent, - ModalSubmitInteraction: i, - }) - - default: - bot.Logger.Errorf("unknown interaction with type %d received", interaction.Type()) - } -} diff --git a/core/handlers/gateway_handler_invite_create.go b/core/handlers/gateway_handler_invite_create.go deleted file mode 100644 index 14a61aa7..00000000 --- a/core/handlers/gateway_handler_invite_create.go +++ /dev/null @@ -1,35 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerInviteCreate handles discord.GatewayEventTypeInviteCreate -type gatewayHandlerInviteCreate struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerInviteCreate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeInviteCreate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerInviteCreate) New() interface{} { - return &discord.Invite{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerInviteCreate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - invite := *v.(*discord.Invite) - - bot.EventManager.Dispatch(&events.GuildInviteCreateEvent{ - GenericGuildInviteEvent: &events.GenericGuildInviteEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: *invite.GuildID, - Code: invite.Code, - ChannelID: invite.ChannelID, - }, - Invite: bot.EntityBuilder.CreateInvite(invite, core.CacheStrategyYes), - }) -} diff --git a/core/handlers/gateway_handler_invite_delete.go b/core/handlers/gateway_handler_invite_delete.go deleted file mode 100644 index 7053e484..00000000 --- a/core/handlers/gateway_handler_invite_delete.go +++ /dev/null @@ -1,34 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerInviteDelete handles discord.GatewayEventTypeInviteDelete -type gatewayHandlerInviteDelete struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerInviteDelete) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeInviteDelete -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerInviteDelete) New() interface{} { - return &discord.InviteDeleteGatewayEvent{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerInviteDelete) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.InviteDeleteGatewayEvent) - - bot.EventManager.Dispatch(&events.GuildInviteDeleteEvent{ - GenericGuildInviteEvent: &events.GenericGuildInviteEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildID: *payload.GuildID, - ChannelID: payload.ChannelID, - Code: payload.Code, - }, - }) -} diff --git a/core/handlers/gateway_handler_message_create.go b/core/handlers/gateway_handler_message_create.go deleted file mode 100644 index 7f703b17..00000000 --- a/core/handlers/gateway_handler_message_create.go +++ /dev/null @@ -1,60 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerMessageCreate handles discord.GatewayEventTypeMessageCreate -type gatewayHandlerMessageCreate struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerMessageCreate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeMessageCreate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerMessageCreate) New() interface{} { - return &discord.Message{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerMessageCreate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.Message) - - genericEvent := events.NewGenericEvent(bot, sequenceNumber) - message := bot.EntityBuilder.CreateMessage(payload, core.CacheStrategyYes) - - bot.EventManager.Dispatch(&events.MessageCreateEvent{ - GenericMessageEvent: &events.GenericMessageEvent{ - GenericEvent: genericEvent, - MessageID: payload.ID, - Message: message, - ChannelID: payload.ChannelID, - GuildID: payload.GuildID, - }, - }) - - if message.GuildID == nil { - bot.EventManager.Dispatch(&events.DMMessageCreateEvent{ - GenericDMMessageEvent: &events.GenericDMMessageEvent{ - GenericEvent: genericEvent, - MessageID: payload.ID, - Message: message, - ChannelID: payload.ChannelID, - }, - }) - } else { - bot.EventManager.Dispatch(&events.GuildMessageCreateEvent{ - GenericGuildMessageEvent: &events.GenericGuildMessageEvent{ - GenericEvent: genericEvent, - MessageID: payload.ID, - Message: message, - ChannelID: payload.ChannelID, - GuildID: *payload.GuildID, - }, - }) - } - -} diff --git a/core/handlers/gateway_handler_message_update.go b/core/handlers/gateway_handler_message_update.go deleted file mode 100644 index b748dc49..00000000 --- a/core/handlers/gateway_handler_message_update.go +++ /dev/null @@ -1,65 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerMessageUpdate handles discord.GatewayEventTypeMessageUpdate -type gatewayHandlerMessageUpdate struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerMessageUpdate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeMessageUpdate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerMessageUpdate) New() interface{} { - return &discord.Message{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerMessageUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.Message) - - oldMessage := bot.Caches.Messages().GetCopy(payload.ChannelID, payload.ID) - - message := bot.EntityBuilder.CreateMessage(payload, core.CacheStrategyYes) - - genericEvent := events.NewGenericEvent(bot, sequenceNumber) - - bot.EventManager.Dispatch(&events.MessageUpdateEvent{ - GenericMessageEvent: &events.GenericMessageEvent{ - GenericEvent: genericEvent, - MessageID: payload.ID, - Message: message, - ChannelID: payload.ChannelID, - GuildID: payload.GuildID, - }, - OldMessage: oldMessage, - }) - - if payload.GuildID == nil { - bot.EventManager.Dispatch(&events.DMMessageUpdateEvent{ - GenericDMMessageEvent: &events.GenericDMMessageEvent{ - GenericEvent: genericEvent, - MessageID: payload.ID, - Message: message, - ChannelID: payload.ChannelID, - }, - OldMessage: oldMessage, - }) - } else { - bot.EventManager.Dispatch(&events.GuildMessageUpdateEvent{ - GenericGuildMessageEvent: &events.GenericGuildMessageEvent{ - GenericEvent: genericEvent, - MessageID: payload.ID, - Message: message, - ChannelID: payload.ChannelID, - GuildID: *payload.GuildID, - }, - OldMessage: oldMessage, - }) - } -} diff --git a/core/handlers/gateway_handler_stage_instance_create.go b/core/handlers/gateway_handler_stage_instance_create.go deleted file mode 100644 index c3d892fe..00000000 --- a/core/handlers/gateway_handler_stage_instance_create.go +++ /dev/null @@ -1,33 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerStageInstanceCreate handles discord.GatewayEventTypeStageInstanceCreate -type gatewayHandlerStageInstanceCreate struct{} - -// EventType returns the discord.GatewayEventTypeStageInstanceCreate -func (h *gatewayHandlerStageInstanceCreate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeStageInstanceCreate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerStageInstanceCreate) New() interface{} { - return &discord.StageInstance{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerStageInstanceCreate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.StageInstance) - - bot.EventManager.Dispatch(&events.StageInstanceCreateEvent{ - GenericStageInstanceEvent: &events.GenericStageInstanceEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - StageInstanceID: payload.ID, - StageInstance: bot.EntityBuilder.CreateStageInstance(payload, core.CacheStrategyYes), - }, - }) -} diff --git a/core/handlers/gateway_handler_stage_instance_delete.go b/core/handlers/gateway_handler_stage_instance_delete.go deleted file mode 100644 index b28a1f38..00000000 --- a/core/handlers/gateway_handler_stage_instance_delete.go +++ /dev/null @@ -1,41 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerStageInstanceDelete handles discord.GatewayEventTypeStageInstanceDelete -type gatewayHandlerStageInstanceDelete struct{} - -// EventType returns the discord.GatewayEventType -func (h *gatewayHandlerStageInstanceDelete) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeStageInstanceDelete -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerStageInstanceDelete) New() interface{} { - return &discord.StageInstance{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerStageInstanceDelete) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.StageInstance) - - bot.Caches.StageInstances().Remove(payload.ID) - - if channel := bot.Caches.Channels().Get(payload.ChannelID); channel != nil { - if sCh, ok := channel.(*core.GuildStageVoiceChannel); ok { - sCh.StageInstanceID = nil - } - } - - bot.EventManager.Dispatch(&events.StageInstanceDeleteEvent{ - GenericStageInstanceEvent: &events.GenericStageInstanceEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - StageInstanceID: payload.ID, - StageInstance: bot.EntityBuilder.CreateStageInstance(payload, core.CacheStrategyNo), - }, - }) -} diff --git a/core/handlers/gateway_handler_thread_create.go b/core/handlers/gateway_handler_thread_create.go deleted file mode 100644 index 353959db..00000000 --- a/core/handlers/gateway_handler_thread_create.go +++ /dev/null @@ -1,30 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -type gatewayHandlerThreadCreate struct{} - -func (h *gatewayHandlerThreadCreate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeThreadCreate -} - -func (h *gatewayHandlerThreadCreate) New() interface{} { - return &discord.GatewayEventThreadCreate{} -} - -func (h *gatewayHandlerThreadCreate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GatewayEventThreadCreate) - - bot.EventManager.Dispatch(&events.ThreadCreateEvent{ - GenericThreadEvent: &events.GenericThreadEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - ThreadID: payload.ID(), - GuildID: payload.GuildID(), - Thread: bot.EntityBuilder.CreateChannel(payload.GuildThread, core.CacheStrategyYes).(core.GuildThread), - }, - }) -} diff --git a/core/handlers/gateway_handler_thread_delete.go b/core/handlers/gateway_handler_thread_delete.go deleted file mode 100644 index f9eab781..00000000 --- a/core/handlers/gateway_handler_thread_delete.go +++ /dev/null @@ -1,39 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -type gatewayHandlerThreadDelete struct{} - -func (h *gatewayHandlerThreadDelete) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeThreadDelete -} - -func (h *gatewayHandlerThreadDelete) New() interface{} { - return &discord.GatewayEventThreadDelete{} -} - -func (h *gatewayHandlerThreadDelete) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GatewayEventThreadDelete) - - channel := bot.Caches.Channels().GetCopy(payload.ID) - bot.Caches.Channels().Remove(payload.ID) - bot.Caches.ThreadMembers().RemoveAll(payload.ID) - var thread core.GuildThread - if c, ok := channel.(core.GuildThread); ok { - thread = c - } - - bot.EventManager.Dispatch(&events.ThreadDeleteEvent{ - GenericThreadEvent: &events.GenericThreadEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - ThreadID: payload.ID, - GuildID: payload.GuildID, - ParentID: payload.ParentID, - Thread: thread, - }, - }) -} diff --git a/core/handlers/gateway_handler_thread_list_sync.go b/core/handlers/gateway_handler_thread_list_sync.go deleted file mode 100644 index 001fe2cd..00000000 --- a/core/handlers/gateway_handler_thread_list_sync.go +++ /dev/null @@ -1,32 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -type gatewayHandlerThreadListSync struct{} - -func (h *gatewayHandlerThreadListSync) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeThreadListSync -} - -func (h *gatewayHandlerThreadListSync) New() interface{} { - return &discord.GatewayEventThreadListSync{} -} - -func (h *gatewayHandlerThreadListSync) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GatewayEventThreadListSync) - - for i := range payload.Threads { - thread := bot.EntityBuilder.CreateChannel(payload.Threads[i], core.CacheStrategyYes).(core.GuildThread) - bot.EventManager.Dispatch(&events.ThreadShowEvent{ - GenericThreadEvent: &events.GenericThreadEvent{ - Thread: thread, - ThreadID: thread.ID(), - GuildID: payload.GuildID, - }, - }) - } -} diff --git a/core/handlers/gateway_handler_thread_member_update.go b/core/handlers/gateway_handler_thread_member_update.go deleted file mode 100644 index 23a41895..00000000 --- a/core/handlers/gateway_handler_thread_member_update.go +++ /dev/null @@ -1,22 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" -) - -type gatewayHandlerThreadMemberUpdate struct{} - -func (h *gatewayHandlerThreadMemberUpdate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeThreadMemberUpdate -} - -func (h *gatewayHandlerThreadMemberUpdate) New() interface{} { - return &discord.ThreadMember{} -} - -func (h *gatewayHandlerThreadMemberUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.ThreadMember) - - bot.EntityBuilder.CreateThreadMember(payload, core.CacheStrategyYes) -} diff --git a/core/handlers/gateway_handler_thread_members_update.go b/core/handlers/gateway_handler_thread_members_update.go deleted file mode 100644 index 9077c4fc..00000000 --- a/core/handlers/gateway_handler_thread_members_update.go +++ /dev/null @@ -1,71 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -type gatewayHandlerThreadMembersUpdate struct{} - -func (h *gatewayHandlerThreadMembersUpdate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeThreadMembersUpdate -} - -func (h *gatewayHandlerThreadMembersUpdate) New() interface{} { - return &discord.GatewayEventThreadMembersUpdate{} -} - -func (h *gatewayHandlerThreadMembersUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GatewayEventThreadMembersUpdate) - - genericEvent := events.NewGenericEvent(bot, sequenceNumber) - - if channel := bot.Caches.Channels().Get(payload.ID); channel != nil { - switch thread := channel.(type) { - case *core.GuildNewsThread: - thread.MemberCount = payload.MemberCount - - case *core.GuildPublicThread: - thread.MemberCount = payload.MemberCount - - case *core.GuildPrivateThread: - thread.MemberCount = payload.MemberCount - } - } - - for i := range payload.AddedMembers { - threadMember := bot.EntityBuilder.CreateThreadMember(payload.AddedMembers[i].ThreadMember, core.CacheStrategyYes) - - bot.EntityBuilder.CreateMember(payload.GuildID, payload.AddedMembers[i].Member, core.CacheStrategyYes) - if presence := payload.AddedMembers[i].Presence; presence != nil { - bot.EntityBuilder.CreatePresence(*presence, core.CacheStrategyYes) - } - - bot.EventManager.Dispatch(&events.ThreadMemberAddEvent{ - GenericThreadMemberEvent: &events.GenericThreadMemberEvent{ - GenericEvent: genericEvent, - GuildID: payload.GuildID, - ThreadID: payload.ID, - ThreadMemberID: payload.AddedMembers[i].UserID, - ThreadMember: threadMember, - }, - }) - } - - for i := range payload.RemovedMemberIDs { - threadMember := bot.Caches.ThreadMembers().GetCopy(payload.ID, payload.RemovedMemberIDs[i]) - bot.Caches.ThreadMembers().Remove(payload.ID, payload.RemovedMemberIDs[i]) - - bot.EventManager.Dispatch(&events.ThreadMemberRemoveEvent{ - GenericThreadMemberEvent: &events.GenericThreadMemberEvent{ - GenericEvent: genericEvent, - GuildID: payload.GuildID, - ThreadID: payload.ID, - ThreadMemberID: payload.RemovedMemberIDs[i], - ThreadMember: threadMember, - }, - }) - } - -} diff --git a/core/handlers/gateway_handler_thread_update.go b/core/handlers/gateway_handler_thread_update.go deleted file mode 100644 index 45955c33..00000000 --- a/core/handlers/gateway_handler_thread_update.go +++ /dev/null @@ -1,39 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -type gatewayHandlerThreadUpdate struct{} - -func (h *gatewayHandlerThreadUpdate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeThreadUpdate -} - -func (h *gatewayHandlerThreadUpdate) New() interface{} { - return &discord.UnmarshalChannel{} -} - -func (h *gatewayHandlerThreadUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := v.(*discord.UnmarshalChannel).Channel - - var oldThread core.GuildThread - if ch, ok := bot.Caches.Channels().Get(payload.ID()).(core.GuildThread); ok { - oldThread = ch - } - - thread := bot.EntityBuilder.CreateChannel(payload, core.CacheStrategyYes).(core.GuildThread) - - bot.EventManager.Dispatch(&events.ThreadUpdateEvent{ - GenericThreadEvent: &events.GenericThreadEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - Thread: thread, - ThreadID: thread.ID(), - GuildID: thread.GuildID(), - ParentID: thread.ParentID(), - }, - OldThread: oldThread, - }) -} diff --git a/core/handlers/gateway_handler_user_update.go b/core/handlers/gateway_handler_user_update.go deleted file mode 100644 index cc12b889..00000000 --- a/core/handlers/gateway_handler_user_update.go +++ /dev/null @@ -1,38 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerVoiceServerUpdate handles discord.GatewayEventTypeUserUpdate -type gatewayHandlerUserUpdate struct{} - -// EventType returns the discord.GatewayEventTypeUserUpdate -func (h *gatewayHandlerUserUpdate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeUserUpdate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerUserUpdate) New() interface{} { - return &discord.OAuth2User{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerUserUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.OAuth2User) - - var oldSelfUser *core.SelfUser - if bot.SelfUser != nil { - selfUser := *bot.SelfUser - oldSelfUser = &selfUser - } - - bot.EventManager.Dispatch(&events.SelfUpdateEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - SelfUser: bot.EntityBuilder.CreateSelfUser(payload, core.CacheStrategyYes), - OldSelfUser: oldSelfUser, - }) - -} diff --git a/core/handlers/gateway_handler_voice_state_update.go b/core/handlers/gateway_handler_voice_state_update.go deleted file mode 100644 index 663c157f..00000000 --- a/core/handlers/gateway_handler_voice_state_update.go +++ /dev/null @@ -1,78 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" -) - -// gatewayHandlerVoiceStateUpdate handles core.GatewayEventVoiceStateUpdate -type gatewayHandlerVoiceStateUpdate struct{} - -// EventType returns the gateway.EventType -func (h *gatewayHandlerVoiceStateUpdate) EventType() discord.GatewayEventType { - return discord.GatewayEventTypeVoiceStateUpdate -} - -// New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerVoiceStateUpdate) New() interface{} { - return &discord.VoiceState{} -} - -// HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerVoiceStateUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.VoiceState) - - oldVoiceState := bot.Caches.VoiceStates().GetCopy(payload.GuildID, payload.UserID) - - voiceState := bot.EntityBuilder.CreateVoiceState(payload, core.CacheStrategyYes) - - if oldVoiceState != nil && oldVoiceState.ChannelID != nil { - if channel := bot.Caches.Channels().Get(*oldVoiceState.ChannelID); channel != nil { - if ch, ok := channel.(*core.GuildVoiceChannel); ok { - delete(ch.ConnectedMemberIDs, voiceState.UserID) - } else if ch, ok := channel.(*core.GuildStageVoiceChannel); ok { - delete(ch.ConnectedMemberIDs, voiceState.UserID) - } - } - } - - if voiceState.ChannelID != nil { - if channel := bot.Caches.Channels().Get(*voiceState.ChannelID); channel != nil { - if ch, ok := channel.(*core.GuildVoiceChannel); ok { - ch.ConnectedMemberIDs[voiceState.UserID] = struct{}{} - } else if ch, ok := channel.(*core.GuildStageVoiceChannel); ok { - ch.ConnectedMemberIDs[voiceState.UserID] = struct{}{} - } - - } - } - - genericGuildVoiceEvent := &events.GenericGuildVoiceEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - VoiceState: voiceState, - } - - bot.EventManager.Dispatch(&events.GuildVoiceStateUpdateEvent{ - GenericGuildVoiceEvent: genericGuildVoiceEvent, - OldVoiceState: oldVoiceState, - }) - - if oldVoiceState != nil && oldVoiceState.ChannelID != nil && payload.ChannelID != nil { - bot.EventManager.Dispatch(&events.GuildVoiceMoveEvent{ - GenericGuildVoiceEvent: genericGuildVoiceEvent, - OldVoiceState: oldVoiceState, - }) - } else if (oldVoiceState == nil || oldVoiceState.ChannelID == nil) && payload.ChannelID != nil { - bot.EventManager.Dispatch(&events.GuildVoiceJoinEvent{ - GenericGuildVoiceEvent: genericGuildVoiceEvent, - }) - } else if payload.ChannelID == nil { - bot.EventManager.Dispatch(&events.GuildVoiceLeaveEvent{ - GenericGuildVoiceEvent: genericGuildVoiceEvent, - OldVoiceState: oldVoiceState, - }) - } else { - bot.Logger.Warnf("could not decide which GuildVoiceEvent to fire") - } -} diff --git a/core/handlers/httpserver_handler_interaction_create.go b/core/handlers/httpserver_handler_interaction_create.go deleted file mode 100644 index 0ed97c05..00000000 --- a/core/handlers/httpserver_handler_interaction_create.go +++ /dev/null @@ -1,29 +0,0 @@ -package handlers - -import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" -) - -var _ core.HTTPServerEventHandler = (*httpserverHandlerInteractionCreate)(nil) - -type httpserverHandlerInteractionCreate struct{} - -func (h *httpserverHandlerInteractionCreate) New() interface{} { - return &discord.UnmarshalInteraction{} -} - -func (h *httpserverHandlerInteractionCreate) HandleHTTPEvent(bot *core.Bot, c chan<- discord.InteractionResponse, v interface{}) { - interaction := (*v.(*discord.UnmarshalInteraction)).Interaction - - // we just want to pong all pings - // no need for any event - if interaction.Type() == discord.InteractionTypePing { - bot.Logger.Debug("received http interaction ping. responding with pong") - c <- discord.InteractionResponse{ - Type: discord.InteractionCallbackTypePong, - } - return - } - HandleInteraction(bot, -1, c, interaction) -} diff --git a/core/integration.go b/core/integration.go deleted file mode 100644 index d53b5a07..00000000 --- a/core/integration.go +++ /dev/null @@ -1,77 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/snowflake" -) - -type Integration interface { - discord.Integration -} - -type TwitchIntegration struct { - discord.TwitchIntegration - Bot *Bot - GuildID snowflake.Snowflake - User *User -} - -// Guild returns the Guild the Integration belongs to -func (i *TwitchIntegration) Guild() *Guild { - return i.Bot.Caches.Guilds().Get(i.GuildID) -} - -// Role returns the Subscriber Role the Integration uses -func (i *TwitchIntegration) Role() *Role { - return i.Bot.Caches.Roles().Get(i.GuildID, i.RoleID) -} - -// Delete deletes the Integration from the Guild -func (i *TwitchIntegration) Delete(opts ...rest.RequestOpt) error { - return i.Bot.RestServices.GuildService().DeleteIntegration(i.GuildID, i.ID(), opts...) -} - -type YouTubeIntegration struct { - discord.YouTubeIntegration - Bot *Bot - GuildID snowflake.Snowflake - User *User -} - -// Guild returns the Guild the Integration belongs to -func (i *YouTubeIntegration) Guild() *Guild { - return i.Bot.Caches.Guilds().Get(i.GuildID) -} - -// Role returns the Subscriber Role the Integration uses -func (i *YouTubeIntegration) Role() *Role { - return i.Bot.Caches.Roles().Get(i.GuildID, i.RoleID) -} - -// Delete deletes the Integration from the Guild -func (i *YouTubeIntegration) Delete(opts ...rest.RequestOpt) error { - return i.Bot.RestServices.GuildService().DeleteIntegration(i.GuildID, i.ID(), opts...) -} - -type BotIntegration struct { - discord.BotIntegration - Bot *Bot - GuildID snowflake.Snowflake - Application *IntegrationApplication -} - -// Guild returns the Guild the Integration belongs to -func (i *BotIntegration) Guild() *Guild { - return i.Bot.Caches.Guilds().Get(i.GuildID) -} - -// Delete deletes the Integration from the Guild -func (i *BotIntegration) Delete(opts ...rest.RequestOpt) error { - return i.Bot.RestServices.GuildService().DeleteIntegration(i.GuildID, i.ID(), opts...) -} - -type IntegrationApplication struct { - discord.IntegrationApplication - Bot *User -} diff --git a/core/interaction.go b/core/interaction.go deleted file mode 100644 index c52e4728..00000000 --- a/core/interaction.go +++ /dev/null @@ -1,149 +0,0 @@ -package core - -import ( - "time" - - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/snowflake" -) - -type InteractionFilter func(interaction Interaction) bool - -// Interaction represents a generic Interaction received from discord -type Interaction interface { - Type() discord.InteractionType - interaction() - Respond(callbackType discord.InteractionCallbackType, callbackData discord.InteractionCallbackData, opts ...rest.RequestOpt) error -} - -type BaseInteraction struct { - ID snowflake.Snowflake - ApplicationID snowflake.Snowflake - Token string - Version int - GuildID *snowflake.Snowflake - ChannelID snowflake.Snowflake - Locale discord.Locale - GuildLocale *discord.Locale - Member *Member - User *User - ResponseChannel chan<- discord.InteractionResponse - Acknowledged bool - Bot *Bot -} - -func (i *BaseInteraction) Respond(callbackType discord.InteractionCallbackType, callbackData discord.InteractionCallbackData, opts ...rest.RequestOpt) error { - if i.Acknowledged { - return discord.ErrInteractionAlreadyReplied - } - i.Acknowledged = true - - if time.Now().After(i.ID.Time().Add(3 * time.Second)) { - return discord.ErrInteractionExpired - } - - response := discord.InteractionResponse{ - Type: callbackType, - Data: callbackData, - } - - if i.ResponseChannel != nil { - i.ResponseChannel <- response - return nil - } - - return i.Bot.RestServices.InteractionService().CreateInteractionResponse(i.ID, i.Token, response, opts...) -} - -// Guild returns the Guild from the Caches -func (i *BaseInteraction) Guild() *Guild { - if i.GuildID == nil { - return nil - } - return i.Bot.Caches.Guilds().Get(*i.GuildID) -} - -// Channel returns the Channel from the Caches -func (i *BaseInteraction) Channel() MessageChannel { - if ch := i.Bot.Caches.Channels().Get(i.ChannelID); ch != nil { - return ch.(MessageChannel) - } - return nil -} - -type UpdateInteraction struct { - *BaseInteraction -} - -func (i UpdateInteraction) UpdateMessage(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) error { - return i.Respond(discord.InteractionCallbackTypeUpdateMessage, messageUpdate, opts...) -} - -func (i UpdateInteraction) DeferUpdateMessage(opts ...rest.RequestOpt) error { - return i.Respond(discord.InteractionCallbackTypeDeferredUpdateMessage, nil, opts...) -} - -type CreateInteraction struct { - *BaseInteraction -} - -func (i CreateInteraction) CreateMessage(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) error { - return i.Respond(discord.InteractionCallbackTypeChannelMessageWithSource, messageCreate, opts...) -} - -func (i CreateInteraction) DeferCreateMessage(ephemeral bool, opts ...rest.RequestOpt) error { - var data discord.InteractionCallbackData - if ephemeral { - data = discord.MessageCreate{Flags: discord.MessageFlagEphemeral} - } - return i.Respond(discord.InteractionCallbackTypeDeferredChannelMessageWithSource, data, opts...) -} - -func (i CreateInteraction) GetOriginalMessage(opts ...rest.RequestOpt) (*Message, error) { - message, err := i.Bot.RestServices.InteractionService().GetInteractionResponse(i.ApplicationID, i.Token, opts...) - if err != nil { - return nil, err - } - return i.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -func (i CreateInteraction) UpdateOriginalMessage(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - message, err := i.Bot.RestServices.InteractionService().UpdateInteractionResponse(i.ApplicationID, i.Token, messageUpdate, opts...) - if err != nil { - return nil, err - } - return i.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -func (i CreateInteraction) DeleteOriginalMessage(opts ...rest.RequestOpt) error { - return i.Bot.RestServices.InteractionService().DeleteInteractionResponse(i.ApplicationID, i.Token, opts...) -} - -func (i CreateInteraction) GetFollowupMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - message, err := i.Bot.RestServices.InteractionService().GetFollowupMessage(i.ApplicationID, i.Token, messageID, opts...) - if err != nil { - return nil, err - } - return i.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -func (i CreateInteraction) CreateFollowupMessage(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - message, err := i.Bot.RestServices.InteractionService().CreateFollowupMessage(i.ApplicationID, i.Token, messageCreate, opts...) - if err != nil { - return nil, err - } - return i.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -func (i CreateInteraction) UpdateFollowupMessage(messageID snowflake.Snowflake, messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - message, err := i.Bot.RestServices.InteractionService().UpdateFollowupMessage(i.ApplicationID, i.Token, messageID, messageUpdate, opts...) - if err != nil { - return nil, err - } - return i.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -func (i CreateInteraction) DeleteFollowupMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return i.Bot.RestServices.InteractionService().DeleteFollowupMessage(i.ApplicationID, i.Token, messageID, opts...) -} diff --git a/core/invite.go b/core/invite.go deleted file mode 100644 index a1711429..00000000 --- a/core/invite.go +++ /dev/null @@ -1,29 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/disgo/rest/route" -) - -type Invite struct { - discord.Invite - Bot *Bot - Inviter *User - TargetUser *User -} - -// URL returns the invite URL in format like https://discord.gg/{code} -func (i *Invite) URL() string { - compiledRoute, _ := route.InviteURL.Compile(nil, i.Code) - return compiledRoute.URL() -} - -// Delete deletes this Invite -func (i *Invite) Delete(opts ...rest.RequestOpt) (*Invite, error) { - invite, err := i.Bot.RestServices.InviteService().DeleteInvite(i.Code, opts...) - if err != nil { - return nil, err - } - return i.Bot.EntityBuilder.CreateInvite(*invite, CacheStrategyNo), nil -} diff --git a/core/member.go b/core/member.go deleted file mode 100644 index 8307d44f..00000000 --- a/core/member.go +++ /dev/null @@ -1,134 +0,0 @@ -package core - -import ( - "strings" - "time" - - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" -) - -type Member struct { - discord.Member - User *User - Bot *Bot -} - -// Permissions returns the calculated Permissions the Member has in the Guild -func (m *Member) Permissions() discord.Permissions { - return GetMemberPermissions(m) -} - -// InteractionPermissions returns the Permissions the Member has in this Channel for this Interaction -func (m *Member) InteractionPermissions() discord.Permissions { - if m.Member.Permissions != nil { - return *m.Member.Permissions - } - return discord.PermissionsNone -} - -// ChannelPermissions returns the Permissions the Member has in the provided Channel -func (m *Member) ChannelPermissions(channel GuildChannel) discord.Permissions { - return GetMemberPermissionsInChannel(channel, m) -} - -// Roles return all Role(s)the Member has -func (m *Member) Roles() []*Role { - var roles []*Role - allRoles := m.Bot.Caches.Roles().GuildCache(m.GuildID) - for _, roleID := range m.RoleIDs { - roles = append(roles, allRoles[roleID]) - } - return roles -} - -// VoiceState returns the VoiceState for this Member. -// This will only check cached voice states! (requires core.CacheFlagVoiceStates and discord.GatewayIntentGuildVoiceStates) -func (m *Member) VoiceState() *VoiceState { - return m.Bot.Caches.VoiceStates().Get(m.GuildID, m.User.ID) -} - -// Guild returns the Guild this Member is tied to. -// This will only check cached guilds! -func (m *Member) Guild() *Guild { - return m.Bot.Caches.Guilds().Get(m.GuildID) -} - -// IsOwner returns whether this Member is the owner of the Guild -func (m *Member) IsOwner() bool { - if guild := m.Guild(); guild != nil { - return guild.OwnerID == m.User.ID - } - return false -} - -// IsTimedOut returns whether this Member is timed out -func (m *Member) IsTimedOut() bool { - return m.CommunicationDisabledUntil != nil && m.CommunicationDisabledUntil.After(time.Now()) -} - -// AvatarURL returns the Avatar URL of the Member for this guild -func (m *Member) AvatarURL(size int) *string { - if m.Avatar == nil { - return nil - } - format := route.PNG - if strings.HasPrefix(*m.Avatar, "a_") { - format = route.GIF - } - compiledRoute, err := route.MemberAvatar.Compile(nil, format, size, m.GuildID, m.User.ID, *m.Avatar) - if err != nil { - return nil - } - url := compiledRoute.URL() - return &url -} - -// EffectiveAvatarURL returns either the server avatar or global avatar depending on if the user has one -func (m *Member) EffectiveAvatarURL(size int) string { - if m.Avatar == nil { - return m.User.EffectiveAvatarURL(size) - } - return *m.AvatarURL(size) -} - -// Update updates the Member with the properties provided in discord.MemberUpdate -func (m *Member) Update(updateGuildMember discord.MemberUpdate, opts ...rest.RequestOpt) (*Member, error) { - member, err := m.Bot.RestServices.GuildService().UpdateMember(m.GuildID, m.User.ID, updateGuildMember, opts...) - if err != nil { - return nil, err - } - return m.Bot.EntityBuilder.CreateMember(m.GuildID, *member, CacheStrategyNoWs), nil -} - -// Move moves/kicks the member to/from a voice channel -func (m *Member) Move(channelID snowflake.Snowflake, opts ...rest.RequestOpt) (*Member, error) { - return m.Update(discord.MemberUpdate{ChannelID: &channelID}, opts...) -} - -// Kick kicks this Member from the Guild -func (m *Member) Kick(opts ...rest.RequestOpt) error { - return m.Bot.RestServices.GuildService().RemoveMember(m.GuildID, m.User.ID, opts...) -} - -// Ban bans this Member from the Guild -func (m *Member) Ban(deleteMessageDays int, opts ...rest.RequestOpt) error { - return m.Bot.RestServices.GuildService().AddBan(m.GuildID, m.User.ID, deleteMessageDays, opts...) -} - -// Unban unbans this Member from the Guild -func (m *Member) Unban(opts ...rest.RequestOpt) error { - return m.Bot.RestServices.GuildService().DeleteBan(m.GuildID, m.User.ID, opts...) -} - -// AddRole adds a specific Role the Member -func (m *Member) AddRole(roleID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return m.Bot.RestServices.GuildService().AddMemberRole(m.GuildID, m.User.ID, roleID, opts...) -} - -// RemoveRole removes a specific Role this Member -func (m *Member) RemoveRole(roleID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return m.Bot.RestServices.GuildService().RemoveMemberRole(m.GuildID, m.User.ID, roleID, opts...) -} diff --git a/core/member_cache_policy.go b/core/member_cache_policy.go deleted file mode 100644 index 80df65ec..00000000 --- a/core/member_cache_policy.go +++ /dev/null @@ -1,48 +0,0 @@ -package core - -// MemberCachePolicy can be used to define your own policy for caching members -type MemberCachePolicy func(*Member) bool - -// Default member caches policies -//goland:noinspection GoUnusedGlobalVariable -var ( - MemberCachePolicyNone MemberCachePolicy = func(_ *Member) bool { return false } - MemberCachePolicyAll MemberCachePolicy = func(_ *Member) bool { return true } - MemberCachePolicyOwner MemberCachePolicy = func(member *Member) bool { return member.IsOwner() } - MemberCachePolicyOnline MemberCachePolicy = func(_ *Member) bool { return false } - MemberCachePolicyVoice MemberCachePolicy = func(member *Member) bool { return false } - MemberCachePolicyPending MemberCachePolicy = func(member *Member) bool { return member.Pending } - MemberCachePolicyDefault = MemberCachePolicyOwner.Or(MemberCachePolicyVoice) -) - -// Or allows you to combine that policy with another, meaning either needs to be true -func (p MemberCachePolicy) Or(policy MemberCachePolicy) MemberCachePolicy { - return func(member *Member) bool { - return p(member) || policy(member) - } -} - -// And allows you to require both policies to be true for the member to be cached -func (p MemberCachePolicy) And(policy MemberCachePolicy) MemberCachePolicy { - return func(member *Member) bool { - return p(member) && policy(member) - } -} - -// MemberCachePolicyAnyOf is a shorthand for MemberCachePolicy.Or(MemberCachePolicy).Or(MemberCachePolicy) etc. -//goland:noinspection GoUnusedExportedFunction -func MemberCachePolicyAnyOf(policy MemberCachePolicy, policies ...MemberCachePolicy) MemberCachePolicy { - for _, p := range policies { - policy = policy.Or(p) - } - return policy -} - -// MemberCachePolicyAllOf is a shorthand for MemberCachePolicy.And(MemberCachePolicy).And(MemberCachePolicy) etc. -//goland:noinspection GoUnusedExportedFunction -func MemberCachePolicyAllOf(policy MemberCachePolicy, policies ...MemberCachePolicy) MemberCachePolicy { - for _, p := range policies { - policy = policy.And(p) - } - return policy -} diff --git a/core/mentions.go b/core/mentions.go deleted file mode 100644 index cb131465..00000000 --- a/core/mentions.go +++ /dev/null @@ -1,5 +0,0 @@ -package core - -type Mentionable interface { - Mention() string -} diff --git a/core/message.go b/core/message.go deleted file mode 100644 index 19525f08..00000000 --- a/core/message.go +++ /dev/null @@ -1,208 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/snowflake" -) - -// MessageFilter used to filter Message(s) in a collectors.MessageCollector -type MessageFilter func(message *Message) bool - -type Message struct { - discord.Message - Bot *Bot - Member *Member - Author *User - Stickers []*MessageSticker -} - -func (m *Message) CreateThread(threadCreateWithMessage discord.ThreadCreateWithMessage, opts ...rest.RequestOpt) (GuildThread, error) { - channel, err := m.Bot.RestServices.ThreadService().CreateThreadWithMessage(m.ChannelID, m.ID, threadCreateWithMessage, opts...) - if err != nil { - return nil, err - } - return m.Bot.EntityBuilder.CreateChannel(channel.(discord.Channel), CacheStrategyNo).(GuildThread), nil -} - -// Guild returns the Guild this Message was sent in. -// This will only check cached guilds! -func (m *Message) Guild() *Guild { - if m.GuildID == nil { - return nil - } - return m.Bot.Caches.Guilds().Get(*m.GuildID) -} - -// Channel gets the MessageChannel the Message was sent in -func (m *Message) Channel() MessageChannel { - channel := m.Bot.Caches.Channels().Get(m.ChannelID) - if channel != nil { - return channel.(MessageChannel) - } - return nil -} - -// AddReactionByEmote allows you to add an Emoji to a message_events via reaction -func (m *Message) AddReactionByEmote(emote Emoji, opts ...rest.RequestOpt) error { - return m.AddReaction(emote.Reaction(), opts...) -} - -// AddReaction allows you to add a reaction to a message_events from a string, for _examples a custom emoji CommandID, or a native emoji -func (m *Message) AddReaction(emoji string, opts ...rest.RequestOpt) error { - return m.Bot.RestServices.ChannelService().AddReaction(m.ChannelID, m.ID, emoji, opts...) -} - -// Update allows you to edit an existing Message sent by you -func (m *Message) Update(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - message, err := m.Bot.RestServices.ChannelService().UpdateMessage(m.ChannelID, m.ID, messageUpdate, opts...) - if err != nil { - return nil, err - } - return m.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -// Delete deletes this Message -func (m *Message) Delete(opts ...rest.RequestOpt) error { - return m.Bot.RestServices.ChannelService().DeleteMessage(m.ChannelID, m.ID, opts...) -} - -// Crosspost crossposts an existing message -func (m *Message) Crosspost(opts ...rest.RequestOpt) (*Message, error) { - channel := m.Channel() - if channel != nil && channel.Type() != discord.ChannelTypeGuildNews { - return nil, discord.ErrChannelNotTypeNews - } - message, err := m.Bot.RestServices.ChannelService().CrosspostMessage(m.ChannelID, m.ID, opts...) - if err != nil { - return nil, err - } - return m.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -// Reply replies to this Message -func (m *Message) Reply(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) (*Message, error) { - messageCreate.MessageReference = &discord.MessageReference{MessageID: &m.ID} - message, err := m.Bot.RestServices.ChannelService().CreateMessage(m.ChannelID, messageCreate, opts...) - if err != nil { - return nil, err - } - return m.Bot.EntityBuilder.CreateMessage(*message, CacheStrategyNoWs), nil -} - -// ActionRows returns all discord.ActionRowComponent(s) from this Message -func (m *Message) ActionRows() []discord.ActionRowComponent { - var actionRows []discord.ActionRowComponent - for i := range m.Components { - if actionRow, ok := m.Components[i].(discord.ActionRowComponent); ok { - actionRows = append(actionRows, actionRow) - } - } - return actionRows -} - -// InteractiveComponents returns the discord.InteractiveComponent(s) from this Message -func (m *Message) InteractiveComponents() []discord.InteractiveComponent { - var interactiveComponents []discord.InteractiveComponent - for i := range m.Components { - for ii := range m.Components[i].Components() { - interactiveComponents = append(interactiveComponents, m.Components[i].Components()[ii]) - } - } - return interactiveComponents -} - -// ComponentByID returns the discord.Component with the specific discord.CustomID -func (m *Message) ComponentByID(customID discord.CustomID) discord.InteractiveComponent { - for i := range m.Components { - for ii := range m.Components[i].Components() { - if m.Components[i].Components()[ii].ID() == customID { - return m.Components[i].Components()[ii] - } - } - } - return nil -} - -// Buttons returns all ButtonComponent(s) from this Message -func (m *Message) Buttons() []discord.ButtonComponent { - var buttons []discord.ButtonComponent - for i := range m.Components { - for ii := range m.Components[i].Components() { - if button, ok := m.Components[i].Components()[ii].(discord.ButtonComponent); ok { - buttons = append(buttons, button) - } - } - } - return buttons -} - -// ButtonByID returns a ButtonComponent with the specific customID from this Message -func (m *Message) ButtonByID(customID discord.CustomID) *discord.ButtonComponent { - for i := range m.Components { - for ii := range m.Components[i].Components() { - if button, ok := m.Components[i].Components()[ii].(*discord.ButtonComponent); ok && button.ID() == customID { - return button - } - } - } - return nil -} - -// SelectMenus returns all SelectMenuComponent(s) from this Message -func (m *Message) SelectMenus() []discord.SelectMenuComponent { - var selectMenus []discord.SelectMenuComponent - for i := range m.Components { - for ii := range m.Components[i].Components() { - if button, ok := m.Components[i].Components()[ii].(discord.SelectMenuComponent); ok { - selectMenus = append(selectMenus, button) - } - } - } - return selectMenus -} - -// SelectMenuByID returns a SelectMenuComponent with the specific customID from this Message -func (m *Message) SelectMenuByID(customID discord.CustomID) *discord.SelectMenuComponent { - for i := range m.Components { - for ii := range m.Components[i].Components() { - if button, ok := m.Components[i].Components()[ii].(*discord.SelectMenuComponent); ok && button.ID() == customID { - return button - } - } - } - return nil -} - -// IsEphemeral returns true if the Message has MessageFlagEphemeral -func (m *Message) IsEphemeral() bool { - return m.Flags.Has(discord.MessageFlagEphemeral) -} - -// IsWebhookMessage returns true if the Message was sent by a Webhook -func (m *Message) IsWebhookMessage() bool { - return m.WebhookID != nil -} - -// MessageReactionAddFilter used to filter MessageReactionAddEvent in a collectors.MessageReactionAddCollector -type MessageReactionAddFilter func(e *MessageReactionAdd) bool - -type MessageReactionAdd struct { - UserID snowflake.Snowflake - ChannelID snowflake.Snowflake - MessageID snowflake.Snowflake - GuildID *snowflake.Snowflake - Member *Member - Emoji discord.ReactionEmoji -} - -// MessageReactionRemoveFilter used to filter MessageReactionRemoveEvent in a collectors.MessageReactionRemoveCollector -type MessageReactionRemoveFilter func(e *MessageReactionRemove) bool - -type MessageReactionRemove struct { - UserID snowflake.Snowflake - ChannelID snowflake.Snowflake - MessageID snowflake.Snowflake - GuildID *snowflake.Snowflake - Emoji discord.ReactionEmoji -} diff --git a/core/message_cache_policy.go b/core/message_cache_policy.go deleted file mode 100644 index 6464dddc..00000000 --- a/core/message_cache_policy.go +++ /dev/null @@ -1,57 +0,0 @@ -package core - -import ( - "time" -) - -// MessageCachePolicy can be used to define your own policy for caching messages -type MessageCachePolicy func(message *Message) bool - -// Default member caches policies -//goland:noinspection GoUnusedConst -var ( - MessageCachePolicyNone MessageCachePolicy = func(_ *Message) bool { return false } - MessageCachePolicyDefault = MessageCachePolicyNone -) - -// Or allows you to combine that policy with another, meaning either needs to be true -//goland:noinspection GoUnusedExportedFunction -func (p MessageCachePolicy) Or(policy MessageCachePolicy) MessageCachePolicy { - return func(message *Message) bool { - return p(message) || policy(message) - } -} - -// And allows you to require both policies to be true for the member to be cached -//goland:noinspection GoUnusedExportedFunction -func (p MessageCachePolicy) And(policy MessageCachePolicy) MessageCachePolicy { - return func(message *Message) bool { - return p(message) && policy(message) - } -} - -// MessageCachePolicyDuration creates a new MessageCachePolicy which caches messages for the give duration -//goland:noinspection GoUnusedExportedFunction -func MessageCachePolicyDuration(duration time.Duration) MessageCachePolicy { - return func(message *Message) bool { - return message.CreatedAt.Add(duration).After(time.Now()) - } -} - -// MessageCachePolicyAny is a shorthand for MessageCachePolicy.Or(MessageCachePolicy).Or(MessageCachePolicy) etc. -//goland:noinspection GoUnusedExportedFunction -func MessageCachePolicyAny(policy MessageCachePolicy, policies ...MessageCachePolicy) MessageCachePolicy { - for _, p := range policies { - policy = policy.Or(p) - } - return policy -} - -// MessageCachePolicyAll is a shorthand for MessageCachePolicy.And(MessageCachePolicy).And(MessageCachePolicy) etc. -//goland:noinspection GoUnusedExportedFunction -func MessageCachePolicyAll(policy MessageCachePolicy, policies ...MessageCachePolicy) MessageCachePolicy { - for _, p := range policies { - policy = policy.And(p) - } - return policy -} diff --git a/core/message_sticker.go b/core/message_sticker.go deleted file mode 100644 index 339c30c4..00000000 --- a/core/message_sticker.go +++ /dev/null @@ -1,33 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" -) - -type MessageSticker struct { - discord.MessageSticker - Bot *Bot -} - -func (s *MessageSticker) URL(size int) string { - fileExtension := route.PNG - if s.FormatType == discord.StickerFormatTypeLottie { - fileExtension = route.Lottie - } - compiledRoute, _ := route.CustomSticker.Compile(nil, fileExtension, size, s.ID) - return compiledRoute.URL() -} - -func (s *MessageSticker) GetSticker() (*Sticker, error) { - coreSticker := s.Bot.Caches.Stickers().FindFirst(func(sticker *Sticker) bool { return sticker.ID == s.ID }) - if coreSticker != nil { - return coreSticker, nil - } - - sticker, err := s.Bot.RestServices.StickerService().GetSticker(s.ID) - if err != nil { - return nil, err - } - return s.Bot.EntityBuilder.CreateSticker(*sticker, CacheStrategyNoWs), nil -} diff --git a/core/modal_submit_interaction.go b/core/modal_submit_interaction.go deleted file mode 100644 index 54673981..00000000 --- a/core/modal_submit_interaction.go +++ /dev/null @@ -1,61 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" -) - -type ModalSubmitInteractionFilter func(ModalSubmitInteraction *ModalSubmitInteraction) bool - -var _ Interaction = (*ModalSubmitInteraction)(nil) - -type ModalSubmitInteraction struct { - CreateInteraction - Data ModalSubmitInteractionData -} - -func (i ModalSubmitInteraction) interaction() {} -func (i ModalSubmitInteraction) Type() discord.InteractionType { - return discord.InteractionTypeModalSubmit -} - -func (i ModalSubmitInteraction) UpdateMessage(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) error { - return i.Respond(discord.InteractionCallbackTypeUpdateMessage, messageUpdate, opts...) -} - -func (i ModalSubmitInteraction) DeferUpdateMessage(opts ...rest.RequestOpt) error { - return i.Respond(discord.InteractionCallbackTypeDeferredUpdateMessage, nil, opts...) -} - -type ModalSubmitInteractionData struct { - discord.ModalSubmitInteractionData - Components ModalComponentsMap -} - -type ModalComponentsMap map[discord.CustomID]discord.InputComponent - -func (m ModalComponentsMap) Get(customID discord.CustomID) discord.InputComponent { - if component, ok := m[customID]; ok { - return component - } - return nil -} - -func (m ModalComponentsMap) TextComponent(customID discord.CustomID) *discord.TextInputComponent { - component := m.Get(customID) - if component == nil { - return nil - } - if cmp, ok := component.(discord.TextInputComponent); ok { - return &cmp - } - return nil -} - -func (m ModalComponentsMap) Text(customID discord.CustomID) *string { - component := m.TextComponent(customID) - if component == nil { - return nil - } - return &component.Value -} diff --git a/core/permission_util.go b/core/permission_util.go deleted file mode 100644 index 9b3b27b5..00000000 --- a/core/permission_util.go +++ /dev/null @@ -1,82 +0,0 @@ -package core - -import "github.com/DisgoOrg/disgo/discord" - -// GetMemberPermissions returns all Permissions from the provided Member -func GetMemberPermissions(member *Member) discord.Permissions { - if member.IsOwner() { - return discord.PermissionsAll - } - - var permissions discord.Permissions - if publicRole := member.Bot.Caches.Roles().Get(member.GuildID, member.GuildID); publicRole != nil { - permissions = publicRole.Permissions - } - - for _, role := range member.Roles() { - permissions = permissions.Add(role.Permissions) - if permissions.Has(discord.PermissionAdministrator) { - return discord.PermissionsAll - } - } - if member.CommunicationDisabledUntil != nil { - permissions &= discord.PermissionViewChannel | discord.PermissionReadMessageHistory - } - return permissions -} - -func GetMemberPermissionsInChannel(channel GuildChannel, member *Member) discord.Permissions { - if channel.GuildID() != member.GuildID { - panic("channel and member need to be part of the same guild") - } - - if member.IsOwner() { - return discord.PermissionsAll - } - permissions := GetMemberPermissions(member) - if permissions.Has(discord.PermissionAdministrator) { - return discord.PermissionsAll - } - - var ( - allowRaw discord.Permissions - denyRaw discord.Permissions - ) - if overwrite := channel.RolePermissionOverwrite(channel.GuildID()); overwrite != nil { - allowRaw = overwrite.Allow - denyRaw = overwrite.Deny - } - - var ( - allowRole discord.Permissions - denyRole discord.Permissions - ) - for _, roleID := range member.RoleIDs { - if roleID == channel.GuildID() { - continue - } - - overwrite := channel.RolePermissionOverwrite(roleID) - if overwrite == nil { - break - } - allowRole = allowRole.Add(overwrite.Allow) - denyRole = denyRole.Add(overwrite.Deny) - } - - allowRaw = (allowRaw & (denyRole - 1)) | allowRole - denyRaw = (denyRaw & (allowRole - 1)) | denyRole - - if overwrite := channel.MemberPermissionOverwrite(member.User.ID); overwrite != nil { - allowRaw = (allowRaw & (overwrite.Deny - 1)) | overwrite.Allow - denyRaw = (denyRaw & (overwrite.Allow - 1)) | overwrite.Deny - } - - permissions &= denyRaw - 1 - permissions |= allowRaw - - if member.CommunicationDisabledUntil != nil { - permissions &= discord.PermissionViewChannel | discord.PermissionReadMessageHistory - } - return permissions -} diff --git a/core/presence.go b/core/presence.go deleted file mode 100644 index c6061477..00000000 --- a/core/presence.go +++ /dev/null @@ -1,89 +0,0 @@ -package core - -import ( - "time" - - "github.com/DisgoOrg/disgo/discord" -) - -type Presence struct { - discord.Presence - Bot *Bot -} - -// User returns the User this Presence belongs to. -// This will only check cached users! -func (p *Presence) User() *User { - return p.Bot.Caches.Users().Get(p.PresenceUser.ID) -} - -// Member returns the Member this Presence belongs to. -// This will only check cached members! -func (p *Presence) Member() *Member { - return p.Bot.Caches.Members().Get(p.GuildID, p.PresenceUser.ID) -} - -// Guild returns the Guild this Presence belongs to. -// This will only check cached guilds! -func (p *Presence) Guild() *Guild { - return p.Bot.Caches.Guilds().Get(p.GuildID) -} - -// NewPresence creates a new Presence with the provided properties -//goland:noinspection GoUnusedExportedFunction -func NewPresence(activityType discord.ActivityType, name string, url string, status discord.OnlineStatus, afk bool) discord.UpdatePresenceCommandData { - var since *int64 - if status == discord.OnlineStatusIdle { - unix := time.Now().Unix() - since = &unix - } - - var activities []discord.Activity - if name != "" { - activity := discord.Activity{ - Name: name, - Type: activityType, - } - if activityType == discord.ActivityTypeStreaming && url != "" { - activity.URL = &url - } - activities = append(activities, activity) - } - - return discord.UpdatePresenceCommandData{ - Since: since, - Activities: activities, - Status: status, - AFK: afk, - } -} - -// NewGamePresence creates a new Presence of type discord.ActivityTypeGame -//goland:noinspection GoUnusedExportedFunction -func NewGamePresence(name string, status discord.OnlineStatus, afk bool) discord.UpdatePresenceCommandData { - return NewPresence(discord.ActivityTypeGame, name, "", status, afk) -} - -// NewStreamingPresence creates a new Presence of type discord.ActivityTypeStreaming -//goland:noinspection GoUnusedExportedFunction -func NewStreamingPresence(name string, url string, status discord.OnlineStatus, afk bool) discord.UpdatePresenceCommandData { - return NewPresence(discord.ActivityTypeStreaming, name, url, status, afk) -} - -// NewListeningPresence creates a new Presence of type discord.ActivityTypeListening -//goland:noinspection GoUnusedExportedFunction -func NewListeningPresence(name string, status discord.OnlineStatus, afk bool) discord.UpdatePresenceCommandData { - return NewPresence(discord.ActivityTypeListening, name, "", status, afk) -} - -// NewWatchingPresence creates a new Presence of type discord.ActivityTypeWatching -//goland:noinspection GoUnusedExportedFunction -func NewWatchingPresence(name string, status discord.OnlineStatus, afk bool) discord.UpdatePresenceCommandData { - return NewPresence(discord.ActivityTypeWatching, name, "", status, afk) -} - -// NewCompetingPresence creates a new Presence of type discord.ActivityTypeCompeting -//goland:noinspection GoUnusedExportedFunction -func NewCompetingPresence(name string, status discord.OnlineStatus, afk bool) discord.UpdatePresenceCommandData { - return NewPresence(discord.ActivityTypeCompeting, name, "", status, afk) -} diff --git a/core/role.go b/core/role.go deleted file mode 100644 index be978363..00000000 --- a/core/role.go +++ /dev/null @@ -1,65 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/disgo/rest/route" -) - -type Role struct { - discord.Role - Bot *Bot -} - -func (r *Role) IconURL(size int) *string { - if r.Icon == nil { - return nil - } - compiledRoute, _ := route.RoleIcon.Compile(nil, route.PNG, size, r.ID, *r.Icon) - url := compiledRoute.URL() - return &url -} - -// Guild returns the Guild this Role belongs to. -// This will only check cached guilds! -func (r *Role) Guild() *Guild { - return r.Bot.Caches.Guilds().Get(r.GuildID) -} - -//ComparePositionTo compares the position of this Role to another Role. -func (r *Role) ComparePositionTo(role *Role) int { - if role == nil { - panic("Role argument cannot be nil") - } - if r.Position == role.Position { - return int(r.ID.Time().Sub(role.ID.Time()).Nanoseconds()) - } - return r.Position - role.Position -} - -// Update updates this Role with the properties provided in discord.RoleUpdate -func (r *Role) Update(roleUpdate discord.RoleUpdate, opts ...rest.RequestOpt) (*Role, error) { - role, err := r.Bot.RestServices.GuildService().UpdateRole(r.GuildID, r.ID, roleUpdate, opts...) - if err != nil { - return nil, err - } - return r.Bot.EntityBuilder.CreateRole(r.GuildID, *role, CacheStrategyNoWs), nil -} - -// SetPosition sets the position of this Role -func (r *Role) SetPosition(rolePositionUpdate discord.RolePositionUpdate, opts ...rest.RequestOpt) ([]*Role, error) { - roles, err := r.Bot.RestServices.GuildService().UpdateRolePositions(r.GuildID, []discord.RolePositionUpdate{rolePositionUpdate}, opts...) - if err != nil { - return nil, err - } - coreRoles := make([]*Role, len(roles)) - for i, role := range roles { - coreRoles[i] = r.Bot.EntityBuilder.CreateRole(r.GuildID, role, CacheStrategyNoWs) - } - return coreRoles, nil -} - -// Delete deletes this Role -func (r *Role) Delete(opts ...rest.RequestOpt) error { - return r.Bot.RestServices.GuildService().DeleteRole(r.GuildID, r.ID, opts...) -} diff --git a/core/self_user.go b/core/self_user.go deleted file mode 100644 index 4edd687e..00000000 --- a/core/self_user.go +++ /dev/null @@ -1,26 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" -) - -type SelfUser struct { - discord.OAuth2User - Bot *Bot - User *User -} - -// Update updates the SelfUser with the properties provided in discord.SelfUserUpdate -func (u *SelfUser) Update(updateSelfUser discord.SelfUserUpdate, opts ...rest.RequestOpt) (*SelfUser, error) { - selfUser, err := u.Bot.RestServices.UserService().UpdateSelfUser(updateSelfUser, opts...) - if err != nil { - return nil, err - } - return u.Bot.EntityBuilder.CreateSelfUser(*selfUser, CacheStrategyNoWs), nil -} - -// OpenDMChannel creates a Channel between the user and the Bot -func (u *SelfUser) OpenDMChannel(_ ...rest.RequestOpt) (*Channel, error) { - return nil, discord.ErrSelfDM -} diff --git a/core/slash_command_option.go b/core/slash_command_option.go deleted file mode 100644 index 1c80be00..00000000 --- a/core/slash_command_option.go +++ /dev/null @@ -1,388 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" -) - -type SlashCommandOption interface { - discord.SlashCommandOption -} - -type SlashCommandOptionSubCommand struct { - discord.SlashCommandOptionSubCommand - Options []SlashCommandOption -} - -type SlashCommandOptionSubCommandGroup struct { - discord.SlashCommandOptionSubCommandGroup - Options []SlashCommandOptionSubCommand -} - -type SlashCommandOptionString struct { - discord.SlashCommandOptionString - Resolved *SlashCommandResolved -} - -func (o *SlashCommandOptionString) MentionedUsers() []*User { - matches := discord.MentionTypeUser.FindAllStringSubmatch(o.Value, -1) - users := make([]*User, len(matches)) - if matches == nil { - return nil - } - for i := range matches { - users[i] = o.Resolved.Users[snowflake.Snowflake(matches[i][1])] - } - return users -} - -func (o *SlashCommandOptionString) MentionedMembers() []*Member { - matches := discord.MentionTypeUser.FindAllStringSubmatch(o.Value, -1) - members := make([]*Member, len(matches)) - if matches == nil { - return nil - } - for i := range matches { - if member, ok := o.Resolved.Members[snowflake.Snowflake(matches[i][1])]; ok { - members[i] = member - } - } - return members -} - -func (o *SlashCommandOptionString) MentionedChannels() []Channel { - matches := discord.MentionTypeChannel.FindAllStringSubmatch(o.Value, -1) - channels := make([]Channel, len(matches)) - if matches == nil { - return nil - } - for i := range matches { - if channel, ok := o.Resolved.Channels[snowflake.Snowflake(matches[i][1])]; ok { - channels[i] = channel - } - } - return channels -} - -func (o *SlashCommandOptionString) MentionedRoles() []*Role { - matches := discord.MentionTypeRole.FindAllStringSubmatch(o.Value, -1) - roles := make([]*Role, len(matches)) - if matches == nil { - return nil - } - for i := range matches { - if role, ok := o.Resolved.Roles[snowflake.Snowflake(matches[i][1])]; ok { - roles[i] = role - } - } - return roles -} - -type SlashCommandOptionInt struct { - discord.SlashCommandOptionInt -} - -type SlashCommandOptionBool struct { - discord.SlashCommandOptionBool -} - -type SlashCommandOptionUser struct { - discord.SlashCommandOptionUser - Resolved *SlashCommandResolved -} - -func (o SlashCommandOptionUser) User() *User { - return o.Resolved.Users[o.Value] -} - -func (o SlashCommandOptionUser) Member() *Member { - return o.Resolved.Members[o.Value] -} - -type SlashCommandOptionChannel struct { - discord.SlashCommandOptionChannel - Resolved *SlashCommandResolved -} - -func (o SlashCommandOptionChannel) Channel() Channel { - return o.Resolved.Channels[o.Value] -} - -type SlashCommandOptionRole struct { - discord.SlashCommandOptionRole - Resolved *SlashCommandResolved -} - -func (o SlashCommandOptionRole) Role() *Role { - return o.Resolved.Roles[o.Value] -} - -type SlashCommandOptionMentionable struct { - discord.SlashCommandOptionMentionable - Resolved *SlashCommandResolved -} - -func (o SlashCommandOptionMentionable) User() *User { - return o.Resolved.Users[o.Value] -} - -func (o SlashCommandOptionMentionable) Member() *Member { - return o.Resolved.Members[o.Value] -} - -func (o SlashCommandOptionMentionable) Role() *Role { - return o.Resolved.Roles[o.Value] -} - -type SlashCommandOptionFloat struct { - discord.SlashCommandOptionFloat -} - -type SlashCommandOptionAttachment struct { - discord.SlashCommandOptionAttachment - Resolved *SlashCommandResolved -} - -func (o SlashCommandOptionAttachment) Attachment() discord.Attachment { - return o.Resolved.Attachments[o.Value] -} - -type SlashCommandOptionsMap map[string]SlashCommandOption - -func (m SlashCommandOptionsMap) Get(name string) SlashCommandOption { - if option, ok := m[name]; ok { - return option - } - return nil -} - -func (m SlashCommandOptionsMap) StringOption(name string) *SlashCommandOptionString { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionString); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) String(name string) *string { - option := m.StringOption(name) - if option == nil { - return nil - } - return &option.Value -} - -func (m SlashCommandOptionsMap) IntOption(name string) *SlashCommandOptionInt { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionInt); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) Int(name string) *int { - option := m.IntOption(name) - if option == nil { - return nil - } - return &option.Value -} - -func (m SlashCommandOptionsMap) BoolOption(name string) *SlashCommandOptionBool { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionBool); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) Bool(name string) *bool { - option := m.BoolOption(name) - if option == nil { - return nil - } - return &option.Value -} - -func (m SlashCommandOptionsMap) UserOption(name string) *SlashCommandOptionUser { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionUser); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) User(name string) *User { - option := m.Get(name) - if option == nil { - return nil - } - switch opt := option.(type) { - case SlashCommandOptionUser: - return opt.User() - case SlashCommandOptionMentionable: - return opt.User() - default: - return nil - } -} - -func (m SlashCommandOptionsMap) Member(name string) *Member { - option := m.Get(name) - if option == nil { - return nil - } - switch opt := option.(type) { - case SlashCommandOptionUser: - return opt.Member() - case SlashCommandOptionMentionable: - return opt.Member() - default: - return nil - } -} - -func (m SlashCommandOptionsMap) ChannelOption(name string) *SlashCommandOptionChannel { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionChannel); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) Channel(name string) Channel { - option := m.ChannelOption(name) - if option == nil { - return nil - } - return option.Channel() -} - -func (m SlashCommandOptionsMap) RoleOption(name string) *SlashCommandOptionRole { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionRole); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) Role(name string) *Role { - option := m.Get(name) - if option == nil { - return nil - } - switch opt := option.(type) { - case SlashCommandOptionRole: - return opt.Role() - case SlashCommandOptionMentionable: - return opt.Role() - default: - return nil - } -} - -func (m SlashCommandOptionsMap) MentionableOption(name string) *SlashCommandOptionMentionable { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionMentionable); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) Snowflake(name string) *snowflake.Snowflake { - option := m.Get(name) - if option == nil { - return nil - } - switch opt := option.(type) { - case SlashCommandOptionChannel: - return &opt.Value - - case SlashCommandOptionRole: - return &opt.Value - - case SlashCommandOptionUser: - return &opt.Value - - case SlashCommandOptionMentionable: - return &opt.Value - - default: - return nil - } -} - -func (m SlashCommandOptionsMap) FloatOption(name string) *SlashCommandOptionFloat { - option := m.Get(name) - if option == nil { - return nil - } - if opt, ok := option.(SlashCommandOptionFloat); ok { - return &opt - } - return nil -} - -func (m SlashCommandOptionsMap) Float(name string) *float64 { - option := m.FloatOption(name) - if option == nil { - return nil - } - return &option.Value -} - -func (m SlashCommandOptionsMap) GetAll() []SlashCommandOption { - options := make([]SlashCommandOption, len(m)) - i := 0 - for _, option := range m { - options[i] = option - i++ - } - return options -} - -func (m SlashCommandOptionsMap) GetByType(optionType discord.ApplicationCommandOptionType) []SlashCommandOption { - return m.FindAll(func(option SlashCommandOption) bool { - return option.Type() == optionType - }) -} - -func (m SlashCommandOptionsMap) Find(optionFindFunc func(option SlashCommandOption) bool) SlashCommandOption { - for _, option := range m { - if optionFindFunc(option) { - return option - } - } - return nil -} - -func (m SlashCommandOptionsMap) FindAll(optionFindFunc func(option SlashCommandOption) bool) []SlashCommandOption { - var options []SlashCommandOption - for _, option := range m { - if optionFindFunc(option) { - options = append(options, option) - } - } - return options -} diff --git a/core/stage_instance.go b/core/stage_instance.go deleted file mode 100644 index 405e9027..00000000 --- a/core/stage_instance.go +++ /dev/null @@ -1,75 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" -) - -type StageInstance struct { - discord.StageInstance - Bot *Bot -} - -// Guild returns the Guild this StageInstance belongs to. -// This will only check cached guilds! -func (i *StageInstance) Guild() *Guild { - return i.Bot.Caches.Guilds().Get(i.GuildID) -} - -// Channel returns the Channel this StageInstance belongs to. -func (i *StageInstance) Channel() *GuildStageVoiceChannel { - if ch := i.Bot.Caches.Channels().Get(i.ChannelID); ch != nil { - return ch.(*GuildStageVoiceChannel) - } - return nil -} - -// GetSpeakers returns the Member(s) that can speak in this StageInstance -func (i *StageInstance) GetSpeakers() []*Member { - ch := i.Channel() - if ch == nil { - return nil - } - var speakers []*Member - for _, member := range ch.Members() { - if member.VoiceState() != nil && !member.VoiceState().Suppress { - speakers = append(speakers, member) - } - } - return speakers -} - -// GetListeners returns the Member(s) that cannot speak in this StageInstance -func (i *StageInstance) GetListeners() []*Member { - ch := i.Channel() - if ch == nil { - return nil - } - var listeners []*Member - for _, member := range ch.Members() { - if member.VoiceState() != nil && member.VoiceState().Suppress { - listeners = append(listeners, member) - } - } - return listeners -} - -func (s *VoiceState) UpdateVoiceState(suppress *bool, requestToSpeak *discord.NullTime, opts ...rest.RequestOpt) error { - if s.ChannelID == nil { - return discord.ErrMemberMustBeConnectedToChannel - } - return s.Bot.RestServices.GuildService().UpdateCurrentUserVoiceState(s.GuildID, discord.UserVoiceStateUpdate{ChannelID: *s.ChannelID, Suppress: suppress, RequestToSpeakTimestamp: requestToSpeak}, opts...) -} - -func (i *StageInstance) Update(stageInstanceUpdate discord.StageInstanceUpdate, opts ...rest.RequestOpt) (*StageInstance, error) { - stageInstance, err := i.Bot.RestServices.StageInstanceService().UpdateStageInstance(i.ID, stageInstanceUpdate, opts...) - if err != nil { - return nil, err - } - return i.Bot.EntityBuilder.CreateStageInstance(*stageInstance, CacheStrategyNoWs), nil -} - -// Delete deletes this StageInstance -func (i *StageInstance) Delete(opts ...rest.RequestOpt) error { - return i.Bot.RestServices.StageInstanceService().DeleteStageInstance(i.ID, opts...) -} diff --git a/core/sticker.go b/core/sticker.go deleted file mode 100644 index 6b44a268..00000000 --- a/core/sticker.go +++ /dev/null @@ -1,52 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/disgo/rest/route" -) - -type Sticker struct { - discord.Sticker - Bot *Bot - User *User -} - -func (s *Sticker) URL(size int) string { - fileExtension := route.PNG - if s.FormatType == discord.StickerFormatTypeLottie { - fileExtension = route.Lottie - } - compiledRoute, _ := route.CustomSticker.Compile(nil, fileExtension, size, s.ID) - return compiledRoute.URL() -} - -// Guild returns the Guild this Sticker was created for or nil if this isn't a Guild-specific Sticker. -// This will only check cached guilds! -func (s *Sticker) Guild() *Guild { - if s.Type != discord.StickerTypeGuild { - return nil - } - return s.Bot.Caches.Guilds().Get(*s.GuildID) -} - -// Update updates this Sticker with the properties provided in discord.StickerUpdate -func (s *Sticker) Update(stickerUpdate discord.StickerUpdate, opts ...rest.RequestOpt) (*Sticker, error) { - if s.Type != discord.StickerTypeGuild { - return nil, discord.ErrStickerTypeGuild - } - - sticker, err := s.Bot.RestServices.StickerService().UpdateSticker(*s.GuildID, s.ID, stickerUpdate, opts...) - if err != nil { - return nil, err - } - return s.Bot.EntityBuilder.CreateSticker(*sticker, CacheStrategyNoWs), nil -} - -// Delete deletes this Sticker -func (s *Sticker) Delete(opts ...rest.RequestOpt) error { - if s.Type != discord.StickerTypeGuild { - return discord.ErrStickerTypeGuild - } - return s.Bot.RestServices.StickerService().DeleteSticker(*s.GuildID, s.ID, opts...) -} diff --git a/core/sticker_pack.go b/core/sticker_pack.go deleted file mode 100644 index 6a32d153..00000000 --- a/core/sticker_pack.go +++ /dev/null @@ -1,26 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" -) - -type StickerPack struct { - discord.StickerPack - Bot *Bot - Stickers []*Sticker -} - -func (p *StickerPack) CoverSticker() *Sticker { - for _, sticker := range p.Stickers { - if sticker.ID == p.CoverStickerID { - return sticker - } - } - return nil -} - -func (p *StickerPack) BannerAsset(size int) string { - compiledRoute, _ := route.StickerPackBanner.Compile(nil, route.PNG, size, p.BannerAssetID) - return compiledRoute.URL() -} diff --git a/core/thread_member.go b/core/thread_member.go deleted file mode 100644 index 8e548c2e..00000000 --- a/core/thread_member.go +++ /dev/null @@ -1,8 +0,0 @@ -package core - -import "github.com/DisgoOrg/disgo/discord" - -type ThreadMember struct { - discord.ThreadMember - Bot *Bot -} diff --git a/core/user.go b/core/user.go deleted file mode 100644 index 173f22ca..00000000 --- a/core/user.go +++ /dev/null @@ -1,55 +0,0 @@ -package core - -import ( - "strconv" - - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/disgo/rest/route" -) - -type User struct { - discord.User - Bot *Bot -} - -// AvatarURL returns the Avatar URL of this User -func (u *User) AvatarURL(size int) *string { - return u.getAssetURL(route.UserAvatar, u.Avatar, size) -} - -// DefaultAvatarURL returns the default avatar URL of this User -func (u *User) DefaultAvatarURL(size int) string { - discriminator, _ := strconv.Atoi(u.Discriminator) - compiledRoute, err := route.DefaultUserAvatar.Compile(nil, route.PNG, size, discriminator%5) - if err != nil { - return "" - } - return compiledRoute.URL() -} - -// EffectiveAvatarURL returns either this User avatar or default avatar depending on if this User has one -func (u *User) EffectiveAvatarURL(size int) string { - if u.Avatar == nil { - return u.DefaultAvatarURL(size) - } - return *u.AvatarURL(size) -} - -// BannerURL returns the Banner URL of this User -func (u *User) BannerURL(size int) *string { - return u.getAssetURL(route.UserBanner, u.Banner, size) -} - -func (u *User) getAssetURL(cdnRoute *route.CDNRoute, assetId *string, size int) *string { - return discord.FormatAssetURL(cdnRoute, u.ID, assetId, size) -} - -// OpenDMChannel creates a DMChannel between this User and the Bot -func (u *User) OpenDMChannel(opts ...rest.RequestOpt) (*DMChannel, error) { - channel, err := u.Bot.RestServices.UserService().CreateDMChannel(u.ID, opts...) - if err != nil { - return nil, err - } - return u.Bot.EntityBuilder.CreateChannel(*channel, CacheStrategyNoWs).(*DMChannel), nil -} diff --git a/core/user_cache.go b/core/user_cache.go deleted file mode 100644 index 55c10333..00000000 --- a/core/user_cache.go +++ /dev/null @@ -1,89 +0,0 @@ -package core - -import "github.com/DisgoOrg/snowflake" - -type ( - UserFindFunc func(user *User) bool - - UserCache interface { - Get(userID snowflake.Snowflake) *User - GetCopy(userID snowflake.Snowflake) *User - Set(user *User) *User - Remove(userID snowflake.Snowflake) - - Cache() map[snowflake.Snowflake]*User - All() []*User - - FindFirst(userFindFunc UserFindFunc) *User - FindAll(userFindFunc UserFindFunc) []*User - } - - userCacheImpl struct { - users map[snowflake.Snowflake]*User - cacheFlags CacheFlags - } -) - -func NewUserCache(cacheFlags CacheFlags) UserCache { - return &userCacheImpl{users: map[snowflake.Snowflake]*User{}, cacheFlags: cacheFlags} -} - -func (c *userCacheImpl) Get(userID snowflake.Snowflake) *User { - return c.users[userID] -} - -func (c *userCacheImpl) GetCopy(userID snowflake.Snowflake) *User { - if user := c.Get(userID); user != nil { - us := *user - return &us - } - return nil -} - -func (c *userCacheImpl) Set(user *User) *User { - // check if we want to cache user - usr, ok := c.users[user.ID] - if ok { - *usr = *user - return usr - } - c.users[user.ID] = user - return user -} - -func (c *userCacheImpl) Remove(id snowflake.Snowflake) { - delete(c.users, id) -} - -func (c *userCacheImpl) Cache() map[snowflake.Snowflake]*User { - return c.users -} - -func (c *userCacheImpl) All() []*User { - users := make([]*User, len(c.users)) - i := 0 - for _, user := range c.users { - users[i] = user - i++ - } - return users -} - -func (c *userCacheImpl) FindFirst(userFindFunc UserFindFunc) *User { - for _, usr := range c.users { - if userFindFunc(usr) { - return usr - } - } - return nil -} - -func (c *userCacheImpl) FindAll(userFindFunc UserFindFunc) []*User { - var users []*User - for _, usr := range c.users { - if userFindFunc(usr) { - users = append(users, usr) - } - } - return users -} diff --git a/core/voice_state.go b/core/voice_state.go deleted file mode 100644 index 688ca986..00000000 --- a/core/voice_state.go +++ /dev/null @@ -1,50 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" -) - -type VoiceState struct { - discord.VoiceState - Bot *Bot - Member *Member -} - -// Mute returns whether the Member is muted -func (s *VoiceState) Mute() bool { - return s.GuildMute || s.SelfMute -} - -// Deaf returns whether the Member is deafened -func (s *VoiceState) Deaf() bool { - return s.GuildDeaf || s.SelfDeaf -} - -// Guild returns the Guild of this VoiceState. -// This will only check cached guilds! -func (s *VoiceState) Guild() *Guild { - return s.Bot.Caches.Guilds().Get(s.GuildID) -} - -// Channel returns the Channel of this VoiceState from the Caches -func (s *VoiceState) Channel() GuildAudioChannel { - if s.ChannelID == nil { - return nil - } - if ch := s.Bot.Caches.Channels().Get(*s.ChannelID); ch != nil { - return ch.(GuildAudioChannel) - } - return nil -} - -func (s *VoiceState) Update(suppress *bool, requestToSpeak *discord.NullTime, opts ...rest.RequestOpt) error { - if s.ChannelID == nil { - return discord.ErrMemberMustBeConnectedToChannel - } - userVoiceUpdate := discord.UserVoiceStateUpdate{ChannelID: *s.ChannelID, Suppress: suppress, RequestToSpeakTimestamp: requestToSpeak} - if s.UserID == s.Bot.ClientID { - return s.Bot.RestServices.GuildService().UpdateCurrentUserVoiceState(s.GuildID, userVoiceUpdate, opts...) - } - return s.Bot.RestServices.GuildService().UpdateUserVoiceState(s.GuildID, s.UserID, userVoiceUpdate, opts...) -} diff --git a/core/webhook.go b/core/webhook.go deleted file mode 100644 index 87db83ac..00000000 --- a/core/webhook.go +++ /dev/null @@ -1,62 +0,0 @@ -package core - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/disgo/webhook" -) - -type Webhook interface { - discord.Webhook -} - -type IncomingWebhook struct { - discord.IncomingWebhook - Bot *Bot - User *User -} - -func (h *IncomingWebhook) URL() string { - compiledRoute, _ := route.WebhookURL.Compile(nil, h.ID(), h.Token) - return compiledRoute.URL() -} - -func (h *IncomingWebhook) Update(webhookUpdate discord.WebhookUpdate, opts ...rest.RequestOpt) (*IncomingWebhook, error) { - wh, err := h.Bot.RestServices.WebhookService().UpdateWebhook(h.ID(), webhookUpdate, opts...) - if err != nil { - return nil, err - } - return h.Bot.EntityBuilder.CreateWebhook(wh, CacheStrategyNoWs).(*IncomingWebhook), nil -} - -func (h *IncomingWebhook) Delete(opts ...rest.RequestOpt) error { - return h.Bot.RestServices.WebhookService().DeleteWebhook(h.ID(), opts...) -} - -func (h *IncomingWebhook) NewWebhookClient(opts ...webhook.ConfigOpt) *webhook.Client { - return webhook.NewClient(h.ID(), h.Token, append(opts, webhook.WithRestClient(h.Bot.RestServices.RestClient()), webhook.WithLogger(h.Bot.Logger))...) -} - -type ChannelFollowerWebhook struct { - discord.ChannelFollowerWebhook - Bot *Bot - User *User -} - -func (h *ChannelFollowerWebhook) Update(webhookUpdate discord.WebhookUpdate, opts ...rest.RequestOpt) (*ChannelFollowerWebhook, error) { - wh, err := h.Bot.RestServices.WebhookService().UpdateWebhook(h.ID(), webhookUpdate, opts...) - if err != nil { - return nil, err - } - return h.Bot.EntityBuilder.CreateWebhook(wh, CacheStrategyNoWs).(*ChannelFollowerWebhook), nil -} - -func (h *ChannelFollowerWebhook) Delete(opts ...rest.RequestOpt) error { - return h.Bot.RestServices.WebhookService().DeleteWebhook(h.ID(), opts...) -} - -type ApplicationWebhook struct { - discord.ApplicationWebhook - Bot *Bot -} diff --git a/discord/access_token.go b/discord/access_token.go index 40827d8e..0bf88cca 100644 --- a/discord/access_token.go +++ b/discord/access_token.go @@ -3,7 +3,7 @@ package discord import ( "time" - "github.com/DisgoOrg/disgo/json" + "github.com/disgoorg/disgo/json" ) type AccessTokenExchange struct { diff --git a/discord/activity.go b/discord/activity.go index 8ce581de..90c3c923 100644 --- a/discord/activity.go +++ b/discord/activity.go @@ -1,12 +1,11 @@ package discord -import "github.com/DisgoOrg/snowflake" +import "github.com/disgoorg/snowflake" // ActivityType represents the status of a user, one of Game, Streaming, Listening, Watching, Custom or Competing type ActivityType int // Constants for Activity(s) -//goland:noinspection GoUnusedConst const ( ActivityTypeGame ActivityType = iota ActivityTypeStreaming diff --git a/discord/allowed_mentions.go b/discord/allowed_mentions.go index 0b83ad11..abc79330 100644 --- a/discord/allowed_mentions.go +++ b/discord/allowed_mentions.go @@ -1,6 +1,6 @@ package discord -import "github.com/DisgoOrg/snowflake" +import "github.com/disgoorg/snowflake" // DefaultAllowedMentions gives you the default AllowedMentions for a Message var DefaultAllowedMentions = AllowedMentions{ diff --git a/discord/application.go b/discord/application.go index 87be4a5d..2fe210d3 100644 --- a/discord/application.go +++ b/discord/application.go @@ -4,7 +4,8 @@ import ( "fmt" "strings" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) type Application struct { @@ -27,10 +28,18 @@ type Application struct { GuildID *snowflake.Snowflake `json:"guild_id,omitempty"` PrimarySkuID *snowflake.Snowflake `json:"primary_sku_id,omitempty"` Slug *string `json:"slug,omitempty"` - CoverImage *string `json:"cover_image,omitempty"` + Cover *string `json:"cover_image,omitempty"` Flags ApplicationFlags `json:"flags,omitempty"` } +func (a Application) IconURL(opts ...CDNOpt) *string { + return formatAssetURL(route.ApplicationIcon, opts, a.ID, a.Icon) +} + +func (a Application) CoverURL(opts ...CDNOpt) *string { + return formatAssetURL(route.ApplicationCover, opts, a.ID, a.Cover) +} + type PartialApplication struct { ID snowflake.Snowflake `json:"id"` Flags ApplicationFlags `json:"flags"` @@ -50,7 +59,6 @@ type InstallationParams struct { type ApplicationScope string -//goland:noinspection GoUnusedConst const ( ApplicationScopeActivitiesWrite ApplicationScope = "activities.write" ApplicationScopeActivitiesRead ApplicationScope = "activities.read" @@ -114,7 +122,6 @@ func HasScope(scope ApplicationScope, scopes ...ApplicationScope) bool { type TokenType string -//goland:noinspection GoUnusedConst const ( TokenTypeBearer TokenType = "Bearer" TokenTypeBot TokenType = "Bot" @@ -131,7 +138,6 @@ func (t TokenType) Apply(token string) string { // ApplicationFlags (https://discord.com/developers/docs/resources/application#application-object-application-flags) type ApplicationFlags int -//goland:noinspection GoUnusedConst const ( ApplicationFlagGatewayPresence = 1 << (iota + 12) ApplicationFlagGatewayPresenceLimited @@ -179,12 +185,16 @@ func (f ApplicationFlags) Missing(bits ...ApplicationFlags) bool { type Team struct { Icon *string `json:"icon"` - ID string `json:"id"` + ID snowflake.Snowflake `json:"id"` Members []TeamMember `json:"members"` Name string `json:"name"` OwnerID snowflake.Snowflake `json:"owner_user_id"` } +func (t Team) IconURL(opts ...CDNOpt) *string { + return formatAssetURL(route.TeamIcon, opts, t.ID, t.Icon) +} + type TeamMember struct { MembershipState MembershipState `json:"membership_state"` Permissions []TeamPermissions `json:"permissions"` @@ -194,7 +204,6 @@ type TeamMember struct { type MembershipState int -//goland:noinspection GoUnusedConst,GoUnusedConst const ( MembershipStateInvited = iota + 1 MembershipStateAccepted @@ -202,7 +211,6 @@ const ( type TeamPermissions string -//goland:noinspection GoUnusedConst const ( TeamPermissionAdmin = "*" ) diff --git a/discord/application_command.go b/discord/application_command.go index 8f98bd96..995d6a92 100644 --- a/discord/application_command.go +++ b/discord/application_command.go @@ -3,13 +3,12 @@ package discord import ( "fmt" - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" ) type ApplicationCommandType int -//goland:noinspection GoUnusedConst const ( ApplicationCommandTypeSlash = iota + 1 ApplicationCommandTypeUser @@ -18,9 +17,15 @@ const ( type ApplicationCommand interface { json.Marshaler - Type() ApplicationCommandType ID() snowflake.Snowflake + Type() ApplicationCommandType + ApplicationID() snowflake.Snowflake + GuildID() *snowflake.Snowflake Name() string + NameLocalizations() map[Locale]string + NameLocalized() string + DefaultPermission() bool + Version() snowflake.Snowflake applicationCommand() } @@ -73,59 +78,93 @@ func (u *UnmarshalApplicationCommand) UnmarshalJSON(data []byte) error { var _ ApplicationCommand = (*SlashCommand)(nil) type SlashCommand struct { - CommandID snowflake.Snowflake `json:"id"` - ApplicationID snowflake.Snowflake `json:"application_id"` - GuildID *snowflake.Snowflake `json:"guild_id,omitempty"` - CommandName string `json:"name"` - Description string `json:"description,omitempty"` - Options []ApplicationCommandOption `json:"options,omitempty"` - DefaultPermission bool `json:"default_permission,omitempty"` - Version snowflake.Snowflake `json:"version"` -} - -func (c SlashCommand) MarshalJSON() ([]byte, error) { - type slashCommand SlashCommand - return json.Marshal(struct { - Type ApplicationCommandType `json:"type"` - slashCommand - }{ - Type: c.Type(), - slashCommand: slashCommand(c), - }) + id snowflake.Snowflake + applicationID snowflake.Snowflake + guildID *snowflake.Snowflake + name string + nameLocalizations map[Locale]string + nameLocalized string + Description string + DescriptionLocalizations map[Locale]string + DescriptionLocalized string + Options []ApplicationCommandOption + defaultPermission bool + version snowflake.Snowflake } func (c *SlashCommand) UnmarshalJSON(data []byte) error { - type slashCommand SlashCommand - var sc struct { - Options []UnmarshalApplicationCommandOption `json:"options,omitempty"` - slashCommand - } - - if err := json.Unmarshal(data, &sc); err != nil { + var v rawSlashCommand + if err := json.Unmarshal(data, &v); err != nil { return err } - *c = SlashCommand(sc.slashCommand) - - if len(sc.Options) > 0 { - c.Options = make([]ApplicationCommandOption, len(sc.Options)) - for i := range sc.Options { - c.Options[i] = sc.Options[i].ApplicationCommandOption - } - } + c.id = v.ID + c.applicationID = v.ApplicationID + c.guildID = v.GuildID + c.name = v.Name + c.nameLocalizations = v.NameLocalizations + c.nameLocalized = v.NameLocalized + c.Description = v.Description + c.DescriptionLocalizations = v.DescriptionLocalizations + c.DescriptionLocalized = v.DescriptionLocalized + c.Options = v.Options + c.defaultPermission = v.DefaultPermission + c.version = v.Version return nil } +func (c SlashCommand) MarshalJSON() ([]byte, error) { + return json.Marshal(rawSlashCommand{ + ID: c.id, + Type: c.Type(), + ApplicationID: c.applicationID, + GuildID: c.guildID, + Name: c.name, + NameLocalizations: c.nameLocalizations, + NameLocalized: c.nameLocalized, + Description: c.Description, + DescriptionLocalizations: c.DescriptionLocalizations, + DescriptionLocalized: c.DescriptionLocalized, + Options: c.Options, + DefaultPermission: c.defaultPermission, + Version: c.version, + }) +} + func (c SlashCommand) ID() snowflake.Snowflake { - return c.CommandID + return c.id } func (SlashCommand) Type() ApplicationCommandType { return ApplicationCommandTypeSlash } +func (c SlashCommand) ApplicationID() snowflake.Snowflake { + return c.applicationID +} + +func (c SlashCommand) GuildID() *snowflake.Snowflake { + return c.guildID +} + func (c SlashCommand) Name() string { - return c.CommandName + return c.name +} + +func (c SlashCommand) NameLocalizations() map[Locale]string { + return c.nameLocalizations +} + +func (c SlashCommand) NameLocalized() string { + return c.nameLocalized +} + +func (c SlashCommand) DefaultPermission() bool { + return c.defaultPermission +} + +func (c SlashCommand) Version() snowflake.Snowflake { + return c.version } func (SlashCommand) applicationCommand() {} @@ -133,35 +172,81 @@ func (SlashCommand) applicationCommand() {} var _ ApplicationCommand = (*UserCommand)(nil) type UserCommand struct { - CommandID snowflake.Snowflake `json:"id"` - ApplicationID snowflake.Snowflake `json:"application_id"` - GuildID *snowflake.Snowflake `json:"guild_id,omitempty"` - CommandName string `json:"name"` - DefaultPermission bool `json:"default_permission,omitempty"` - Version snowflake.Snowflake `json:"version"` + id snowflake.Snowflake + applicationID snowflake.Snowflake + guildID *snowflake.Snowflake + name string + nameLocalizations map[Locale]string + nameLocalized string + defaultPermission bool + version snowflake.Snowflake +} + +func (c *UserCommand) UnmarshalJSON(data []byte) error { + var v rawContextCommand + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + c.id = v.ID + c.applicationID = v.ApplicationID + c.guildID = v.GuildID + c.name = v.Name + c.nameLocalizations = v.NameLocalizations + c.nameLocalized = v.NameLocalized + c.defaultPermission = v.DefaultPermission + c.version = v.Version + return nil } func (c UserCommand) MarshalJSON() ([]byte, error) { - type userCommand UserCommand - return json.Marshal(struct { - Type ApplicationCommandType `json:"type"` - userCommand - }{ - Type: c.Type(), - userCommand: userCommand(c), + return json.Marshal(rawContextCommand{ + ID: c.id, + Type: c.Type(), + ApplicationID: c.applicationID, + GuildID: c.guildID, + Name: c.name, + NameLocalizations: c.nameLocalizations, + NameLocalized: c.nameLocalized, + DefaultPermission: c.defaultPermission, + Version: c.version, }) } func (c UserCommand) ID() snowflake.Snowflake { - return c.CommandID + return c.id } func (c UserCommand) Type() ApplicationCommandType { return ApplicationCommandTypeUser } +func (c UserCommand) ApplicationID() snowflake.Snowflake { + return c.applicationID +} + +func (c UserCommand) GuildID() *snowflake.Snowflake { + return c.guildID +} + func (c UserCommand) Name() string { - return c.CommandName + return c.name +} + +func (c UserCommand) NameLocalizations() map[Locale]string { + return c.nameLocalizations +} + +func (c UserCommand) NameLocalized() string { + return c.nameLocalized +} + +func (c UserCommand) DefaultPermission() bool { + return c.defaultPermission +} + +func (c UserCommand) Version() snowflake.Snowflake { + return c.version } func (UserCommand) applicationCommand() {} @@ -169,35 +254,81 @@ func (UserCommand) applicationCommand() {} var _ ApplicationCommand = (*MessageCommand)(nil) type MessageCommand struct { - CommandID snowflake.Snowflake `json:"id"` - ApplicationID snowflake.Snowflake `json:"application_id"` - GuildID *snowflake.Snowflake `json:"guild_id,omitempty"` - CommandName string `json:"name"` - DefaultPermission bool `json:"default_permission,omitempty"` - Version snowflake.Snowflake `json:"version"` + id snowflake.Snowflake + applicationID snowflake.Snowflake + guildID *snowflake.Snowflake + name string + nameLocalizations map[Locale]string + nameLocalized string + defaultPermission bool + version snowflake.Snowflake +} + +func (c *MessageCommand) UnmarshalJSON(data []byte) error { + var v rawContextCommand + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + c.id = v.ID + c.applicationID = v.ApplicationID + c.guildID = v.GuildID + c.name = v.Name + c.nameLocalizations = v.NameLocalizations + c.nameLocalized = v.NameLocalized + c.defaultPermission = v.DefaultPermission + c.version = v.Version + return nil } func (c MessageCommand) MarshalJSON() ([]byte, error) { - type messageCommand MessageCommand - return json.Marshal(struct { - Type ApplicationCommandType `json:"type"` - messageCommand - }{ - Type: c.Type(), - messageCommand: messageCommand(c), + return json.Marshal(rawContextCommand{ + ID: c.id, + Type: c.Type(), + ApplicationID: c.applicationID, + GuildID: c.guildID, + Name: c.name, + NameLocalizations: c.nameLocalizations, + NameLocalized: c.nameLocalized, + DefaultPermission: c.defaultPermission, + Version: c.version, }) } func (c MessageCommand) ID() snowflake.Snowflake { - return c.CommandID + return c.id } func (MessageCommand) Type() ApplicationCommandType { return ApplicationCommandTypeMessage } +func (c MessageCommand) ApplicationID() snowflake.Snowflake { + return c.applicationID +} + +func (c MessageCommand) GuildID() *snowflake.Snowflake { + return c.guildID +} + func (c MessageCommand) Name() string { - return c.CommandName + return c.name +} + +func (c MessageCommand) NameLocalizations() map[Locale]string { + return c.nameLocalizations +} + +func (c MessageCommand) NameLocalized() string { + return c.nameLocalized +} + +func (c MessageCommand) DefaultPermission() bool { + return c.defaultPermission +} + +func (c MessageCommand) Version() snowflake.Snowflake { + return c.version } func (MessageCommand) applicationCommand() {} diff --git a/discord/application_command_autocomplete_option.go b/discord/application_command_autocomplete_option.go index d1a6aa80..373f6dd1 100644 --- a/discord/application_command_autocomplete_option.go +++ b/discord/application_command_autocomplete_option.go @@ -3,8 +3,8 @@ package discord import ( "fmt" - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" ) type AutocompleteOption interface { @@ -98,7 +98,7 @@ func (o *UnmarshalAutocompleteOption) UnmarshalJSON(data []byte) error { var _ AutocompleteOption = (*AutocompleteOptionSubCommand)(nil) type AutocompleteOptionSubCommand struct { - CommandName string `json:"name"` + OptionName string `json:"name"` Description string `json:"description"` Options []AutocompleteOption `json:"options,omitempty"` } @@ -131,7 +131,7 @@ func (AutocompleteOptionSubCommand) Type() ApplicationCommandOptionType { } func (o AutocompleteOptionSubCommand) Name() string { - return o.CommandName + return o.OptionName } func (o AutocompleteOptionSubCommand) Focused() bool { @@ -141,7 +141,7 @@ func (o AutocompleteOptionSubCommand) Focused() bool { var _ AutocompleteOption = (*AutocompleteOptionSubCommandGroup)(nil) type AutocompleteOptionSubCommandGroup struct { - GroupName string `json:"name"` + OptionName string `json:"name"` Description string `json:"description"` Options []AutocompleteOptionSubCommand `json:"options,omitempty"` } @@ -152,7 +152,7 @@ func (AutocompleteOptionSubCommandGroup) Type() ApplicationCommandOptionType { } func (o AutocompleteOptionSubCommandGroup) Name() string { - return o.GroupName + return o.OptionName } func (o AutocompleteOptionSubCommandGroup) Focused() bool { diff --git a/discord/application_command_create.go b/discord/application_command_create.go index 59831766..d655032f 100644 --- a/discord/application_command_create.go +++ b/discord/application_command_create.go @@ -1,6 +1,6 @@ package discord -import "github.com/DisgoOrg/disgo/json" +import "github.com/disgoorg/disgo/json" type ApplicationCommandCreate interface { json.Marshaler @@ -10,10 +10,12 @@ type ApplicationCommandCreate interface { } type SlashCommandCreate struct { - CommandName string `json:"name"` - Description string `json:"description"` - Options []ApplicationCommandOption `json:"options"` - DefaultPermission bool `json:"default_permission"` + CommandName string `json:"name"` + CommandNameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[Locale]string `json:"description_localizations,omitempty"` + Options []ApplicationCommandOption `json:"options"` + DefaultPermission bool `json:"default_permission"` } func (c SlashCommandCreate) MarshalJSON() ([]byte, error) { @@ -38,8 +40,9 @@ func (c SlashCommandCreate) Name() string { func (SlashCommandCreate) applicationCommandCreate() {} type UserCommandCreate struct { - CommandName string `json:"name"` - DefaultPermission bool `json:"default_permission"` + CommandName string `json:"name"` + CommandNameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + DefaultPermission bool `json:"default_permission"` } func (c UserCommandCreate) MarshalJSON() ([]byte, error) { @@ -64,8 +67,9 @@ func (c UserCommandCreate) Name() string { func (UserCommandCreate) applicationCommandCreate() {} type MessageCommandCreate struct { - CommandName string `json:"name"` - DefaultPermission bool `json:"default_permission"` + CommandName string `json:"name"` + CommandNameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + DefaultPermission bool `json:"default_permission"` } func (c MessageCommandCreate) MarshalJSON() ([]byte, error) { diff --git a/discord/application_command_option.go b/discord/application_command_option.go index 8da72778..a2273a06 100644 --- a/discord/application_command_option.go +++ b/discord/application_command_option.go @@ -3,14 +3,13 @@ package discord import ( "fmt" - "github.com/DisgoOrg/disgo/json" + "github.com/disgoorg/disgo/json" ) // ApplicationCommandOptionType specifies the type of the arguments used in ApplicationCommand.Options type ApplicationCommandOptionType int // Constants for each slash command option type -//goland:noinspection GoUnusedConst const ( ApplicationCommandOptionTypeSubCommand ApplicationCommandOptionType = iota + 1 ApplicationCommandOptionTypeSubCommandGroup @@ -120,9 +119,11 @@ func (u *UnmarshalApplicationCommandOption) UnmarshalJSON(data []byte) error { var _ ApplicationCommandOption = (*ApplicationCommandOptionSubCommand)(nil) type ApplicationCommandOptionSubCommand struct { - Name string `json:"name"` - Description string `json:"description"` - Options []ApplicationCommandOption `json:"options,omitempty"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[Locale]string `json:"description_localizations,omitempty"` + Options []ApplicationCommandOption `json:"options,omitempty"` } func (o ApplicationCommandOptionSubCommand) MarshalJSON() ([]byte, error) { @@ -166,9 +167,11 @@ func (ApplicationCommandOptionSubCommand) Type() ApplicationCommandOptionType { var _ ApplicationCommandOption = (*ApplicationCommandOptionSubCommandGroup)(nil) type ApplicationCommandOptionSubCommandGroup struct { - Name string `json:"name"` - Description string `json:"description"` - Options []ApplicationCommandOptionSubCommand `json:"options,omitempty"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[Locale]string `json:"description_localizations,omitempty"` + Options []ApplicationCommandOptionSubCommand `json:"options,omitempty"` } func (o ApplicationCommandOptionSubCommandGroup) MarshalJSON() ([]byte, error) { @@ -190,11 +193,13 @@ func (ApplicationCommandOptionSubCommandGroup) Type() ApplicationCommandOptionTy var _ ApplicationCommandOption = (*ApplicationCommandOptionString)(nil) type ApplicationCommandOptionString struct { - Name string `json:"name"` - Description string `json:"description"` - Required bool `json:"required,omitempty"` - Choices []ApplicationCommandOptionChoiceString `json:"choices,omitempty"` - Autocomplete bool `json:"autocomplete,omitempty"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[Locale]string `json:"description_localizations,omitempty"` + Required bool `json:"required,omitempty"` + Choices []ApplicationCommandOptionChoiceString `json:"choices,omitempty"` + Autocomplete bool `json:"autocomplete,omitempty"` } func (o ApplicationCommandOptionString) MarshalJSON() ([]byte, error) { @@ -216,13 +221,15 @@ func (ApplicationCommandOptionString) Type() ApplicationCommandOptionType { var _ ApplicationCommandOption = (*ApplicationCommandOptionInt)(nil) type ApplicationCommandOptionInt struct { - Name string `json:"name"` - Description string `json:"description"` - Required bool `json:"required,omitempty"` - Choices []ApplicationCommandOptionChoiceInt `json:"choices,omitempty"` - Autocomplete bool `json:"autocomplete,omitempty"` - MinValue *json.NullInt `json:"min_value,omitempty"` - MaxValue *json.NullInt `json:"max_value,omitempty"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[Locale]string `json:"description_localizations,omitempty"` + Required bool `json:"required,omitempty"` + Choices []ApplicationCommandOptionChoiceInt `json:"choices,omitempty"` + Autocomplete bool `json:"autocomplete,omitempty"` + MinValue *int `json:"min_value,omitempty"` + MaxValue *int `json:"max_value,omitempty"` } func (o ApplicationCommandOptionInt) MarshalJSON() ([]byte, error) { @@ -244,9 +251,11 @@ func (ApplicationCommandOptionInt) Type() ApplicationCommandOptionType { var _ ApplicationCommandOption = (*ApplicationCommandOptionBool)(nil) type ApplicationCommandOptionBool struct { - Name string `json:"name"` - Description string `json:"description"` - Required bool `json:"required,omitempty"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[Locale]string `json:"description_localizations,omitempty"` + Required bool `json:"required,omitempty"` } func (o ApplicationCommandOptionBool) MarshalJSON() ([]byte, error) { @@ -268,9 +277,11 @@ func (ApplicationCommandOptionBool) Type() ApplicationCommandOptionType { var _ ApplicationCommandOption = (*ApplicationCommandOptionUser)(nil) type ApplicationCommandOptionUser struct { - Name string `json:"name"` - Description string `json:"description"` - Required bool `json:"required,omitempty"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[Locale]string `json:"description_localizations,omitempty"` + Required bool `json:"required,omitempty"` } func (o ApplicationCommandOptionUser) MarshalJSON() ([]byte, error) { @@ -292,10 +303,12 @@ func (ApplicationCommandOptionUser) Type() ApplicationCommandOptionType { var _ ApplicationCommandOption = (*ApplicationCommandOptionChannel)(nil) type ApplicationCommandOptionChannel struct { - Name string `json:"name"` - Description string `json:"description"` - Required bool `json:"required,omitempty"` - ChannelTypes []ChannelType `json:"channel_types,omitempty"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[Locale]string `json:"description_localizations,omitempty"` + Required bool `json:"required,omitempty"` + ChannelTypes []ChannelType `json:"channel_types,omitempty"` } func (o ApplicationCommandOptionChannel) MarshalJSON() ([]byte, error) { @@ -317,9 +330,11 @@ func (ApplicationCommandOptionChannel) Type() ApplicationCommandOptionType { var _ ApplicationCommandOption = (*ApplicationCommandOptionRole)(nil) type ApplicationCommandOptionRole struct { - Name string `json:"name"` - Description string `json:"description"` - Required bool `json:"required,omitempty"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[Locale]string `json:"description_localizations,omitempty"` + Required bool `json:"required,omitempty"` } func (o ApplicationCommandOptionRole) MarshalJSON() ([]byte, error) { @@ -341,9 +356,11 @@ func (ApplicationCommandOptionRole) Type() ApplicationCommandOptionType { var _ ApplicationCommandOption = (*ApplicationCommandOptionMentionable)(nil) type ApplicationCommandOptionMentionable struct { - Name string `json:"name"` - Description string `json:"description"` - Required bool `json:"required,omitempty"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[Locale]string `json:"description_localizations,omitempty"` + Required bool `json:"required,omitempty"` } func (o ApplicationCommandOptionMentionable) MarshalJSON() ([]byte, error) { @@ -365,13 +382,15 @@ func (ApplicationCommandOptionMentionable) Type() ApplicationCommandOptionType { var _ ApplicationCommandOption = (*ApplicationCommandOptionFloat)(nil) type ApplicationCommandOptionFloat struct { - Name string `json:"name"` - Description string `json:"description"` - Required bool `json:"required,omitempty"` - Choices []ApplicationCommandOptionChoiceFloat `json:"choices,omitempty"` - Autocomplete bool `json:"autocomplete,omitempty"` - MinValue *json.NullFloat `json:"min_value,omitempty"` - MaxValue *json.NullFloat `json:"max_value,omitempty"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[Locale]string `json:"description_localizations,omitempty"` + Required bool `json:"required,omitempty"` + Choices []ApplicationCommandOptionChoiceFloat `json:"choices,omitempty"` + Autocomplete bool `json:"autocomplete,omitempty"` + MinValue *float64 `json:"min_value,omitempty"` + MaxValue *float64 `json:"max_value,omitempty"` } func (o ApplicationCommandOptionFloat) MarshalJSON() ([]byte, error) { @@ -397,8 +416,9 @@ type ApplicationCommandOptionChoice interface { var _ ApplicationCommandOptionChoice = (*ApplicationCommandOptionChoiceInt)(nil) type ApplicationCommandOptionChoiceInt struct { - Name string `json:"name"` - Value int `json:"value"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Value int `json:"value"` } func (ApplicationCommandOptionChoiceInt) applicationCommandOptionChoice() {} @@ -406,8 +426,9 @@ func (ApplicationCommandOptionChoiceInt) applicationCommandOptionChoice() {} var _ ApplicationCommandOptionChoice = (*ApplicationCommandOptionChoiceString)(nil) type ApplicationCommandOptionChoiceString struct { - Name string `json:"name"` - Value string `json:"value"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Value string `json:"value"` } func (ApplicationCommandOptionChoiceString) applicationCommandOptionChoice() {} @@ -415,16 +436,19 @@ func (ApplicationCommandOptionChoiceString) applicationCommandOptionChoice() {} var _ ApplicationCommandOptionChoice = (*ApplicationCommandOptionChoiceInt)(nil) type ApplicationCommandOptionChoiceFloat struct { - Name string `json:"name"` - Value float64 `json:"value"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Value float64 `json:"value"` } func (ApplicationCommandOptionChoiceFloat) applicationCommandOptionChoice() {} type ApplicationCommandOptionAttachment struct { - Name string `json:"name"` - Description string `json:"description"` - Required bool `json:"required,omitempty"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Description string `json:"description"` + DescriptionLocalizations map[Locale]string `json:"description_localizations,omitempty"` + Required bool `json:"required,omitempty"` } func (o ApplicationCommandOptionAttachment) MarshalJSON() ([]byte, error) { diff --git a/discord/application_command_permission.go b/discord/application_command_permission.go index 5ba0b7c6..74850668 100644 --- a/discord/application_command_permission.go +++ b/discord/application_command_permission.go @@ -3,15 +3,14 @@ package discord import ( "fmt" - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" ) // ApplicationCommandPermissionType is the type of the ApplicationCommandPermission type ApplicationCommandPermissionType int // types of ApplicationCommandPermissionType -//goland:noinspection GoUnusedConst const ( ApplicationCommandPermissionTypeRole = iota + 1 ApplicationCommandPermissionTypeUser diff --git a/discord/application_command_raw.go b/discord/application_command_raw.go new file mode 100644 index 00000000..4940cbfb --- /dev/null +++ b/discord/application_command_raw.go @@ -0,0 +1,56 @@ +package discord + +import ( + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" +) + +type rawSlashCommand struct { + ID snowflake.Snowflake `json:"id"` + Type ApplicationCommandType `json:"type"` + ApplicationID snowflake.Snowflake `json:"application_id"` + GuildID *snowflake.Snowflake `json:"guild_id,omitempty"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + NameLocalized string `json:"name_localized,omitempty"` + Description string `json:"description,omitempty"` + DescriptionLocalizations map[Locale]string `json:"description_localizations,omitempty"` + DescriptionLocalized string `json:"description_localized,omitempty"` + Options []ApplicationCommandOption `json:"options,omitempty"` + DefaultPermission bool `json:"default_permission,omitempty"` + Version snowflake.Snowflake `json:"version"` +} + +func (c *rawSlashCommand) UnmarshalJSON(data []byte) error { + type alias rawSlashCommand + var sc struct { + Options []UnmarshalApplicationCommandOption `json:"options,omitempty"` + alias + } + + if err := json.Unmarshal(data, &sc); err != nil { + return err + } + + *c = rawSlashCommand(sc.alias) + + if len(sc.Options) > 0 { + c.Options = make([]ApplicationCommandOption, len(sc.Options)) + for i := range sc.Options { + c.Options[i] = sc.Options[i].ApplicationCommandOption + } + } + return nil +} + +type rawContextCommand struct { + ID snowflake.Snowflake `json:"id"` + Type ApplicationCommandType `json:"type"` + ApplicationID snowflake.Snowflake `json:"application_id"` + GuildID *snowflake.Snowflake `json:"guild_id,omitempty"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + NameLocalized string `json:"name_localized,omitempty"` + DefaultPermission bool `json:"default_permission,omitempty"` + Version snowflake.Snowflake `json:"version"` +} diff --git a/discord/application_command_update.go b/discord/application_command_update.go index b3910f69..4f7216ba 100644 --- a/discord/application_command_update.go +++ b/discord/application_command_update.go @@ -1,18 +1,21 @@ package discord -import "github.com/DisgoOrg/disgo/json" +import "github.com/disgoorg/disgo/json" type ApplicationCommandUpdate interface { json.Marshaler Type() ApplicationCommandType + Name() *string applicationCommandUpdate() } type SlashCommandUpdate struct { - Name *string `json:"name,omitempty"` - Description *string `json:"description,omitempty"` - Options *[]ApplicationCommandOption `json:"options,omitempty"` - DefaultPermission *bool `json:"default_permission,omitempty"` + CommandName *string `json:"name,omitempty"` + CommandNameLocalizations *map[Locale]string `json:"name_localizations,omitempty"` + Description *string `json:"description,omitempty"` + DescriptionLocalizations *map[Locale]string `json:"description_localizations,omitempty"` + Options *[]ApplicationCommandOption `json:"options,omitempty"` + DefaultPermission *bool `json:"default_permission,omitempty"` } func (c SlashCommandUpdate) MarshalJSON() ([]byte, error) { @@ -30,11 +33,16 @@ func (SlashCommandUpdate) Type() ApplicationCommandType { return ApplicationCommandTypeSlash } +func (c SlashCommandUpdate) Name() *string { + return c.CommandName +} + func (SlashCommandUpdate) applicationCommandUpdate() {} type UserCommandUpdate struct { - Name *string `json:"name"` - DefaultPermission *bool `json:"default_permission,omitempty"` + CommandName *string `json:"name"` + CommandNameLocalizations *map[Locale]string `json:"name_localizations,omitempty"` + DefaultPermission *bool `json:"default_permission,omitempty"` } func (c UserCommandUpdate) MarshalJSON() ([]byte, error) { @@ -52,11 +60,16 @@ func (UserCommandUpdate) Type() ApplicationCommandType { return ApplicationCommandTypeUser } +func (c UserCommandUpdate) Name() *string { + return c.CommandName +} + func (UserCommandUpdate) applicationCommandUpdate() {} type MessageCommandUpdate struct { - Name *string `json:"name"` - DefaultPermission *bool `json:"default_permission,omitempty"` + CommandName *string `json:"name"` + CommandNameLocalizations *map[Locale]string `json:"name_localizations,omitempty"` + DefaultPermission *bool `json:"default_permission,omitempty"` } func (c MessageCommandUpdate) MarshalJSON() ([]byte, error) { @@ -74,4 +87,8 @@ func (MessageCommandUpdate) Type() ApplicationCommandType { return ApplicationCommandTypeMessage } +func (c MessageCommandUpdate) Name() *string { + return c.CommandName +} + func (MessageCommandUpdate) applicationCommandUpdate() {} diff --git a/discord/asset.go b/discord/asset.go new file mode 100644 index 00000000..15c9c835 --- /dev/null +++ b/discord/asset.go @@ -0,0 +1,82 @@ +package discord + +import ( + "strings" + + "github.com/disgoorg/disgo/rest/route" +) + +func DefaultCDNConfig() *CDNConfig { + return &CDNConfig{ + Size: 0, + Format: route.PNG, + } +} + +type CDNConfig struct { + Size int + Format route.ImageFormat + V int +} + +// Apply applies the given ConfigOpt(s) to the Config +func (c *CDNConfig) Apply(opts []CDNOpt) { + for _, opt := range opts { + opt(c) + } +} + +type CDNOpt func(config *CDNConfig) + +func WithSize(size int) CDNOpt { + return func(config *CDNConfig) { + config.Size = size + } +} + +func WithFormat(format route.ImageFormat) CDNOpt { + return func(config *CDNConfig) { + config.Format = format + } +} + +func WithV(v int) CDNOpt { + return func(config *CDNConfig) { + config.V = v + } +} + +func formatAssetURL(cdnRoute *route.CDNRoute, opts []CDNOpt, params ...any) *string { + var lastStringParam string + lastParam := params[len(params)-1] + if str, ok := lastParam.(string); ok { + if str == "" { + return nil + } + lastStringParam = str + } else if ptrStr, ok := lastParam.(*string); ok { + if ptrStr == nil { + return nil + } + lastStringParam = *ptrStr + } + + config := DefaultCDNConfig() + config.Apply(opts) + + if strings.HasPrefix(lastStringParam, "a_") && !config.Format.CanBeAnimated() { + config.Format = route.GIF + } + + queryValues := route.QueryValues{} + if config.V > 0 { + queryValues["v"] = config.V + } + + compiledRoute, err := cdnRoute.Compile(queryValues, config.Format, config.Size, params...) + if err != nil { + return nil + } + url := compiledRoute.URL() + return &url +} diff --git a/discord/attachement.go b/discord/attachement.go deleted file mode 100644 index 13ca157d..00000000 --- a/discord/attachement.go +++ /dev/null @@ -1,15 +0,0 @@ -package discord - -import "github.com/DisgoOrg/snowflake" - -//Attachment is used for files sent in a Message -type Attachment struct { - ID snowflake.Snowflake `json:"id,omitempty"` - Filename string `json:"filename"` - Size int `json:"size"` - URL string `json:"url"` - ProxyURL string `json:"proxy_url"` - Height *int `json:"height"` - Width *int `json:"width"` - Ephemeral bool `json:"ephemeral"` -} diff --git a/discord/attachment.go b/discord/attachment.go new file mode 100644 index 00000000..5cf1efb7 --- /dev/null +++ b/discord/attachment.go @@ -0,0 +1,34 @@ +package discord + +import "github.com/disgoorg/snowflake" + +//Attachment is used for files sent in a Message +type Attachment struct { + ID snowflake.Snowflake `json:"id,omitempty"` + Filename string `json:"filename,omitempty"` + Description *string `json:"description,omitempty"` + ContentType *string `json:"content_type,omitempty"` + Size int `json:"size,omitempty"` + URL string `json:"url,omitempty"` + ProxyURL string `json:"proxy_url,omitempty"` + Height *int `json:"height,omitempty"` + Width *int `json:"width,omitempty"` + Ephemeral bool `json:"ephemeral,omitempty"` +} + +type AttachmentUpdate interface { + attachmentUpdate() +} + +type AttachmentKeep struct { + ID snowflake.Snowflake `json:"id,omitempty"` +} + +func (AttachmentKeep) attachmentUpdate() {} + +type AttachmentCreate struct { + ID int `json:"id"` + Description string `json:"description"` +} + +func (AttachmentCreate) attachmentUpdate() {} diff --git a/discord/audit_log.go b/discord/audit_log.go index a722f903..acbdecd2 100644 --- a/discord/audit_log.go +++ b/discord/audit_log.go @@ -1,21 +1,19 @@ package discord import ( - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" ) // AuditLogEvent is an 8-bit unsigned integer representing an audit log event. type AuditLogEvent int // AuditLogEventGuildUpdate ... -//goland:noinspection GoUnusedConst const ( AuditLogEventGuildUpdate AuditLogEvent = 1 ) // AuditLogEventChannelCreate -//goland:noinspection GoUnusedConst const ( AuditLogEventChannelCreate AuditLogEvent = iota + 10 AuditLogEventChannelUpdate @@ -26,7 +24,6 @@ const ( ) // AuditLogEventMemberKick -//goland:noinspection GoUnusedConst const ( AuditLogEventMemberKick AuditLogEvent = iota + 20 AuditLogEventMemberPrune @@ -40,7 +37,6 @@ const ( ) // AuditLogEventRoleCreate -//goland:noinspection GoUnusedConst const ( AuditLogEventRoleCreate AuditLogEvent = iota + 30 AuditLogEventRoleUpdate @@ -48,7 +44,6 @@ const ( ) // AuditLogEventInviteCreate -//goland:noinspection GoUnusedConst const ( AuditLogEventInviteCreate AuditLogEvent = iota + 40 AuditLogEventInviteUpdate @@ -56,7 +51,6 @@ const ( ) // AuditLogEventWebhookCreate -//goland:noinspection GoUnusedConst const ( AuditLogEventWebhookCreate AuditLogEvent = iota + 50 AuditLogEventWebhookUpdate @@ -64,7 +58,6 @@ const ( ) // AuditLogEventEmojiCreate -//goland:noinspection GoUnusedConst const ( AuditLogEventEmojiCreate AuditLogEvent = iota + 60 AuditLogEventEmojiUpdate @@ -72,7 +65,6 @@ const ( ) // AuditLogEventMessageDelete -//goland:noinspection GoUnusedConst const ( AuditLogEventMessageDelete AuditLogEvent = iota + 72 AuditLogEventMessageBulkDelete @@ -81,7 +73,6 @@ const ( ) // AuditLogEventIntegrationCreate -//goland:noinspection GoUnusedConst const ( AuditLogEventIntegrationCreate AuditLogEvent = iota + 80 AuditLogEventIntegrationUpdate @@ -92,7 +83,6 @@ const ( ) // AuditLogEventStickerCreate -//goland:noinspection GoUnusedConst const ( AuditLogEventStickerCreate AuditLogEvent = iota + 90 AuditLogEventStickerUpdate @@ -100,7 +90,6 @@ const ( ) // AuditLogGuildScheduledEventCreate -//goland:noinspection GoUnusedConst const ( AuditLogGuildScheduledEventCreate AuditLogEvent = iota + 100 AuditLogGuildScheduledEventUpdate @@ -108,7 +97,6 @@ const ( ) // AuditLogThreadCreate -//goland:noinspection GoUnusedConst const ( AuditLogThreadCreate AuditLogEvent = iota + 100 AuditLogThreadUpdate @@ -224,7 +212,7 @@ type AuditLogChangeKey struct { Nick *string `json:"nick"` AvatarHash *string `json:"avatar_hash"` ID *snowflake.Snowflake `json:"id"` - Type interface{} `json:"type"` + Type any `json:"type"` EnableEmoticons *bool `json:"enable_emoticons"` ExpireBehavior *int `json:"expire_behavior"` ExpireGracePeriod *int `json:"expire_grace_period"` diff --git a/discord/channel.go b/discord/channel.go index 699a7c8a..e98c1277 100644 --- a/discord/channel.go +++ b/discord/channel.go @@ -3,16 +3,14 @@ package discord import ( "fmt" - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" ) // ChannelType for interacting with discord's channels type ChannelType int // Channel constants -//goland:noinspection GoUnusedConst const ( ChannelTypeGuildText ChannelType = iota ChannelTypeDM @@ -20,7 +18,7 @@ const ( ChannelTypeGroupDM ChannelTypeGuildCategory ChannelTypeGuildNews - ChannelTypeGuildStore + _ _ _ _ @@ -33,43 +31,52 @@ const ( type Channel interface { json.Marshaler fmt.Stringer + Type() ChannelType ID() snowflake.Snowflake Name() string + channel() } +type MessageChannel interface { + Channel + + LastMessageID() *snowflake.Snowflake + LastPinTimestamp() *Time + + messageChannel() +} + type GuildChannel interface { Channel Mentionable + GuildID() snowflake.Snowflake - guildChannel() -} + Position() int + ParentID() *snowflake.Snowflake + PermissionOverwrites() []PermissionOverwrite -type MessageChannel interface { - Channel - messageChannel() + guildChannel() } -type BaseGuildMessageChannel interface { +type GuildMessageChannel interface { GuildChannel MessageChannel - baseGuildMessageChannel() -} -type GuildMessageChannel interface { - BaseGuildMessageChannel - guildMessageChannel() -} + Topic() *string + NSFW() bool + DefaultAutoArchiveDuration() AutoArchiveDuration -type GuildThread interface { - BaseGuildMessageChannel - ParentID() snowflake.Snowflake - guildThread() + guildMessageChannel() } type GuildAudioChannel interface { GuildChannel + + Bitrate() int + RTCRegion() string + guildAudioChannel() } @@ -107,11 +114,6 @@ func (u *UnmarshalChannel) UnmarshalJSON(data []byte) error { err = json.Unmarshal(data, &v) channel = v - case ChannelTypeGroupDM: - var v GroupDMChannel - err = json.Unmarshal(data, &v) - channel = v - case ChannelTypeGuildCategory: var v GuildCategoryChannel err = json.Unmarshal(data, &v) @@ -122,23 +124,8 @@ func (u *UnmarshalChannel) UnmarshalJSON(data []byte) error { err = json.Unmarshal(data, &v) channel = v - case ChannelTypeGuildStore: - var v GuildStoreChannel - err = json.Unmarshal(data, &v) - channel = v - - case ChannelTypeGuildNewsThread: - var v GuildNewsThread - err = json.Unmarshal(data, &v) - channel = v - - case ChannelTypeGuildPublicThread: - var v GuildPublicThread - err = json.Unmarshal(data, &v) - channel = v - - case ChannelTypeGuildPrivateThread: - var v GuildPrivateThread + case ChannelTypeGuildNewsThread, ChannelTypeGuildPublicThread, ChannelTypeGuildPrivateThread: + var v GuildThread err = json.Unmarshal(data, &v) channel = v @@ -160,53 +147,63 @@ func (u *UnmarshalChannel) UnmarshalJSON(data []byte) error { } var ( - _ Channel = (*GuildTextChannel)(nil) - _ GuildChannel = (*GuildTextChannel)(nil) - _ MessageChannel = (*GuildTextChannel)(nil) - _ BaseGuildMessageChannel = (*GuildTextChannel)(nil) - _ GuildMessageChannel = (*GuildTextChannel)(nil) + _ Channel = (*GuildTextChannel)(nil) + _ GuildChannel = (*GuildTextChannel)(nil) + _ MessageChannel = (*GuildTextChannel)(nil) + _ GuildMessageChannel = (*GuildTextChannel)(nil) ) type GuildTextChannel struct { - ChannelID snowflake.Snowflake `json:"id"` - ChannelGuildID snowflake.Snowflake `json:"guild_id,omitempty"` - Position int `json:"position,omitempty"` - ChannelPermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` - ChannelName string `json:"name,omitempty"` - Topic *string `json:"topic,omitempty"` - NSFW bool `json:"nsfw,omitempty"` - LastMessageID *snowflake.Snowflake `json:"last_message_id,omitempty"` - RateLimitPerUser int `json:"rate_limit_per_user,omitempty"` - ParentID *snowflake.Snowflake `json:"parent_id,omitempty"` - LastPinTimestamp *Time `json:"last_pin_timestamp,omitempty"` - DefaultAutoArchiveDuration AutoArchiveDuration `json:"default_auto_archive_duration"` - InteractionPermissions Permissions `json:"permissions,omitempty"` + id snowflake.Snowflake + guildID snowflake.Snowflake + position int + permissionOverwrites []PermissionOverwrite + name string + topic *string + nsfw bool + lastMessageID *snowflake.Snowflake + rateLimitPerUser int + parentID *snowflake.Snowflake + lastPinTimestamp *Time + defaultAutoArchiveDuration AutoArchiveDuration } func (c *GuildTextChannel) UnmarshalJSON(data []byte) error { - type guildTextChannel GuildTextChannel - var v struct { - ChannelPermissionOverwrites []UnmarshalPermissionOverwrite `json:"permission_overwrites"` - guildTextChannel - } - + var v guildTextChannel if err := json.Unmarshal(data, &v); err != nil { return err } - *c = GuildTextChannel(v.guildTextChannel) - c.ChannelPermissionOverwrites = parsePermissionOverwrites(v.ChannelPermissionOverwrites) + c.id = v.ID + c.guildID = v.GuildID + c.position = v.Position + c.permissionOverwrites = v.PermissionOverwrites + c.name = v.Name + c.topic = v.Topic + c.nsfw = v.NSFW + c.lastMessageID = v.LastMessageID + c.rateLimitPerUser = v.RateLimitPerUser + c.parentID = v.ParentID + c.lastPinTimestamp = v.LastPinTimestamp + c.defaultAutoArchiveDuration = v.DefaultAutoArchiveDuration return nil } func (c GuildTextChannel) MarshalJSON() ([]byte, error) { - type guildTextChannel GuildTextChannel - return json.Marshal(struct { - Type ChannelType `json:"type"` - guildTextChannel - }{ - Type: c.Type(), - guildTextChannel: guildTextChannel(c), + return json.Marshal(guildTextChannel{ + ID: c.id, + Type: c.Type(), + GuildID: c.guildID, + Position: c.position, + PermissionOverwrites: c.permissionOverwrites, + Name: c.name, + Topic: c.topic, + NSFW: c.nsfw, + LastMessageID: c.lastMessageID, + RateLimitPerUser: c.rateLimitPerUser, + ParentID: c.parentID, + LastPinTimestamp: c.lastPinTimestamp, + DefaultAutoArchiveDuration: c.defaultAutoArchiveDuration, }) } @@ -215,7 +212,11 @@ func (c GuildTextChannel) String() string { } func (c GuildTextChannel) Mention() string { - return channelMention(c.ID()) + return ChannelMention(c.ID()) +} + +func (c GuildTextChannel) ID() snowflake.Snowflake { + return c.id } func (GuildTextChannel) Type() ChannelType { @@ -223,22 +224,49 @@ func (GuildTextChannel) Type() ChannelType { } func (c GuildTextChannel) Name() string { - return c.ChannelName + return c.name } -func (c GuildTextChannel) ID() snowflake.Snowflake { - return c.ChannelID +func (c GuildTextChannel) GuildID() snowflake.Snowflake { + return c.guildID } -func (c GuildTextChannel) GuildID() snowflake.Snowflake { - return c.ChannelGuildID +func (c GuildTextChannel) PermissionOverwrites() []PermissionOverwrite { + return c.permissionOverwrites +} + +func (c GuildTextChannel) Position() int { + return c.position +} + +func (c GuildTextChannel) ParentID() *snowflake.Snowflake { + return c.parentID +} + +func (c GuildTextChannel) LastMessageID() *snowflake.Snowflake { + return c.lastMessageID +} + +func (c GuildTextChannel) LastPinTimestamp() *Time { + return c.lastPinTimestamp +} + +func (c GuildTextChannel) Topic() *string { + return c.topic +} + +func (c GuildTextChannel) NSFW() bool { + return c.nsfw +} + +func (c GuildTextChannel) DefaultAutoArchiveDuration() AutoArchiveDuration { + return c.defaultAutoArchiveDuration } -func (GuildTextChannel) channel() {} -func (GuildTextChannel) guildChannel() {} -func (GuildTextChannel) messageChannel() {} -func (GuildTextChannel) baseGuildMessageChannel() {} -func (GuildTextChannel) guildMessageChannel() {} +func (GuildTextChannel) channel() {} +func (GuildTextChannel) guildChannel() {} +func (GuildTextChannel) messageChannel() {} +func (GuildTextChannel) guildMessageChannel() {} var ( _ Channel = (*DMChannel)(nil) @@ -246,20 +274,32 @@ var ( ) type DMChannel struct { - ChannelID snowflake.Snowflake `json:"id"` - LastMessageID *snowflake.Snowflake `json:"last_message_id,omitempty"` - Recipients []User `json:"recipients,omitempty"` - LastPinTimestamp *Time `json:"last_pin_timestamp,omitempty"` + id snowflake.Snowflake + lastMessageID *snowflake.Snowflake + recipients []User + lastPinTimestamp *Time +} + +func (c *DMChannel) UnmarshalJSON(data []byte) error { + var v dmChannel + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + c.id = v.ID + c.lastMessageID = v.LastMessageID + c.recipients = v.Recipients + c.lastPinTimestamp = v.LastPinTimestamp + return nil } func (c DMChannel) MarshalJSON() ([]byte, error) { - type dmChannel DMChannel - return json.Marshal(struct { - Type ChannelType `json:"type"` - dmChannel - }{ - Type: c.Type(), - dmChannel: dmChannel(c), + return json.Marshal(dmChannel{ + ID: c.id, + Type: c.Type(), + LastMessageID: c.lastMessageID, + Recipients: c.recipients, + LastPinTimestamp: c.lastPinTimestamp, }) } @@ -267,16 +307,24 @@ func (c DMChannel) String() string { return channelString(c) } -func (DMChannel) Type() ChannelType { - return ChannelTypeGuildText +func (c DMChannel) ID() snowflake.Snowflake { + return c.id } -func (c DMChannel) ID() snowflake.Snowflake { - return c.ChannelID +func (DMChannel) Type() ChannelType { + return ChannelTypeDM } func (c DMChannel) Name() string { - return "" + return c.recipients[0].Username +} + +func (c DMChannel) LastMessageID() *snowflake.Snowflake { + return c.lastMessageID +} + +func (c DMChannel) LastPinTimestamp() *Time { + return c.lastPinTimestamp } func (DMChannel) channel() {} @@ -289,45 +337,50 @@ var ( ) type GuildVoiceChannel struct { - ChannelID snowflake.Snowflake `json:"id"` - ChannelGuildID snowflake.Snowflake `json:"guild_id,omitempty"` - Position int `json:"position,omitempty"` - ChannelPermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` - ChannelName string `json:"name,omitempty"` - NSFW bool `json:"nsfw,omitempty"` - Topic *string `json:"topic,omitempty"` - Bitrate int `json:"bitrate,omitempty"` - UserLimit int `json:"user_limit,omitempty"` - ParentID *snowflake.Snowflake `json:"parent_id,omitempty"` - RTCRegion string `json:"rtc_region"` - VideoQualityMode VideoQualityMode `json:"video_quality_mode"` - InteractionPermissions Permissions `json:"permissions,omitempty"` + id snowflake.Snowflake + guildID snowflake.Snowflake + position int + permissionOverwrites []PermissionOverwrite + name string + bitrate int + UserLimit int + parentID *snowflake.Snowflake + rtcRegion string + VideoQualityMode VideoQualityMode } func (c *GuildVoiceChannel) UnmarshalJSON(data []byte) error { - type guildVoiceChannel GuildVoiceChannel - var v struct { - ChannelPermissionOverwrites []UnmarshalPermissionOverwrite `json:"permission_overwrites"` - guildVoiceChannel - } - + var v guildVoiceChannel if err := json.Unmarshal(data, &v); err != nil { return err } - *c = GuildVoiceChannel(v.guildVoiceChannel) - c.ChannelPermissionOverwrites = parsePermissionOverwrites(v.ChannelPermissionOverwrites) + c.id = v.ID + c.guildID = v.GuildID + c.position = v.Position + c.permissionOverwrites = v.PermissionOverwrites + c.name = v.Name + c.bitrate = v.Bitrate + c.UserLimit = v.UserLimit + c.parentID = v.ParentID + c.rtcRegion = v.RTCRegion + c.VideoQualityMode = v.VideoQualityMode return nil } func (c GuildVoiceChannel) MarshalJSON() ([]byte, error) { - type guildVoiceChannel GuildVoiceChannel - return json.Marshal(struct { - Type ChannelType `json:"type"` - guildVoiceChannel - }{ - Type: c.Type(), - guildVoiceChannel: guildVoiceChannel(c), + return json.Marshal(guildVoiceChannel{ + ID: c.id, + Type: c.Type(), + GuildID: c.guildID, + Position: c.position, + PermissionOverwrites: c.permissionOverwrites, + Name: c.name, + Bitrate: c.bitrate, + UserLimit: c.UserLimit, + ParentID: c.parentID, + RTCRegion: c.rtcRegion, + VideoQualityMode: c.VideoQualityMode, }) } @@ -336,7 +389,7 @@ func (c GuildVoiceChannel) String() string { } func (c GuildVoiceChannel) Mention() string { - return channelMention(c.ID()) + return ChannelMention(c.ID()) } func (GuildVoiceChannel) Type() ChannelType { @@ -344,65 +397,40 @@ func (GuildVoiceChannel) Type() ChannelType { } func (c GuildVoiceChannel) ID() snowflake.Snowflake { - return c.ChannelID + return c.id } func (c GuildVoiceChannel) Name() string { - return c.ChannelName + return c.name } func (c GuildVoiceChannel) GuildID() snowflake.Snowflake { - return c.ChannelGuildID + return c.guildID } -func (GuildVoiceChannel) channel() {} -func (GuildVoiceChannel) guildChannel() {} -func (GuildVoiceChannel) guildAudioChannel() {} - -var ( - _ Channel = (*GroupDMChannel)(nil) - _ MessageChannel = (*GroupDMChannel)(nil) -) - -type GroupDMChannel struct { - ChannelID snowflake.Snowflake `json:"id"` - ChannelName string `json:"name,omitempty"` - LastMessageID *snowflake.Snowflake `json:"last_message_id,omitempty"` - Recipients []User `json:"recipients,omitempty"` - Icon *string `json:"icon,omitempty"` - OwnerID snowflake.Snowflake `json:"owner_id,omitempty"` - ApplicationID snowflake.Snowflake `json:"application_id,omitempty"` - LastPinTimestamp *Time `json:"last_pin_timestamp,omitempty"` +func (c GuildVoiceChannel) PermissionOverwrites() []PermissionOverwrite { + return c.permissionOverwrites } -func (c GroupDMChannel) MarshalJSON() ([]byte, error) { - type groupDMChannel GroupDMChannel - return json.Marshal(struct { - Type ChannelType `json:"type"` - groupDMChannel - }{ - Type: c.Type(), - groupDMChannel: groupDMChannel(c), - }) +func (c GuildVoiceChannel) Bitrate() int { + return c.bitrate } -func (c GroupDMChannel) String() string { - return channelString(c) +func (c GuildVoiceChannel) RTCRegion() string { + return c.rtcRegion } -func (GroupDMChannel) Type() ChannelType { - return ChannelTypeGuildText -} -func (c GroupDMChannel) ID() snowflake.Snowflake { - return c.ChannelID +func (c GuildVoiceChannel) Position() int { + return c.position } -func (c GroupDMChannel) Name() string { - return c.ChannelName +func (c GuildVoiceChannel) ParentID() *snowflake.Snowflake { + return c.parentID } -func (GroupDMChannel) channel() {} -func (GroupDMChannel) messageChannel() {} +func (GuildVoiceChannel) channel() {} +func (GuildVoiceChannel) guildChannel() {} +func (GuildVoiceChannel) guildAudioChannel() {} var ( _ Channel = (*GuildCategoryChannel)(nil) @@ -410,39 +438,35 @@ var ( ) type GuildCategoryChannel struct { - ChannelID snowflake.Snowflake `json:"id"` - ChannelGuildID snowflake.Snowflake `json:"guild_id"` - Position int `json:"position"` - ChannelPermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` - ChannelName string `json:"name"` - NSFW bool `json:"nsfw"` - InteractionPermissions Permissions `json:"permissions,omitempty"` + id snowflake.Snowflake + guildID snowflake.Snowflake + position int + permissionOverwrites []PermissionOverwrite + name string } func (c *GuildCategoryChannel) UnmarshalJSON(data []byte) error { - type guildCategoryChannel GuildCategoryChannel - var v struct { - ChannelPermissionOverwrites []UnmarshalPermissionOverwrite `json:"permission_overwrites"` - guildCategoryChannel - } - + var v guildCategoryChannel if err := json.Unmarshal(data, &v); err != nil { return err } - *c = GuildCategoryChannel(v.guildCategoryChannel) - c.ChannelPermissionOverwrites = parsePermissionOverwrites(v.ChannelPermissionOverwrites) + c.id = v.ID + c.guildID = v.GuildID + c.position = v.Position + c.permissionOverwrites = v.PermissionOverwrites + c.name = v.Name return nil } func (c GuildCategoryChannel) MarshalJSON() ([]byte, error) { - type guildCategoryChannel GuildCategoryChannel - return json.Marshal(struct { - Type ChannelType `json:"type"` - guildCategoryChannel - }{ + return json.Marshal(guildCategoryChannel{ + ID: c.id, Type: c.Type(), - guildCategoryChannel: guildCategoryChannel(c), + GuildID: c.guildID, + Position: c.position, + PermissionOverwrites: c.permissionOverwrites, + Name: c.name, }) } @@ -451,7 +475,7 @@ func (c GuildCategoryChannel) String() string { } func (c GuildCategoryChannel) Mention() string { - return channelMention(c.ID()) + return ChannelMention(c.ID()) } func (GuildCategoryChannel) Type() ChannelType { @@ -459,68 +483,90 @@ func (GuildCategoryChannel) Type() ChannelType { } func (c GuildCategoryChannel) ID() snowflake.Snowflake { - return c.ChannelID + return c.id } func (c GuildCategoryChannel) Name() string { - return c.ChannelName + return c.name } func (c GuildCategoryChannel) GuildID() snowflake.Snowflake { - return c.ChannelGuildID + return c.guildID +} + +func (c GuildCategoryChannel) PermissionOverwrites() []PermissionOverwrite { + return c.permissionOverwrites +} + +func (c GuildCategoryChannel) Position() int { + return c.position +} + +func (c GuildCategoryChannel) ParentID() *snowflake.Snowflake { + return nil } func (GuildCategoryChannel) channel() {} func (GuildCategoryChannel) guildChannel() {} var ( - _ Channel = (*GuildNewsChannel)(nil) - _ GuildChannel = (*GuildNewsChannel)(nil) - _ MessageChannel = (*GuildNewsChannel)(nil) - _ BaseGuildMessageChannel = (*GuildNewsChannel)(nil) - _ GuildMessageChannel = (*GuildNewsChannel)(nil) + _ Channel = (*GuildNewsChannel)(nil) + _ GuildChannel = (*GuildNewsChannel)(nil) + _ MessageChannel = (*GuildNewsChannel)(nil) + _ GuildMessageChannel = (*GuildNewsChannel)(nil) ) type GuildNewsChannel struct { - ChannelID snowflake.Snowflake `json:"id"` - ChannelGuildID snowflake.Snowflake `json:"guild_id,omitempty"` - Position int `json:"position,omitempty"` - ChannelPermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` - ChannelName string `json:"name,omitempty"` - Topic *string `json:"topic,omitempty"` - NSFW bool `json:"nsfw,omitempty"` - LastMessageID *snowflake.Snowflake `json:"last_message_id,omitempty"` - RateLimitPerUser int `json:"rate_limit_per_user,omitempty"` - ParentID *snowflake.Snowflake `json:"parent_id,omitempty"` - LastPinTimestamp *Time `json:"last_pin_timestamp,omitempty"` - DefaultAutoArchiveDuration AutoArchiveDuration `json:"default_auto_archive_duration"` - InteractionPermissions Permissions `json:"permissions,omitempty"` + id snowflake.Snowflake + guildID snowflake.Snowflake + position int + permissionOverwrites []PermissionOverwrite + name string + topic *string + nsfw bool + lastMessageID *snowflake.Snowflake + rateLimitPerUser int + parentID *snowflake.Snowflake + lastPinTimestamp *Time + defaultAutoArchiveDuration AutoArchiveDuration } func (c *GuildNewsChannel) UnmarshalJSON(data []byte) error { - type guildNewsChannel GuildNewsChannel - var v struct { - ChannelPermissionOverwrites []UnmarshalPermissionOverwrite `json:"permission_overwrites"` - guildNewsChannel - } - + var v guildNewsChannel if err := json.Unmarshal(data, &v); err != nil { return err } - *c = GuildNewsChannel(v.guildNewsChannel) - c.ChannelPermissionOverwrites = parsePermissionOverwrites(v.ChannelPermissionOverwrites) + c.id = v.ID + c.guildID = v.GuildID + c.position = v.Position + c.permissionOverwrites = v.PermissionOverwrites + c.name = v.Name + c.topic = v.Topic + c.nsfw = v.NSFW + c.lastMessageID = v.LastMessageID + c.rateLimitPerUser = v.RateLimitPerUser + c.parentID = v.ParentID + c.lastPinTimestamp = v.LastPinTimestamp + c.defaultAutoArchiveDuration = v.DefaultAutoArchiveDuration return nil } func (c GuildNewsChannel) MarshalJSON() ([]byte, error) { - type guildNewsChannel GuildNewsChannel - return json.Marshal(struct { - Type ChannelType `json:"type"` - guildNewsChannel - }{ - Type: c.Type(), - guildNewsChannel: guildNewsChannel(c), + return json.Marshal(guildNewsChannel{ + ID: c.id, + Type: c.Type(), + GuildID: c.guildID, + Position: c.position, + PermissionOverwrites: c.permissionOverwrites, + Name: c.name, + Topic: c.topic, + NSFW: c.nsfw, + LastMessageID: c.lastMessageID, + RateLimitPerUser: c.rateLimitPerUser, + ParentID: c.parentID, + LastPinTimestamp: c.lastPinTimestamp, + DefaultAutoArchiveDuration: c.defaultAutoArchiveDuration, }) } @@ -529,7 +575,7 @@ func (c GuildNewsChannel) String() string { } func (c GuildNewsChannel) Mention() string { - return channelMention(c.ID()) + return ChannelMention(c.ID()) } func (GuildNewsChannel) Type() ChannelType { @@ -537,296 +583,162 @@ func (GuildNewsChannel) Type() ChannelType { } func (c GuildNewsChannel) ID() snowflake.Snowflake { - return c.ChannelID + return c.id } func (c GuildNewsChannel) Name() string { - return c.ChannelName + return c.name } func (c GuildNewsChannel) GuildID() snowflake.Snowflake { - return c.ChannelGuildID + return c.guildID } -func (GuildNewsChannel) channel() {} -func (GuildNewsChannel) guildChannel() {} -func (GuildNewsChannel) messageChannel() {} -func (GuildNewsChannel) baseGuildMessageChannel() {} -func (GuildNewsChannel) guildMessageChannel() {} - -var ( - _ Channel = (*GuildStoreChannel)(nil) - _ GuildChannel = (*GuildStoreChannel)(nil) -) - -type GuildStoreChannel struct { - ChannelID snowflake.Snowflake `json:"id"` - ChannelGuildID snowflake.Snowflake `json:"guild_id"` - Position int `json:"position"` - ChannelPermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` - ChannelName string `json:"name"` - NSFW bool `json:"nsfw,omitempty"` - ParentID *snowflake.Snowflake `json:"parent_id"` - InteractionPermissions Permissions `json:"permissions,omitempty"` -} - -func (c *GuildStoreChannel) UnmarshalJSON(data []byte) error { - type guildStoreChannel GuildStoreChannel - var v struct { - ChannelPermissionOverwrites []UnmarshalPermissionOverwrite `json:"permission_overwrites"` - guildStoreChannel - } - - if err := json.Unmarshal(data, &v); err != nil { - return err - } - - *c = GuildStoreChannel(v.guildStoreChannel) - c.ChannelPermissionOverwrites = parsePermissionOverwrites(v.ChannelPermissionOverwrites) - return nil +func (c GuildNewsChannel) PermissionOverwrites() []PermissionOverwrite { + return c.permissionOverwrites } -func (c GuildStoreChannel) MarshalJSON() ([]byte, error) { - type guildStoreChannel GuildStoreChannel - return json.Marshal(struct { - Type ChannelType `json:"type"` - guildStoreChannel - }{ - Type: c.Type(), - guildStoreChannel: guildStoreChannel(c), - }) +func (c GuildNewsChannel) Topic() *string { + return c.topic } -func (c GuildStoreChannel) String() string { - return channelString(c) +func (c GuildNewsChannel) NSFW() bool { + return c.nsfw } -func (c GuildStoreChannel) Mention() string { - return channelMention(c.ID()) +func (c GuildNewsChannel) DefaultAutoArchiveDuration() AutoArchiveDuration { + return c.defaultAutoArchiveDuration } -func (GuildStoreChannel) Type() ChannelType { - return ChannelTypeGuildStore +func (c GuildNewsChannel) LastMessageID() *snowflake.Snowflake { + return c.lastMessageID } -func (c GuildStoreChannel) ID() snowflake.Snowflake { - return c.ChannelID +func (c GuildNewsChannel) LastPinTimestamp() *Time { + return c.lastPinTimestamp } -func (c GuildStoreChannel) Name() string { - return c.ChannelName +func (c GuildNewsChannel) Position() int { + return c.position } -func (c GuildStoreChannel) GuildID() snowflake.Snowflake { - return c.ChannelGuildID +func (c GuildNewsChannel) ParentID() *snowflake.Snowflake { + return c.parentID } -func (GuildStoreChannel) channel() {} -func (GuildStoreChannel) guildChannel() {} +func (GuildNewsChannel) channel() {} +func (GuildNewsChannel) guildChannel() {} +func (GuildNewsChannel) messageChannel() {} +func (GuildNewsChannel) guildMessageChannel() {} var ( - _ Channel = (*GuildNewsThread)(nil) - _ GuildChannel = (*GuildNewsThread)(nil) - _ MessageChannel = (*GuildNewsThread)(nil) - _ BaseGuildMessageChannel = (*GuildNewsThread)(nil) - _ GuildThread = (*GuildNewsThread)(nil) + _ Channel = (*GuildThread)(nil) + _ GuildChannel = (*GuildThread)(nil) + _ MessageChannel = (*GuildThread)(nil) ) -type GuildNewsThread struct { - ChannelID snowflake.Snowflake `json:"id"` - ChannelGuildID snowflake.Snowflake `json:"guild_id"` - ChannelName string `json:"name"` - NSFW bool `json:"nsfw"` - LastMessageID snowflake.Snowflake `json:"last_message_id"` - LastPinTimestamp *Time `json:"last_pin_timestamp"` - RateLimitPerUser int `json:"rate_limit_per_user"` - OwnerID snowflake.Snowflake `json:"owner_id"` - ParentChannelID snowflake.Snowflake `json:"parent_id"` - MessageCount int `json:"message_count"` - MemberCount int `json:"member_count"` - ThreadMetadata ThreadMetadata `json:"thread_metadata"` -} - -func (c GuildNewsThread) MarshalJSON() ([]byte, error) { - type guildNewsThread GuildNewsThread - return json.Marshal(struct { - Type ChannelType `json:"type"` - guildNewsThread - }{ - Type: c.Type(), - guildNewsThread: guildNewsThread(c), - }) -} - -func (c GuildNewsThread) String() string { - return channelString(c) -} - -func (c GuildNewsThread) Mention() string { - return channelMention(c.ID()) -} - -func (GuildNewsThread) Type() ChannelType { - return ChannelTypeGuildNewsThread -} - -func (c GuildNewsThread) ID() snowflake.Snowflake { - return c.ChannelID -} - -func (c GuildNewsThread) ParentID() snowflake.Snowflake { - return c.ParentChannelID -} - -func (c GuildNewsThread) Name() string { - return c.ChannelName -} +type GuildThread struct { + id snowflake.Snowflake + guildID snowflake.Snowflake + name string + NSFW bool + lastMessageID *snowflake.Snowflake + lastPinTimestamp *Time + RateLimitPerUser int + OwnerID snowflake.Snowflake + parentID snowflake.Snowflake + MessageCount int + MemberCount int + ThreadMetadata ThreadMetadata +} + +func (c *GuildThread) UnmarshalJSON(data []byte) error { + var v guildThread + if err := json.Unmarshal(data, &v); err != nil { + return err + } -func (c GuildNewsThread) GuildID() snowflake.Snowflake { - return c.ChannelGuildID + c.id = v.ID + c.guildID = v.GuildID + c.name = v.Name + c.NSFW = v.NSFW + c.lastMessageID = v.LastMessageID + c.lastPinTimestamp = v.LastPinTimestamp + c.RateLimitPerUser = v.RateLimitPerUser + c.OwnerID = v.OwnerID + c.parentID = v.ParentID + c.MessageCount = v.MessageCount + c.MemberCount = v.MemberCount + c.ThreadMetadata = v.ThreadMetadata + return nil } -func (GuildNewsThread) channel() {} -func (GuildNewsThread) guildChannel() {} -func (GuildNewsThread) messageChannel() {} -func (GuildNewsThread) baseGuildMessageChannel() {} -func (GuildNewsThread) guildThread() {} - -var ( - _ Channel = (*GuildPublicThread)(nil) - _ GuildChannel = (*GuildPublicThread)(nil) - _ MessageChannel = (*GuildPublicThread)(nil) - _ BaseGuildMessageChannel = (*GuildPublicThread)(nil) - _ GuildThread = (*GuildPublicThread)(nil) -) - -type GuildPublicThread struct { - ChannelID snowflake.Snowflake `json:"id"` - ChannelGuildID snowflake.Snowflake `json:"guild_id"` - ChannelName string `json:"name"` - NSFW bool `json:"nsfw"` - LastMessageID snowflake.Snowflake `json:"last_message_id"` - LastPinTimestamp *Time `json:"last_pin_timestamp"` - RateLimitPerUser int `json:"rate_limit_per_user"` - OwnerID snowflake.Snowflake `json:"owner_id"` - ParentChannelID snowflake.Snowflake `json:"parent_id"` - MessageCount int `json:"message_count"` - MemberCount int `json:"member_count"` - ThreadMetadata ThreadMetadata `json:"thread_metadata"` -} - -func (c GuildPublicThread) MarshalJSON() ([]byte, error) { - type guildTextChannel GuildPublicThread - return json.Marshal(struct { - Type ChannelType `json:"type"` - guildTextChannel - }{ +func (c GuildThread) MarshalJSON() ([]byte, error) { + return json.Marshal(guildThread{ + ID: c.id, Type: c.Type(), - guildTextChannel: guildTextChannel(c), + GuildID: c.guildID, + Name: c.name, + NSFW: c.NSFW, + LastMessageID: c.lastMessageID, + LastPinTimestamp: c.lastPinTimestamp, + RateLimitPerUser: c.RateLimitPerUser, + OwnerID: c.OwnerID, + ParentID: c.parentID, + MessageCount: c.MessageCount, + MemberCount: c.MemberCount, + ThreadMetadata: c.ThreadMetadata, }) } -func (c GuildPublicThread) String() string { +func (c GuildThread) String() string { return channelString(c) } -func (c GuildPublicThread) Mention() string { - return channelMention(c.ID()) -} - -func (GuildPublicThread) Type() ChannelType { - return ChannelTypeGuildPublicThread -} - -func (c GuildPublicThread) ID() snowflake.Snowflake { - return c.ChannelID +func (c GuildThread) Mention() string { + return ChannelMention(c.ID()) } -func (c GuildPublicThread) ParentID() snowflake.Snowflake { - return c.ParentChannelID -} - -func (c GuildPublicThread) Name() string { - return c.ChannelName -} - -func (c GuildPublicThread) GuildID() snowflake.Snowflake { - return c.ChannelGuildID +func (GuildThread) Type() ChannelType { + return ChannelTypeGuildNewsThread } -func (GuildPublicThread) channel() {} -func (GuildPublicThread) guildChannel() {} -func (GuildPublicThread) messageChannel() {} -func (GuildPublicThread) baseGuildMessageChannel() {} -func (GuildPublicThread) guildThread() {} - -var ( - _ Channel = (*GuildPrivateThread)(nil) - _ GuildChannel = (*GuildPrivateThread)(nil) - _ MessageChannel = (*GuildPrivateThread)(nil) - _ BaseGuildMessageChannel = (*GuildPrivateThread)(nil) - _ GuildThread = (*GuildPrivateThread)(nil) -) - -type GuildPrivateThread struct { - ChannelID snowflake.Snowflake `json:"id"` - ChannelGuildID snowflake.Snowflake `json:"guild_id"` - ChannelName string `json:"name"` - NSFW bool `json:"nsfw"` - LastMessageID snowflake.Snowflake `json:"last_message_id"` - LastPinTimestamp *Time `json:"last_pin_timestamp"` - RateLimitPerUser int `json:"rate_limit_per_user"` - OwnerID snowflake.Snowflake `json:"owner_id"` - ParentChannelID snowflake.Snowflake `json:"parent_id"` - MessageCount int `json:"message_count"` - MemberCount int `json:"member_count"` - ThreadMetadata ThreadMetadata `json:"thread_metadata"` -} - -func (c GuildPrivateThread) MarshalJSON() ([]byte, error) { - type guildPrivateThread GuildPrivateThread - return json.Marshal(struct { - Type ChannelType `json:"type"` - guildPrivateThread - }{ - Type: c.Type(), - guildPrivateThread: guildPrivateThread(c), - }) +func (c GuildThread) ID() snowflake.Snowflake { + return c.id } -func (c GuildPrivateThread) String() string { - return channelString(c) +func (c GuildThread) Name() string { + return c.name } -func (c GuildPrivateThread) Mention() string { - return channelMention(c.ID()) +func (c GuildThread) GuildID() snowflake.Snowflake { + return c.guildID } -func (GuildPrivateThread) Type() ChannelType { - return ChannelTypeGuildPrivateThread +func (c GuildThread) LastMessageID() *snowflake.Snowflake { + return c.lastMessageID } -func (c GuildPrivateThread) ID() snowflake.Snowflake { - return c.ChannelID +func (c GuildThread) LastPinTimestamp() *Time { + return c.lastPinTimestamp } -func (c GuildPrivateThread) ParentID() snowflake.Snowflake { - return c.ParentChannelID +func (c GuildThread) Position() int { + return 0 } -func (c GuildPrivateThread) Name() string { - return c.ChannelName +func (c GuildThread) ParentID() *snowflake.Snowflake { + return &c.parentID } -func (c GuildPrivateThread) GuildID() snowflake.Snowflake { - return c.ChannelGuildID +func (c *GuildThread) PermissionOverwrites() []PermissionOverwrite { + return nil } -func (GuildPrivateThread) channel() {} -func (GuildPrivateThread) guildChannel() {} -func (GuildPrivateThread) messageChannel() {} -func (GuildPrivateThread) baseGuildMessageChannel() {} -func (GuildPrivateThread) guildThread() {} +func (GuildThread) channel() {} +func (GuildThread) guildChannel() {} +func (GuildThread) messageChannel() {} +func (GuildThread) guildThread() {} var ( _ Channel = (*GuildStageVoiceChannel)(nil) @@ -835,44 +747,44 @@ var ( ) type GuildStageVoiceChannel struct { - ChannelID snowflake.Snowflake `json:"id"` - ChannelGuildID snowflake.Snowflake `json:"guild_id,omitempty"` - Position int `json:"position,omitempty"` - ChannelPermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` - ChannelName string `json:"name,omitempty"` - Topic *string `json:"topic,omitempty"` - Bitrate int `json:"bitrate,omitempty"` - UserLimit int `json:"user_limit,omitempty"` - ParentID *snowflake.Snowflake `json:"parent_id,omitempty"` - RTCRegion string `json:"rtc_region"` - VideoQualityMode VideoQualityMode `json:"video_quality_mode"` - InteractionPermissions Permissions `json:"permissions,omitempty"` + id snowflake.Snowflake + guildID snowflake.Snowflake + position int + permissionOverwrites []PermissionOverwrite + name string + bitrate int + parentID *snowflake.Snowflake + rtcRegion string } func (c *GuildStageVoiceChannel) UnmarshalJSON(data []byte) error { - type guildStageVoiceChannel GuildStageVoiceChannel - var v struct { - ChannelPermissionOverwrites []UnmarshalPermissionOverwrite `json:"permission_overwrites"` - guildStageVoiceChannel - } - + var v guildStageVoiceChannel if err := json.Unmarshal(data, &v); err != nil { return err } - *c = GuildStageVoiceChannel(v.guildStageVoiceChannel) - c.ChannelPermissionOverwrites = parsePermissionOverwrites(v.ChannelPermissionOverwrites) + c.id = v.ID + c.guildID = v.GuildID + c.position = v.Position + c.permissionOverwrites = v.PermissionOverwrites + c.name = v.Name + c.bitrate = v.Bitrate + c.parentID = v.ParentID + c.rtcRegion = v.RTCRegion return nil } func (c GuildStageVoiceChannel) MarshalJSON() ([]byte, error) { - type guildStageVoiceChannel GuildStageVoiceChannel - return json.Marshal(struct { - Type ChannelType `json:"type"` - guildStageVoiceChannel - }{ - Type: c.Type(), - guildStageVoiceChannel: guildStageVoiceChannel(c), + return json.Marshal(guildStageVoiceChannel{ + ID: c.id, + Type: c.Type(), + GuildID: c.guildID, + Position: c.position, + PermissionOverwrites: c.permissionOverwrites, + Name: c.name, + Bitrate: c.bitrate, + ParentID: c.parentID, + RTCRegion: c.rtcRegion, }) } @@ -881,23 +793,43 @@ func (c GuildStageVoiceChannel) String() string { } func (c GuildStageVoiceChannel) Mention() string { - return channelMention(c.ID()) + return ChannelMention(c.ID()) } func (GuildStageVoiceChannel) Type() ChannelType { - return ChannelTypeGuildStageVoice + return ChannelTypeGuildText } func (c GuildStageVoiceChannel) ID() snowflake.Snowflake { - return c.ChannelID + return c.id } func (c GuildStageVoiceChannel) Name() string { - return c.ChannelName + return c.name } func (c GuildStageVoiceChannel) GuildID() snowflake.Snowflake { - return c.ChannelGuildID + return c.guildID +} + +func (c GuildStageVoiceChannel) PermissionOverwrites() []PermissionOverwrite { + return c.permissionOverwrites +} + +func (c GuildStageVoiceChannel) Bitrate() int { + return c.bitrate +} + +func (c GuildStageVoiceChannel) RTCRegion() string { + return c.rtcRegion +} + +func (c GuildStageVoiceChannel) Position() int { + return c.position +} + +func (c GuildStageVoiceChannel) ParentID() *snowflake.Snowflake { + return c.parentID } func (GuildStageVoiceChannel) channel() {} @@ -907,7 +839,6 @@ func (GuildStageVoiceChannel) guildAudioChannel() {} // VideoQualityMode https://com/developers/docs/resources/channel#channel-object-video-quality-modes type VideoQualityMode int -//goland:noinspection GoUnusedConst const ( VideoQualityModeAuto = iota + 1 VideoQualityModeFull @@ -924,7 +855,6 @@ type ThreadMetadata struct { type AutoArchiveDuration int -//goland:noinspection GoUnusedConst const ( AutoArchiveDuration1h AutoArchiveDuration = 60 AutoArchiveDuration24h AutoArchiveDuration = 1440 @@ -932,28 +862,6 @@ const ( AutoArchiveDuration1w AutoArchiveDuration = 10080 ) -// PartialChannel contains basic info about a Channel -type PartialChannel struct { - ID snowflake.Snowflake `json:"id"` - Type ChannelType `json:"type"` - Name string `json:"name"` - Icon *string `json:"icon,omitempty"` -} - -// GetIconURL returns the Icon URL of this channel. -// This will be nil for every ChannelType except ChannelTypeGroupDM -func (c *PartialChannel) GetIconURL(size int) *string { - return FormatAssetURL(route.ChannelIcon, c.ID, c.Icon, size) -} - -func parsePermissionOverwrites(unmarshalOverwrites []UnmarshalPermissionOverwrite) []PermissionOverwrite { - overwrites := make([]PermissionOverwrite, len(unmarshalOverwrites)) - for i := range unmarshalOverwrites { - overwrites[i] = unmarshalOverwrites[i].PermissionOverwrite - } - return overwrites -} - func channelString(channel Channel) string { return fmt.Sprintf("%d:%s(%s)", channel.Type(), channel.Name(), channel.ID()) } diff --git a/discord/channel_create.go b/discord/channel_create.go index c993b73b..d2a90856 100644 --- a/discord/channel_create.go +++ b/discord/channel_create.go @@ -1,8 +1,8 @@ package discord import ( - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" ) type ChannelCreate interface { diff --git a/discord/channel_update.go b/discord/channel_update.go index a3ecf8ba..13520f27 100644 --- a/discord/channel_update.go +++ b/discord/channel_update.go @@ -1,6 +1,9 @@ package discord -import "github.com/DisgoOrg/snowflake" +import ( + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" +) type ChannelUpdate interface { channelUpdate() @@ -20,36 +23,31 @@ type GuildTextChannelUpdate struct { RateLimitPerUser *int `json:"rate_limit_per_user,omitempty"` PermissionOverwrites *[]PermissionOverwrite `json:"permission_overwrites,omitempty"` ParentID *snowflake.Snowflake `json:"parent_id,omitempty"` - DefaultAutoArchiveDuration *int `json:"default_auto_archive_duration,omitempty"` + DefaultAutoArchiveDuration *AutoArchiveDuration `json:"default_auto_archive_duration,omitempty"` } func (GuildTextChannelUpdate) channelUpdate() {} func (GuildTextChannelUpdate) guildChannelUpdate() {} type GuildVoiceChannelUpdate struct { - Name *string `json:"name,omitempty"` - Position *int `json:"position,omitempty"` - RateLimitPerUser *int `json:"rate_limit_per_user,omitempty"` - Bitrate *int `json:"bitrate,omitempty"` - UserLimit *int `json:"user_limit,omitempty"` - PermissionOverwrites *[]PermissionOverwrite `json:"permission_overwrites,omitempty"` - ParentID *snowflake.Snowflake `json:"parent_id,omitempty"` - RTCRegion *string `json:"rtc_region"` - VideoQualityMode *VideoQualityMode `json:"video_quality_mode"` - DefaultAutoArchiveDuration *int `json:"default_auto_archive_duration"` + Name *string `json:"name,omitempty"` + Position *int `json:"position,omitempty"` + RateLimitPerUser *int `json:"rate_limit_per_user,omitempty"` + Bitrate *int `json:"bitrate,omitempty"` + UserLimit *int `json:"user_limit,omitempty"` + PermissionOverwrites *[]PermissionOverwrite `json:"permission_overwrites,omitempty"` + ParentID *snowflake.Snowflake `json:"parent_id,omitempty"` + RTCRegion *string `json:"rtc_region"` + VideoQualityMode *VideoQualityMode `json:"video_quality_mode"` } func (GuildVoiceChannelUpdate) channelUpdate() {} func (GuildVoiceChannelUpdate) guildChannelUpdate() {} -type GroupDMChannelUpdate struct { - Name *string `json:"name,omitempty"` - Icon *NullIcon `json:"icon,omitempty"` -} - -func (GroupDMChannelUpdate) channelUpdate() {} - type GuildCategoryChannelUpdate struct { + Name *string `json:"name,omitempty"` + Position *int `json:"position,omitempty"` + PermissionOverwrites *[]PermissionOverwrite `json:"permission_overwrites,omitempty"` } func (GuildCategoryChannelUpdate) channelUpdate() {} @@ -69,29 +67,17 @@ type GuildNewsChannelUpdate struct { func (GuildNewsChannelUpdate) channelUpdate() {} func (GuildNewsChannelUpdate) guildChannelUpdate() {} -type GuildStoreChannelUpdate struct { -} - -func (GuildStoreChannelUpdate) channelUpdate() {} -func (GuildStoreChannelUpdate) guildChannelUpdate() {} - -type GuildNewsThreadUpdate struct { -} - -func (GuildNewsThreadUpdate) channelUpdate() {} -func (GuildNewsThreadUpdate) guildChannelUpdate() {} - -type GuildPublicThreadUpdate struct { -} - -func (GuildPublicThreadUpdate) channelUpdate() {} -func (GuildPublicThreadUpdate) guildChannelUpdate() {} - -type GuildPrivateThreadUpdate struct { +type GuildThreadUpdate struct { + Name *string `json:"name,omitempty"` + Archived *bool `json:"archived,omitempty"` + AutoArchiveDuration *AutoArchiveDuration `json:"auto_archive_duration,omitempty"` + Locked *bool `json:"locked,omitempty"` + Invitable *bool `json:"invitable,omitempty"` + RateLimitPerUser *int `json:"rate_limit_per_user,omitempty"` } -func (GuildPrivateThreadUpdate) channelUpdate() {} -func (GuildPrivateThreadUpdate) guildChannelUpdate() {} +func (GuildThreadUpdate) channelUpdate() {} +func (GuildThreadUpdate) guildChannelUpdate() {} type GuildStageVoiceChannelUpdate struct { Name *string `json:"name,omitempty"` @@ -102,8 +88,14 @@ type GuildStageVoiceChannelUpdate struct { PermissionOverwrites *[]PermissionOverwrite `json:"permission_overwrites,omitempty"` ParentID *snowflake.Snowflake `json:"parent_id,omitempty"` RTCRegion *string `json:"rtc_region"` - VideoQualityMode *VideoQualityMode `json:"video_quality_mode"` } func (GuildStageVoiceChannelUpdate) channelUpdate() {} func (GuildStageVoiceChannelUpdate) guildChannelUpdate() {} + +type GuildChannelPositionUpdate struct { + ID snowflake.Snowflake `json:"id"` + Position *json.Nullable[int] `json:"position"` + LockPermissions *json.Nullable[bool] `json:"lock_permissions,omitempty"` + ParentID *json.Nullable[snowflake.Snowflake] `json:"parent_id,omitempty"` +} diff --git a/discord/channels_raw.go b/discord/channels_raw.go new file mode 100644 index 00000000..8d0dc08c --- /dev/null +++ b/discord/channels_raw.go @@ -0,0 +1,192 @@ +package discord + +import ( + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" +) + +type dmChannel struct { + ID snowflake.Snowflake `json:"id"` + Type ChannelType `json:"type"` + LastMessageID *snowflake.Snowflake `json:"last_message_id"` + Recipients []User `json:"recipients"` + LastPinTimestamp *Time `json:"last_pin_timestamp"` +} + +type guildTextChannel struct { + ID snowflake.Snowflake `json:"id"` + Type ChannelType `json:"type"` + GuildID snowflake.Snowflake `json:"guild_id"` + Position int `json:"position"` + PermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` + Name string `json:"name"` + Topic *string `json:"topic"` + NSFW bool `json:"nsfw"` + LastMessageID *snowflake.Snowflake `json:"last_message_id"` + RateLimitPerUser int `json:"rate_limit_per_user"` + ParentID *snowflake.Snowflake `json:"parent_id"` + LastPinTimestamp *Time `json:"last_pin_timestamp"` + DefaultAutoArchiveDuration AutoArchiveDuration `json:"default_auto_archive_duration"` +} + +func (t *guildTextChannel) UnmarshalJSON(data []byte) error { + type guildTextChannelAlias guildTextChannel + var v struct { + PermissionOverwrites []UnmarshalPermissionOverwrite `json:"permission_overwrites"` + guildTextChannelAlias + } + if err := json.Unmarshal(data, &v); err != nil { + return err + } + *t = guildTextChannel(v.guildTextChannelAlias) + if len(v.PermissionOverwrites) > 0 { + t.PermissionOverwrites = make([]PermissionOverwrite, len(v.PermissionOverwrites)) + for i := range v.PermissionOverwrites { + t.PermissionOverwrites[i] = v.PermissionOverwrites[i].PermissionOverwrite + } + } + return nil +} + +type guildNewsChannel struct { + ID snowflake.Snowflake `json:"id"` + Type ChannelType `json:"type"` + GuildID snowflake.Snowflake `json:"guild_id"` + Position int `json:"position"` + PermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` + Name string `json:"name"` + Topic *string `json:"topic"` + NSFW bool `json:"nsfw"` + RateLimitPerUser int `json:"rate_limit_per_user"` + ParentID *snowflake.Snowflake `json:"parent_id"` + LastMessageID *snowflake.Snowflake `json:"last_message_id"` + LastPinTimestamp *Time `json:"last_pin_timestamp"` + DefaultAutoArchiveDuration AutoArchiveDuration `json:"default_auto_archive_duration"` +} + +func (t *guildNewsChannel) UnmarshalJSON(data []byte) error { + type guildNewsChannelAlias guildNewsChannel + var v struct { + PermissionOverwrites []UnmarshalPermissionOverwrite `json:"permission_overwrites"` + guildNewsChannelAlias + } + if err := json.Unmarshal(data, &v); err != nil { + return err + } + *t = guildNewsChannel(v.guildNewsChannelAlias) + if len(v.PermissionOverwrites) > 0 { + t.PermissionOverwrites = make([]PermissionOverwrite, len(v.PermissionOverwrites)) + for i := range v.PermissionOverwrites { + t.PermissionOverwrites[i] = v.PermissionOverwrites[i].PermissionOverwrite + } + } + return nil +} + +type guildThread struct { + ID snowflake.Snowflake `json:"id"` + Type ChannelType `json:"type"` + GuildID snowflake.Snowflake `json:"guild_id"` + Name string `json:"name"` + NSFW bool `json:"nsfw"` + LastMessageID *snowflake.Snowflake `json:"last_message_id"` + RateLimitPerUser int `json:"rate_limit_per_user"` + OwnerID snowflake.Snowflake `json:"owner_id"` + ParentID snowflake.Snowflake `json:"parent_id"` + LastPinTimestamp *Time `json:"last_pin_timestamp"` + MessageCount int `json:"message_count"` + MemberCount int `json:"member_count"` + ThreadMetadata ThreadMetadata `json:"thread_metadata"` +} + +type guildCategoryChannel struct { + ID snowflake.Snowflake `json:"id"` + Type ChannelType `json:"type"` + GuildID snowflake.Snowflake `json:"guild_id"` + Position int `json:"position"` + PermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` + Name string `json:"name"` +} + +func (t *guildCategoryChannel) UnmarshalJSON(data []byte) error { + type guildCategoryChannelAlias guildCategoryChannel + var v struct { + PermissionOverwrites []UnmarshalPermissionOverwrite `json:"permission_overwrites"` + guildCategoryChannelAlias + } + if err := json.Unmarshal(data, &v); err != nil { + return err + } + *t = guildCategoryChannel(v.guildCategoryChannelAlias) + if len(v.PermissionOverwrites) > 0 { + t.PermissionOverwrites = make([]PermissionOverwrite, len(v.PermissionOverwrites)) + for i := range v.PermissionOverwrites { + t.PermissionOverwrites[i] = v.PermissionOverwrites[i].PermissionOverwrite + } + } + return nil +} + +type guildVoiceChannel struct { + ID snowflake.Snowflake `json:"id"` + Type ChannelType `json:"type"` + GuildID snowflake.Snowflake `json:"guild_id"` + Position int `json:"position"` + PermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` + Name string `json:"name"` + Bitrate int `json:"bitrate"` + UserLimit int `json:"user_limit"` + ParentID *snowflake.Snowflake `json:"parent_id"` + RTCRegion string `json:"rtc_region"` + VideoQualityMode VideoQualityMode `json:"video_quality_mode"` +} + +func (t *guildVoiceChannel) UnmarshalJSON(data []byte) error { + type guildVoiceChannelAlias guildVoiceChannel + var v struct { + PermissionOverwrites []UnmarshalPermissionOverwrite `json:"permission_overwrites"` + guildVoiceChannelAlias + } + if err := json.Unmarshal(data, &v); err != nil { + return err + } + *t = guildVoiceChannel(v.guildVoiceChannelAlias) + if len(v.PermissionOverwrites) > 0 { + t.PermissionOverwrites = make([]PermissionOverwrite, len(v.PermissionOverwrites)) + for i := range v.PermissionOverwrites { + t.PermissionOverwrites[i] = v.PermissionOverwrites[i].PermissionOverwrite + } + } + return nil +} + +type guildStageVoiceChannel struct { + ID snowflake.Snowflake `json:"id"` + Type ChannelType `json:"type"` + GuildID snowflake.Snowflake `json:"guild_id"` + Position int `json:"position"` + PermissionOverwrites []PermissionOverwrite `json:"permission_overwrites"` + Name string `json:"name"` + Bitrate int `json:"bitrate,"` + ParentID *snowflake.Snowflake `json:"parent_id"` + RTCRegion string `json:"rtc_region"` +} + +func (t *guildStageVoiceChannel) UnmarshalJSON(data []byte) error { + type guildStageVoiceChannelAlias guildStageVoiceChannel + var v struct { + PermissionOverwrites []UnmarshalPermissionOverwrite `json:"permission_overwrites"` + guildStageVoiceChannelAlias + } + if err := json.Unmarshal(data, &v); err != nil { + return err + } + *t = guildStageVoiceChannel(v.guildStageVoiceChannelAlias) + if len(v.PermissionOverwrites) > 0 { + t.PermissionOverwrites = make([]PermissionOverwrite, len(v.PermissionOverwrites)) + for i := range v.PermissionOverwrites { + t.PermissionOverwrites[i] = v.PermissionOverwrites[i].PermissionOverwrite + } + } + return nil +} diff --git a/discord/component.go b/discord/component.go index 767b3105..ce9c8a89 100644 --- a/discord/component.go +++ b/discord/component.go @@ -3,15 +3,14 @@ package discord import ( "fmt" - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" ) // ComponentType defines different Component(s) type ComponentType int // Supported ComponentType(s) -//goland:noinspection GoUnusedConst const ( ComponentTypeActionRow = iota + 1 ComponentTypeButton @@ -110,7 +109,6 @@ var ( _ ContainerComponent = (*ActionRowComponent)(nil) ) -//goland:noinspection GoUnusedExportedFunction func NewActionRow(components ...InteractiveComponent) ActionRowComponent { return components } @@ -216,7 +214,6 @@ const ( ) // NewButton creates a new ButtonComponent with the provided parameters. Link ButtonComponent(s) need a URL and other ButtonComponent(s) need a customID -//goland:noinspection GoUnusedExportedFunction func NewButton(style ButtonStyle, label string, customID CustomID, url string) ButtonComponent { return ButtonComponent{ Style: style, @@ -227,31 +224,26 @@ func NewButton(style ButtonStyle, label string, customID CustomID, url string) B } // NewPrimaryButton creates a new ButtonComponent with ButtonStylePrimary & the provided parameters -//goland:noinspection GoUnusedExportedFunction func NewPrimaryButton(label string, customID CustomID) ButtonComponent { return NewButton(ButtonStylePrimary, label, customID, "") } // NewSecondaryButton creates a new ButtonComponent with ButtonStyleSecondary & the provided parameters -//goland:noinspection GoUnusedExportedFunction func NewSecondaryButton(label string, customID CustomID) ButtonComponent { return NewButton(ButtonStyleSecondary, label, customID, "") } // NewSuccessButton creates a new ButtonComponent with ButtonStyleSuccess & the provided parameters -//goland:noinspection GoUnusedExportedFunction func NewSuccessButton(label string, customID CustomID) ButtonComponent { return NewButton(ButtonStyleSuccess, label, customID, "") } // NewDangerButton creates a new ButtonComponent with ButtonStyleDanger & the provided parameters -//goland:noinspection GoUnusedExportedFunction func NewDangerButton(label string, customID CustomID) ButtonComponent { return NewButton(ButtonStyleDanger, label, customID, "") } // NewLinkButton creates a new link ButtonComponent with ButtonStyleLink & the provided parameters -//goland:noinspection GoUnusedExportedFunction func NewLinkButton(label string, url string) ButtonComponent { return NewButton(ButtonStyleLink, label, "", url) } @@ -346,7 +338,6 @@ func (c ButtonComponent) WithDisabled(disabled bool) ButtonComponent { } // NewSelectMenu builds a new SelectMenuComponent from the provided values -//goland:noinspection GoUnusedExportedFunction func NewSelectMenu(customID CustomID, placeholder string, options ...SelectMenuOption) SelectMenuComponent { return SelectMenuComponent{ CustomID: customID, @@ -363,7 +354,7 @@ var ( type SelectMenuComponent struct { CustomID CustomID `json:"custom_id"` Placeholder string `json:"placeholder,omitempty"` - MinValues json.NullInt `json:"min_values,omitempty"` + MinValues *int `json:"min_values,omitempty"` MaxValues int `json:"max_values,omitempty"` Disabled bool `json:"disabled,omitempty"` Options []SelectMenuOption `json:"options,omitempty"` @@ -410,7 +401,7 @@ func (c SelectMenuComponent) WithPlaceholder(placeholder string) SelectMenuCompo // WithMinValues returns a new SelectMenuComponent with the provided minValue func (c SelectMenuComponent) WithMinValues(minValue int) SelectMenuComponent { - c.MinValues = *json.NewInt(minValue) + c.MinValues = &minValue return c } @@ -470,7 +461,6 @@ func (c SelectMenuComponent) RemoveOption(index int) SelectMenuComponent { } // NewSelectMenuOption builds a new SelectMenuOption -//goland:noinspection GoUnusedExportedFunction func NewSelectMenuOption(label string, value string) SelectMenuOption { return SelectMenuOption{ Label: label, @@ -523,7 +513,6 @@ var ( _ InputComponent = (*TextInputComponent)(nil) ) -//goland:noinspection GoUnusedExportedFunction func NewTextInput(customID CustomID, style TextInputStyle, label string) TextInputComponent { return TextInputComponent{ CustomID: customID, @@ -532,12 +521,10 @@ func NewTextInput(customID CustomID, style TextInputStyle, label string) TextInp } } -//goland:noinspection GoUnusedExportedFunction func NewShortTextInput(customID CustomID, label string) TextInputComponent { return NewTextInput(customID, TextInputStyleShort, label) } -//goland:noinspection GoUnusedExportedFunction func NewParagraphTextInput(customID CustomID, label string) TextInputComponent { return NewTextInput(customID, TextInputStyleParagraph, label) } @@ -546,7 +533,7 @@ type TextInputComponent struct { CustomID CustomID `json:"custom_id"` Style TextInputStyle `json:"style"` Label string `json:"label"` - MinLength json.NullInt `json:"min_length,omitempty"` + MinLength *int `json:"min_length,omitempty"` MaxLength int `json:"max_length,omitempty"` Required bool `json:"required,omitempty"` Placeholder string `json:"placeholder,omitempty"` @@ -595,7 +582,7 @@ func (c TextInputComponent) WithStyle(style TextInputStyle) TextInputComponent { // WithMinLength returns a new TextInputComponent with the provided minLength func (c TextInputComponent) WithMinLength(minLength int) TextInputComponent { - c.MinLength = *json.NewInt(minLength) + c.MinLength = &minLength return c } @@ -625,7 +612,6 @@ func (c TextInputComponent) WithValue(value string) TextInputComponent { type TextInputStyle int -//goland:noinspection GoUnusedConst const ( TextInputStyleShort = iota + 1 TextInputStyleParagraph diff --git a/discord/connection.go b/discord/connection.go index 00b40528..e03117f0 100644 --- a/discord/connection.go +++ b/discord/connection.go @@ -1,6 +1,6 @@ package discord -import "github.com/DisgoOrg/snowflake" +import "github.com/disgoorg/snowflake" type Connection struct { ID snowflake.Snowflake `json:"id"` @@ -16,7 +16,6 @@ type Connection struct { type ConnectionType string -//goland:noinspection GoUnusedConst const ( ConnectionTypeYouTube ConnectionType = "youtube" ConnectionTypeBattleNet ConnectionType = "battlenet" @@ -32,7 +31,6 @@ const ( type VisibilityType int -//goland:noinspection GoUnusedConst const ( VisibilityTypeNone VisibilityType = iota VisibilityTypeEveryone diff --git a/discord/embed.go b/discord/embed.go index 7e07ea79..fb5d3de7 100644 --- a/discord/embed.go +++ b/discord/embed.go @@ -4,7 +4,6 @@ package discord type EmbedType string // Constants for EmbedType -//goland:noinspection GoUnusedConst const ( EmbedTypeRich EmbedType = "rich" EmbedTypeImage EmbedType = "image" diff --git a/discord/embed_builder.go b/discord/embed_builder.go index a8c9e209..31c241cc 100644 --- a/discord/embed_builder.go +++ b/discord/embed_builder.go @@ -22,7 +22,7 @@ func (b *EmbedBuilder) SetTitle(title string) *EmbedBuilder { } // SetTitlef sets the title of the EmbedBuilder with format -func (b *EmbedBuilder) SetTitlef(title string, a ...interface{}) *EmbedBuilder { +func (b *EmbedBuilder) SetTitlef(title string, a ...any) *EmbedBuilder { return b.SetTitle(fmt.Sprintf(title, a...)) } @@ -33,7 +33,7 @@ func (b *EmbedBuilder) SetDescription(description string) *EmbedBuilder { } // SetDescriptionf sets the description of the EmbedBuilder with format -func (b *EmbedBuilder) SetDescriptionf(description string, a ...interface{}) *EmbedBuilder { +func (b *EmbedBuilder) SetDescriptionf(description string, a ...any) *EmbedBuilder { descriptionf := fmt.Sprintf(description, a...) b.Description = descriptionf return b diff --git a/discord/emoji.go b/discord/emoji.go index 16d996de..89298398 100644 --- a/discord/emoji.go +++ b/discord/emoji.go @@ -1,6 +1,9 @@ package discord -import "github.com/DisgoOrg/snowflake" +import ( + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" +) var _ Mentionable = (*Emoji)(nil) @@ -14,16 +17,14 @@ type Emoji struct { Managed bool `json:"managed,omitempty"` Animated bool `json:"animated,omitempty"` Available bool `json:"available,omitempty"` - - GuildID snowflake.Snowflake `json:"guild_id,omitempty"` } // Mention returns the string used to send the Emoji func (e Emoji) Mention() string { if e.Animated { - return animatedEmojiMention(e.ID, e.Name) + return AnimatedEmojiMention(e.ID, e.Name) } - return emojiMention(e.ID, e.Name) + return EmojiMention(e.ID, e.Name) } // String formats the Emoji as string @@ -31,6 +32,13 @@ func (e Emoji) String() string { return e.Mention() } +func (e Emoji) URL(opts ...CDNOpt) string { + if avatar := formatAssetURL(route.CustomEmoji, opts, e.ID); avatar != nil { + return *avatar + } + return "" +} + type EmojiCreate struct { Name string `json:"name"` Image Icon `json:"image"` diff --git a/discord/error.go b/discord/error.go index 96feb025..4706d6d3 100644 --- a/discord/error.go +++ b/discord/error.go @@ -1,8 +1,9 @@ package discord import ( - "github.com/DisgoOrg/disgo/json" - "github.com/pkg/errors" + "fmt" + + "github.com/disgoorg/disgo/json" ) type ErrorCode int @@ -22,7 +23,7 @@ func (e *APIError) UnmarshalJSON(data []byte) error { Errors json.RawMessage `json:"errors"` } if err := json.Unmarshal(data, &v); err != nil { - return errors.Wrap(err, "error unmarshalling discord error") + return fmt.Errorf("error unmarshalling discord error: %w", err) } e.Code = v.Code diff --git a/discord/errors.go b/discord/errors.go index e177ff33..1d7f54d1 100644 --- a/discord/errors.go +++ b/discord/errors.go @@ -1,10 +1,9 @@ package discord import ( - "github.com/pkg/errors" + "errors" ) -//goland:noinspection GoUnusedGlobalVariable var ( ErrNoGatewayOrShardManager = errors.New("no gateway or shard manager configured") ErrNoGuildMembersIntent = errors.New("this operation requires the GUILD_MEMBERS intent") @@ -18,8 +17,8 @@ var ( ErrNoDisgoInstance = errors.New("no disgo instance injected") - ErrInvalidBotToken = errors.New("BotToken is not in a valid format") - ErrNoBotToken = errors.New("please specify the BotToken") + ErrInvalidBotToken = errors.New("token is not in a valid format") + ErrNoBotToken = errors.New("please specify the token") ErrSelfDM = errors.New("can't open a dm channel to yourself") diff --git a/discord/file.go b/discord/file.go index 4611f13e..355f5bd6 100644 --- a/discord/file.go +++ b/discord/file.go @@ -7,11 +7,11 @@ import ( "mime/multipart" "net/textproto" - "github.com/DisgoOrg/disgo/json" + "github.com/disgoorg/disgo/json" ) type Payload interface { - ToBody() (interface{}, error) + ToBody() (any, error) } // MultipartBuffer holds the Body & ContentType of the multipart body @@ -21,8 +21,7 @@ type MultipartBuffer struct { } // PayloadWithFiles returns the given payload as multipart body with all files in it -//goland:noinspection GoUnusedExportedFunction -func PayloadWithFiles(v interface{}, files ...*File) (*MultipartBuffer, error) { +func PayloadWithFiles(v any, files ...*File) (*MultipartBuffer, error) { buffer := &bytes.Buffer{} writer := multipart.NewWriter(buffer) writer.FormDataContentType() @@ -74,21 +73,36 @@ func partHeader(contentDisposition string, contentType string) textproto.MIMEHea } } +func parseAttachments(files []*File) []AttachmentCreate { + var attachments []AttachmentCreate + for i, file := range files { + if file.Description == "" { + continue + } + attachments = append(attachments, AttachmentCreate{ + ID: i, + Description: file.Description, + }) + } + return attachments +} + // NewFile returns a new File struct with the given name, io.Reader & FileFlags -//goland:noinspection GoUnusedExportedFunction -func NewFile(name string, reader io.Reader, flags ...FileFlags) *File { +func NewFile(name string, description string, reader io.Reader, flags ...FileFlags) *File { return &File{ - Name: name, - Reader: reader, - Flags: FileFlagNone.Add(flags...), + Name: name, + Description: description, + Reader: reader, + Flags: FileFlagNone.Add(flags...), } } // File holds all information about a given io.Reader type File struct { - Name string - Reader io.Reader - Flags FileFlags + Name string + Description string + Reader io.Reader + Flags FileFlags } // FileFlags are used to mark Attachments as Spoiler diff --git a/discord/gateway.go b/discord/gateway.go index 074f6b35..deed7645 100644 --- a/discord/gateway.go +++ b/discord/gateway.go @@ -1,12 +1,5 @@ package discord -import ( - "time" - - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" -) - type Gateway struct { URL string `json:"url"` } @@ -23,165 +16,3 @@ type SessionStartLimit struct { ResetAfter int `json:"reset_after"` MaxConcurrency int `json:"max_concurrency"` } - -type ChannelPinsUpdateGatewayEvent struct { - GuildID *snowflake.Snowflake `json:"guild_id"` - ChannelID snowflake.Snowflake `json:"channel_id"` - LastPinTimestamp *Time `json:"last_pin_timestamp"` -} - -type GuildMembersChunkGatewayEvent struct { - GuildID snowflake.Snowflake `json:"guild_id"` - Members []Member `json:"members"` - ChunkIndex int `json:"chunk_index"` - ChunkCount int `json:"chunk_count"` - NotFound []snowflake.Snowflake `json:"not_found"` - Presences []Presence `json:"presences"` - Nonce string `json:"nonce"` -} - -type GuildBanAddGatewayEvent struct { - GuildID snowflake.Snowflake `json:"guild_id"` - User User `json:"user"` -} - -type GuildBanRemoveGatewayEvent struct { - GuildID snowflake.Snowflake `json:"guild_id"` - User User `json:"user"` -} - -type GuildEmojisUpdateGatewayEvent struct { - GuildID snowflake.Snowflake `json:"guild_id"` - Emojis []Emoji `json:"emojis"` -} - -type GuildStickersUpdateGatewayEvent struct { - GuildID snowflake.Snowflake `json:"guild_id"` - Stickers []Sticker `json:"stickers"` -} - -type GuildIntegrationsUpdateGatewayEvent struct { - GuildID snowflake.Snowflake `json:"guild_id"` -} - -type GuildMemberRemoveGatewayEvent struct { - GuildID snowflake.Snowflake `json:"guild_id"` - User User `json:"user"` -} - -type GuildRoleCreateGatewayEvent struct { - GuildID snowflake.Snowflake `json:"guild_id"` - Role Role `json:"role"` -} - -type GuildRoleDeleteGatewayEvent struct { - GuildID snowflake.Snowflake `json:"guild_id"` - RoleID snowflake.Snowflake `json:"role_id"` -} - -type GuildRoleUpdateGatewayEvent struct { - GuildID snowflake.Snowflake `json:"guild_id"` - Role Role `json:"role"` -} - -type GuildScheduledEventUserEvent struct { - GuildScheduledEventID snowflake.Snowflake `json:"guild_scheduled_event_id"` - UserID snowflake.Snowflake `json:"user_id"` - GuildID snowflake.Snowflake `json:"guild_id"` -} - -type InviteDeleteGatewayEvent struct { - ChannelID snowflake.Snowflake `json:"channel_id"` - GuildID *snowflake.Snowflake `json:"guild_id"` - Code string `json:"code"` -} - -type MessageDeleteGatewayEvent struct { - ID snowflake.Snowflake `json:"id"` - ChannelID snowflake.Snowflake `json:"channel_id"` - GuildID *snowflake.Snowflake `json:"guild_id,omitempty"` -} - -type MessageDeleteBulkGatewayEvent struct { - IDs []snowflake.Snowflake `json:"id"` - ChannelID snowflake.Snowflake `json:"channel_id"` - GuildID *snowflake.Snowflake `json:"guild_id,omitempty"` -} - -type TypingStartGatewayEvent struct { - ChannelID snowflake.Snowflake `json:"channel_id"` - GuildID *snowflake.Snowflake `json:"guild_id,omitempty"` - UserID snowflake.Snowflake `json:"user_id"` - Timestamp time.Time `json:"timestamp"` - Member *Member `json:"member,omitempty"` - User User `json:"user"` -} - -func (e *TypingStartGatewayEvent) UnmarshalJSON(data []byte) error { - type typingStartGatewayEvent TypingStartGatewayEvent - var v struct { - Timestamp int64 `json:"timestamp"` - typingStartGatewayEvent - } - if err := json.Unmarshal(data, &v); err != nil { - return err - } - *e = TypingStartGatewayEvent(v.typingStartGatewayEvent) - e.Timestamp = time.Unix(v.Timestamp, 0) - return nil -} - -type WebhooksUpdateGatewayEvent struct { - GuildID snowflake.Snowflake `json:"guild_id"` - ChannelID snowflake.Snowflake `json:"channel_id"` -} - -type IntegrationCreateGatewayEvent struct { - Integration - GuildID snowflake.Snowflake `json:"guild_id"` -} - -func (e *IntegrationCreateGatewayEvent) UnmarshalJSON(data []byte) error { - type integrationCreateGatewayEvent IntegrationCreateGatewayEvent - var v struct { - UnmarshalIntegration - integrationCreateGatewayEvent - } - - if err := json.Unmarshal(data, &v); err != nil { - return err - } - - *e = IntegrationCreateGatewayEvent(v.integrationCreateGatewayEvent) - - e.Integration = v.UnmarshalIntegration.Integration - return nil -} - -type IntegrationUpdateGatewayEvent struct { - Integration - GuildID snowflake.Snowflake `json:"guild_id"` -} - -func (e *IntegrationUpdateGatewayEvent) UnmarshalJSON(data []byte) error { - type integrationUpdateGatewayEvent IntegrationUpdateGatewayEvent - var v struct { - UnmarshalIntegration - integrationUpdateGatewayEvent - } - - if err := json.Unmarshal(data, &v); err != nil { - return err - } - - *e = IntegrationUpdateGatewayEvent(v.integrationUpdateGatewayEvent) - - e.Integration = v.UnmarshalIntegration.Integration - return nil -} - -type IntegrationDeleteGatewayEvent struct { - ID snowflake.Snowflake `json:"id"` - GuildID snowflake.Snowflake `json:"guild_id"` - ApplicationID *snowflake.Snowflake `json:"application_id"` -} diff --git a/discord/gateway_commands.go b/discord/gateway_commands.go deleted file mode 100644 index 9f7e3fe1..00000000 --- a/discord/gateway_commands.go +++ /dev/null @@ -1,105 +0,0 @@ -package discord - -import "github.com/DisgoOrg/snowflake" - -// NewGatewayCommand returns a new GatewayCommand struct with the given payload -func NewGatewayCommand(op GatewayOpcode, d GatewayCommandData) GatewayCommand { - return GatewayCommand{ - GatewayPayload: GatewayPayload{ - Op: op, - }, - D: d, - } -} - -// GatewayCommand object is used when sending data to discord's websocket, it's recommended that you don't use these -//goland:noinspection GoNameStartsWithPackageName -type GatewayCommand struct { - GatewayPayload - D GatewayCommandData `json:"d"` -} - -type GatewayCommandData interface { - gatewayCommandData() -} - -var _ GatewayCommandData = (*GatewaySequence)(nil) - -type GatewaySequence int - -func (GatewaySequence) gatewayCommandData() {} - -var _ GatewayCommandData = (*IdentifyCommandData)(nil) - -// IdentifyCommandData is the data used in IdentifyCommandData -type IdentifyCommandData struct { - Token string `json:"token"` - Properties IdentifyCommandDataProperties `json:"properties"` - Compress bool `json:"compress,omitempty"` - LargeThreshold int `json:"large_threshold,omitempty"` - Shard []int `json:"shard,omitempty"` - GatewayIntents GatewayIntents `json:"intents"` - Presence *UpdatePresenceCommandData `json:"presence,omitempty"` -} - -func (IdentifyCommandData) gatewayCommandData() {} - -// IdentifyCommandDataProperties is used for specifying to discord which library and OS the bot is using, is -// automatically handled by the library and should rarely be used. -type IdentifyCommandDataProperties struct { - OS string `json:"$os"` // user OS - Browser string `json:"$browser"` // library name - Device string `json:"$device"` // library name -} - -var _ GatewayCommandData = (*IdentifyCommandData)(nil) - -// ResumeCommandData is used to resume a connection to discord in the case that you are disconnected. Is automatically -// handled by the library and should rarely be used. -type ResumeCommandData struct { - Token string `json:"token"` - SessionID string `json:"session_id"` - Seq GatewaySequence `json:"seq"` -} - -func (ResumeCommandData) gatewayCommandData() {} - -var _ GatewayCommandData = (*HeartbeatCommandData)(nil) - -// HeartbeatCommandData is used to ensure the websocket connection remains open, and disconnect if not. -type HeartbeatCommandData int - -func (HeartbeatCommandData) gatewayCommandData() {} - -// RequestGuildMembersCommandData is used for fetching all the members of a guild_events. It is recommended you have a strict -// member caching policy when using this. -type RequestGuildMembersCommandData struct { - GuildID snowflake.Snowflake `json:"guild_id"` - Query *string `json:"query,omitempty"` //If specified, user_ids must not be entered - Limit *int `json:"limit,omitempty"` //Must be >=1 if query/user_ids is used, otherwise 0 - Presences bool `json:"presences,omitempty"` - UserIDs []snowflake.Snowflake `json:"user_ids,omitempty"` //If specified, query must not be entered - Nonce string `json:"nonce,omitempty"` //All responses are hashed with this nonce, optional -} - -func (RequestGuildMembersCommandData) gatewayCommandData() {} - -// UpdateVoiceStateCommandData is used for updating the bots voice state in a guild_events -type UpdateVoiceStateCommandData struct { - GuildID snowflake.Snowflake `json:"guild_id"` - ChannelID *snowflake.Snowflake `json:"channel_id"` - SelfMute bool `json:"self_mute"` - SelfDeaf bool `json:"self_deaf"` -} - -func (UpdateVoiceStateCommandData) gatewayCommandData() {} - -// UpdatePresenceCommandData is used for updating Bot's presence -type UpdatePresenceCommandData struct { - Since *int64 `json:"since"` - Activities []Activity `json:"activities"` - Status OnlineStatus `json:"status"` - AFK bool `json:"afk"` -} - -func (UpdatePresenceCommandData) gatewayCommandData() {} diff --git a/discord/gateway_event_type.go b/discord/gateway_event_type.go index 4389ed88..5f84588b 100644 --- a/discord/gateway_event_type.go +++ b/discord/gateway_event_type.go @@ -4,7 +4,6 @@ package discord type GatewayEventType string // Constants for the gateway events -//goland:noinspection GoUnusedConst const ( GatewayEventTypeHello GatewayEventType = "HELLO" GatewayEventTypeReady GatewayEventType = "READY" diff --git a/discord/gateway_events.go b/discord/gateway_events.go index f70f383a..20e679fc 100644 --- a/discord/gateway_events.go +++ b/discord/gateway_events.go @@ -3,18 +3,10 @@ package discord import ( "time" - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" ) -// GatewayPayload raw GatewayEvent type -type GatewayPayload struct { - Op GatewayOpcode `json:"op"` - S GatewaySequence `json:"s,omitempty"` - T GatewayEventType `json:"t,omitempty"` - D json.RawMessage `json:"d,omitempty"` -} - // GatewayEventReady is the event sent by discord when you successfully Identify type GatewayEventReady struct { Version int `json:"v"` @@ -25,11 +17,6 @@ type GatewayEventReady struct { Application PartialApplication `json:"application"` } -// GatewayEventHello is sent when we connect to the gateway -type GatewayEventHello struct { - HeartbeatInterval time.Duration `json:"heartbeat_interval"` -} - type GatewayEventThreadCreate struct { GuildThread ThreadMember ThreadMember `json:"thread_member"` @@ -95,14 +82,14 @@ func (e *GatewayEventThreadListSync) UnmarshalJSON(data []byte) error { } type GatewayEventThreadMembersUpdate struct { - ID snowflake.Snowflake `json:"id"` - GuildID snowflake.Snowflake `json:"guild_id"` - MemberCount int `json:"member_count"` - AddedMembers []ThreadMembersAddedMember `json:"added_members"` - RemovedMemberIDs []snowflake.Snowflake `json:"removed_member_ids"` + ID snowflake.Snowflake `json:"id"` + GuildID snowflake.Snowflake `json:"guild_id"` + MemberCount int `json:"member_count"` + AddedMembers []AddedThreadMember `json:"added_members"` + RemovedMemberIDs []snowflake.Snowflake `json:"removed_member_ids"` } -type ThreadMembersAddedMember struct { +type AddedThreadMember struct { ThreadMember Member Member `json:"member"` Presence *Presence `json:"presence"` @@ -137,3 +124,165 @@ type GatewayEventMessageReactionRemoveAll struct { MessageID snowflake.Snowflake `json:"message_id"` GuildID *snowflake.Snowflake `json:"guild_id"` } + +type GatewayEventChannelPinsUpdate struct { + GuildID *snowflake.Snowflake `json:"guild_id"` + ChannelID snowflake.Snowflake `json:"channel_id"` + LastPinTimestamp *Time `json:"last_pin_timestamp"` +} + +type GatewayEventGuildMembersChunk struct { + GuildID snowflake.Snowflake `json:"guild_id"` + Members []Member `json:"members"` + ChunkIndex int `json:"chunk_index"` + ChunkCount int `json:"chunk_count"` + NotFound []snowflake.Snowflake `json:"not_found"` + Presences []Presence `json:"presences"` + Nonce string `json:"nonce"` +} + +type GatewayEventGuildBanAdd struct { + GuildID snowflake.Snowflake `json:"guild_id"` + User User `json:"user"` +} + +type GatewayEventGuildBanRemove struct { + GuildID snowflake.Snowflake `json:"guild_id"` + User User `json:"user"` +} + +type GatewayEventGuildEmojisUpdate struct { + GuildID snowflake.Snowflake `json:"guild_id"` + Emojis []Emoji `json:"emojis"` +} + +type GatewayEventGuildStickersUpdate struct { + GuildID snowflake.Snowflake `json:"guild_id"` + Stickers []Sticker `json:"stickers"` +} + +type GatewayEventGuildIntegrationsUpdate struct { + GuildID snowflake.Snowflake `json:"guild_id"` +} + +type GatewayEventGuildMemberRemove struct { + GuildID snowflake.Snowflake `json:"guild_id"` + User User `json:"user"` +} + +type GatewayEventGuildRoleCreate struct { + GuildID snowflake.Snowflake `json:"guild_id"` + Role Role `json:"role"` +} + +type GatewayEventGuildRoleDelete struct { + GuildID snowflake.Snowflake `json:"guild_id"` + RoleID snowflake.Snowflake `json:"role_id"` +} + +type GatewayEventGuildRoleUpdate struct { + GuildID snowflake.Snowflake `json:"guild_id"` + Role Role `json:"role"` +} + +type GatewayEventGuildScheduledEventUser struct { + GuildScheduledEventID snowflake.Snowflake `json:"guild_scheduled_event_id"` + UserID snowflake.Snowflake `json:"user_id"` + GuildID snowflake.Snowflake `json:"guild_id"` +} + +type GatewayEventInviteDelete struct { + ChannelID snowflake.Snowflake `json:"channel_id"` + GuildID *snowflake.Snowflake `json:"guild_id"` + Code string `json:"code"` +} + +type GatewayEventMessageDelete struct { + ID snowflake.Snowflake `json:"id"` + ChannelID snowflake.Snowflake `json:"channel_id"` + GuildID *snowflake.Snowflake `json:"guild_id,omitempty"` +} + +type GatewayEventMessageDeleteBulk struct { + IDs []snowflake.Snowflake `json:"id"` + ChannelID snowflake.Snowflake `json:"channel_id"` + GuildID *snowflake.Snowflake `json:"guild_id,omitempty"` +} + +type GatewayEventTypingStart struct { + ChannelID snowflake.Snowflake `json:"channel_id"` + GuildID *snowflake.Snowflake `json:"guild_id,omitempty"` + UserID snowflake.Snowflake `json:"user_id"` + Timestamp time.Time `json:"timestamp"` + Member *Member `json:"member,omitempty"` + User User `json:"user"` +} + +func (e *GatewayEventTypingStart) UnmarshalJSON(data []byte) error { + type typingStartGatewayEvent GatewayEventTypingStart + var v struct { + Timestamp int64 `json:"timestamp"` + typingStartGatewayEvent + } + if err := json.Unmarshal(data, &v); err != nil { + return err + } + *e = GatewayEventTypingStart(v.typingStartGatewayEvent) + e.Timestamp = time.Unix(v.Timestamp, 0) + return nil +} + +type GatewayEventWebhooksUpdate struct { + GuildID snowflake.Snowflake `json:"guild_id"` + ChannelID snowflake.Snowflake `json:"channel_id"` +} + +type GatewayEventIntegrationCreate struct { + Integration + GuildID snowflake.Snowflake `json:"guild_id"` +} + +func (e *GatewayEventIntegrationCreate) UnmarshalJSON(data []byte) error { + type integrationCreateGatewayEvent GatewayEventIntegrationCreate + var v struct { + UnmarshalIntegration + integrationCreateGatewayEvent + } + + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + *e = GatewayEventIntegrationCreate(v.integrationCreateGatewayEvent) + + e.Integration = v.UnmarshalIntegration.Integration + return nil +} + +type GatewayEventIntegrationUpdate struct { + Integration + GuildID snowflake.Snowflake `json:"guild_id"` +} + +func (e *GatewayEventIntegrationUpdate) UnmarshalJSON(data []byte) error { + type integrationUpdateGatewayEvent GatewayEventIntegrationUpdate + var v struct { + UnmarshalIntegration + integrationUpdateGatewayEvent + } + + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + *e = GatewayEventIntegrationUpdate(v.integrationUpdateGatewayEvent) + + e.Integration = v.UnmarshalIntegration.Integration + return nil +} + +type GatewayEventIntegrationDelete struct { + ID snowflake.Snowflake `json:"id"` + GuildID snowflake.Snowflake `json:"guild_id"` + ApplicationID *snowflake.Snowflake `json:"application_id"` +} diff --git a/discord/gateway_intents.go b/discord/gateway_intents.go index 3a38f676..b38afa20 100644 --- a/discord/gateway_intents.go +++ b/discord/gateway_intents.go @@ -4,7 +4,6 @@ package discord type GatewayIntents int64 // Constants for the different bit offsets of GatewayIntents -//goland:noinspection GoUnusedConst const ( GatewayIntentGuilds GatewayIntents = 1 << iota GatewayIntentGuildMembers diff --git a/discord/gateway_messages.go b/discord/gateway_messages.go new file mode 100644 index 00000000..56dc6cee --- /dev/null +++ b/discord/gateway_messages.go @@ -0,0 +1,179 @@ +package discord + +import ( + "errors" + + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" +) + +// GatewayMessage raw GatewayMessage type +type GatewayMessage struct { + Op GatewayOpcode `json:"op"` + S int `json:"s"` + T GatewayEventType `json:"t"` + D GatewayMessageData `json:"d,omitempty"` +} + +func (e *GatewayMessage) UnmarshalJSON(data []byte) error { + type gatewayMessage GatewayMessage + var v struct { + D json.RawMessage `json:"d,omitempty"` + gatewayMessage + } + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + var ( + messageData GatewayMessageData + err error + ) + + switch v.Op { + case GatewayOpcodeDispatch: + messageData = GatewayMessageDataDispatch(v.D) + + case GatewayOpcodeHeartbeat: + var d GatewayMessageDataHeartbeat + err = json.Unmarshal(v.D, &d) + messageData = d + + case GatewayOpcodeIdentify: + var d GatewayMessageDataIdentify + err = json.Unmarshal(v.D, &d) + messageData = d + + case GatewayOpcodePresenceUpdate: + var d GatewayMessageDataPresenceUpdate + err = json.Unmarshal(v.D, &d) + messageData = d + + case GatewayOpcodeVoiceStateUpdate: + var d GatewayMessageDataVoiceStateUpdate + err = json.Unmarshal(v.D, &d) + messageData = d + + case GatewayOpcodeResume: + var d GatewayMessageDataResume + err = json.Unmarshal(v.D, &d) + messageData = d + + case GatewayOpcodeReconnect: + // no data + + case GatewayOpcodeRequestGuildMembers: + var d GatewayMessageDataRequestGuildMembers + err = json.Unmarshal(v.D, &d) + messageData = d + + case GatewayOpcodeInvalidSession: + var d GatewayMessageDataInvalidSession + err = json.Unmarshal(v.D, &d) + messageData = d + + case GatewayOpcodeHello: + var d GatewayMessageDataHello + err = json.Unmarshal(v.D, &d) + messageData = d + + case GatewayOpcodeHeartbeatACK: + // no data + + default: + err = errors.New("unknown gateway event type") + } + if err != nil { + return err + } + *e = GatewayMessage(v.gatewayMessage) + e.D = messageData + return nil +} + +type GatewayMessageData interface { + gatewayMessageData() +} + +type GatewayMessageDataDispatch json.RawMessage + +func (GatewayMessageDataDispatch) gatewayMessageData() {} + +// GatewayMessageDataHeartbeat is used to ensure the websocket connection remains open, and disconnect if not. +type GatewayMessageDataHeartbeat int + +func (GatewayMessageDataHeartbeat) gatewayMessageData() {} + +// GatewayMessageDataIdentify is the data used in IdentifyCommandData +type GatewayMessageDataIdentify struct { + Token string `json:"token"` + Properties IdentifyCommandDataProperties `json:"properties"` + Compress bool `json:"compress,omitempty"` + LargeThreshold int `json:"large_threshold,omitempty"` + Shard []int `json:"shard,omitempty"` + GatewayIntents GatewayIntents `json:"intents"` + Presence *GatewayMessageDataPresenceUpdate `json:"presence,omitempty"` +} + +func (GatewayMessageDataIdentify) gatewayMessageData() {} + +// IdentifyCommandDataProperties is used for specifying to discord which library and OS the bot is using, is +// automatically handled by the library and should rarely be used. +type IdentifyCommandDataProperties struct { + OS string `json:"$os"` // user OS + Browser string `json:"$browser"` // library name + Device string `json:"$device"` // library name +} + +// GatewayMessageDataPresenceUpdate is used for updating Client's presence +type GatewayMessageDataPresenceUpdate struct { + Since *int64 `json:"since"` + Activities []Activity `json:"activities"` + Status OnlineStatus `json:"status"` + AFK bool `json:"afk"` +} + +func (GatewayMessageDataPresenceUpdate) gatewayMessageData() {} + +// GatewayMessageDataVoiceStateUpdate is used for updating the bots voice state in a guild +type GatewayMessageDataVoiceStateUpdate struct { + GuildID snowflake.Snowflake `json:"guild_id"` + ChannelID *snowflake.Snowflake `json:"channel_id"` + SelfMute bool `json:"self_mute"` + SelfDeaf bool `json:"self_deaf"` +} + +func (GatewayMessageDataVoiceStateUpdate) gatewayMessageData() {} + +// GatewayMessageDataResume is used to resume a connection to discord in the case that you are disconnected. Is automatically +// handled by the library and should rarely be used. +type GatewayMessageDataResume struct { + Token string `json:"token"` + SessionID string `json:"session_id"` + Seq int `json:"seq"` +} + +func (GatewayMessageDataResume) gatewayMessageData() {} + +// GatewayMessageDataRequestGuildMembers is used for fetching all the members of a guild_events. It is recommended you have a strict +// member caching policy when using this. +type GatewayMessageDataRequestGuildMembers struct { + GuildID snowflake.Snowflake `json:"guild_id"` + Query *string `json:"query,omitempty"` //If specified, user_ids must not be entered + Limit *int `json:"limit,omitempty"` //Must be >=1 if query/user_ids is used, otherwise 0 + Presences bool `json:"presences,omitempty"` + UserIDs []snowflake.Snowflake `json:"user_ids,omitempty"` //If specified, query must not be entered + Nonce string `json:"nonce,omitempty"` //All responses are hashed with this nonce, optional +} + +func (GatewayMessageDataRequestGuildMembers) gatewayMessageData() {} + +type GatewayMessageDataInvalidSession bool + +func (GatewayMessageDataInvalidSession) gatewayMessageData() {} + +type GatewayMessageDataHello struct { + HeartbeatInterval int `json:"heartbeat_interval"` +} + +func (GatewayMessageDataHello) gatewayMessageData() {} diff --git a/discord/guild.go b/discord/guild.go index fd87674a..72566146 100644 --- a/discord/guild.go +++ b/discord/guild.go @@ -1,15 +1,15 @@ package discord import ( - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) // PremiumTier tells you the boost level of a Guild type PremiumTier int // Constants for PremiumTier -//goland:noinspection GoUnusedConst const ( PremiumTierNone PremiumTier = iota PremiumTier1 @@ -21,7 +21,6 @@ const ( type SystemChannelFlags int // Constants for SystemChannelFlags -//goland:noinspection GoUnusedConst const ( SystemChannelFlagSuppressJoinNotifications SystemChannelFlags = 1 << iota SystemChannelFlagSuppressPremiumSubscriptions @@ -31,7 +30,6 @@ const ( type VerificationLevel int // Constants for VerificationLevel -//goland:noinspection GoUnusedConst const ( VerificationLevelNone VerificationLevel = iota VerificationLevelLow @@ -44,7 +42,6 @@ const ( type MessageNotificationsLevel int // Constants for MessageNotificationsLevel -//goland:noinspection GoUnusedConst const ( MessageNotificationsLevelAllMessages MessageNotificationsLevel = iota MessageNotificationsLevelOnlyMentions @@ -54,7 +51,6 @@ const ( type ExplicitContentFilterLevel int // Constants for ExplicitContentFilterLevel -//goland:noinspection GoUnusedConst const ( ExplicitContentFilterLevelDisabled ExplicitContentFilterLevel = iota ExplicitContentFilterLevelMembersWithoutRoles @@ -65,7 +61,6 @@ const ( type MFALevel int // Constants for MFALevel -//goland:noinspection GoUnusedConst const ( MFALevelNone MFALevel = iota MFALevelElevated @@ -75,7 +70,6 @@ const ( type GuildFeature string // Constants for GuildFeature -//goland:noinspection GoUnusedConst const ( GuildFeatureAnimatedIcon GuildFeature = "ANIMATED_ICON" GuildFeatureBanner GuildFeature = "BANNER" @@ -146,6 +140,22 @@ type Guild struct { ApproximatePresenceCount int `json:"approximate_presence_count"` } +func (g Guild) IconURL(opts ...CDNOpt) *string { + return formatAssetURL(route.GuildIcon, opts, g.ID, g.Icon) +} + +func (g Guild) SplashURL(opts ...CDNOpt) *string { + return formatAssetURL(route.GuildSplash, opts, g.ID, g.Splash) +} + +func (g Guild) DiscoverySplashURL(opts ...CDNOpt) *string { + return formatAssetURL(route.GuildDiscoverySplash, opts, g.ID, g.DiscoverySplash) +} + +func (g Guild) BannerURL(opts ...CDNOpt) *string { + return formatAssetURL(route.GuildBanner, opts, g.ID, g.Banner) +} + type GatewayGuild struct { Guild Large bool `json:"large"` @@ -163,7 +173,6 @@ func (g *GatewayGuild) UnmarshalJSON(data []byte) error { type gatewayGuild GatewayGuild var v struct { Channels []UnmarshalChannel `json:"channels"` - Threads []UnmarshalChannel `json:"threads"` gatewayGuild } if err := json.Unmarshal(data, &v); err != nil { @@ -177,11 +186,6 @@ func (g *GatewayGuild) UnmarshalJSON(data []byte) error { g.Channels[i] = v.Channels[i].Channel.(GuildChannel) } - g.Threads = make([]GuildThread, len(v.Threads)) - for i := range v.Threads { - g.Threads[i] = v.Threads[i].Channel.(GuildThread) - } - return nil } @@ -251,11 +255,11 @@ type GuildUpdate struct { ExplicitContentFilterLevel *ExplicitContentFilterLevel `json:"explicit_content_filter_level,omitempty"` AFKChannelID *snowflake.Snowflake `json:"afk_channel_id,omitempty"` AFKTimeout *int `json:"afk_timeout,omitempty"` - Icon *NullIcon `json:"icon,omitempty"` + Icon *json.Nullable[Icon] `json:"icon,omitempty"` OwnerID *snowflake.Snowflake `json:"owner_id,omitempty"` - Splash *NullIcon `json:"splash,omitempty"` - DiscoverySplash *NullIcon `json:"discovery_splash,omitempty"` - Banner *NullIcon `json:"banner,omitempty"` + Splash *json.Nullable[Icon] `json:"splash,omitempty"` + DiscoverySplash *json.Nullable[Icon] `json:"discovery_splash,omitempty"` + Banner *json.Nullable[Icon] `json:"banner,omitempty"` SystemChannelID *snowflake.Snowflake `json:"system_channel_id,omitempty"` SystemChannelFlags *SystemChannelFlags `json:"system_channel_flags,omitempty"` RulesChannelID *snowflake.Snowflake `json:"rules_channel_id,omitempty"` @@ -268,7 +272,6 @@ type GuildUpdate struct { type NSFWLevel int -//goland:noinspection GoUnusedConst const ( NSFWLevelDefault NSFWLevel = iota NSFWLevelExplicit diff --git a/discord/guild_scheduled_event.go b/discord/guild_scheduled_event.go index 477f49ac..f8a9b65a 100644 --- a/discord/guild_scheduled_event.go +++ b/discord/guild_scheduled_event.go @@ -1,6 +1,6 @@ package discord -import "github.com/DisgoOrg/snowflake" +import "github.com/disgoorg/snowflake" // GuildScheduledEvent a representation of a scheduled event in a Guild (https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-object) type GuildScheduledEvent struct { @@ -53,7 +53,6 @@ type GuildScheduledEventUser struct { // ScheduledEventPrivacyLevel the privacy level of the ScheduledEventPrivacyLevel (https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-object-guild-scheduled-event-privacy-level) type ScheduledEventPrivacyLevel int -//goland:noinspection GoUnusedConst const ( _ ScheduledEventPrivacyLevel = iota + 1 ScheduledEventPrivacyLevelGuildOnly @@ -62,7 +61,6 @@ const ( // ScheduledEventStatus the status of the scheduled event (https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-object-guild-scheduled-event-status) type ScheduledEventStatus int -//goland:noinspection GoUnusedConst const ( ScheduledEventStatusScheduled ScheduledEventStatus = iota + 1 ScheduledEventStatusActive @@ -73,7 +71,6 @@ const ( // ScheduledEventEntityType the type of the scheduled event (https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-object-guild-scheduled-event-entity-types) type ScheduledEventEntityType int -//goland:noinspection GoUnusedConst const ( ScheduledEventEntityTypeStageInstance ScheduledEventEntityType = iota + 1 ScheduledEventEntityTypeVoice @@ -82,5 +79,5 @@ const ( // EntityMetaData additional metadata for the scheduled event (https://discord.com/developers/docs/resources/guild-scheduled-event#guild-scheduled-event-object-guild-scheduled-event-entity-metadata) type EntityMetaData struct { - Location string + Location string `json:"location"` } diff --git a/discord/guild_template.go b/discord/guild_template.go index ad2feed6..8e8c7260 100644 --- a/discord/guild_template.go +++ b/discord/guild_template.go @@ -1,6 +1,6 @@ package discord -import "github.com/DisgoOrg/snowflake" +import "github.com/disgoorg/snowflake" // GuildTemplate is a template used for copying guilds https://discord.com/developers/docs/resources/guild-template type GuildTemplate struct { diff --git a/discord/icon.go b/discord/icon.go index 477372d9..68bfcd28 100644 --- a/discord/icon.go +++ b/discord/icon.go @@ -6,12 +6,11 @@ import ( "io" "io/ioutil" - "github.com/DisgoOrg/disgo/json" + "github.com/disgoorg/disgo/json" ) type IconType string -//goland:noinspection GoUnusedConst const ( IconTypeJPEG IconType = "image/jpeg" IconTypePNG IconType = "image/png" @@ -31,7 +30,6 @@ func (t IconType) GetHeader() string { var _ json.Marshaler = (*Icon)(nil) var _ fmt.Stringer = (*Icon)(nil) -//goland:noinspection GoUnusedExportedFunction func NewIcon(iconType IconType, reader io.Reader) (*Icon, error) { data, err := ioutil.ReadAll(reader) if err != nil { @@ -40,7 +38,6 @@ func NewIcon(iconType IconType, reader io.Reader) (*Icon, error) { return NewIconRaw(iconType, data), nil } -//goland:noinspection GoUnusedExportedFunction func NewIconRaw(iconType IconType, src []byte) *Icon { var data []byte base64.StdEncoding.Encode(data, src) diff --git a/discord/icon_test.go b/discord/icon_test.go index d0cded5c..35eb3b6d 100644 --- a/discord/icon_test.go +++ b/discord/icon_test.go @@ -3,7 +3,7 @@ package discord import ( "testing" - "github.com/DisgoOrg/disgo/json" + "github.com/disgoorg/disgo/json" "github.com/stretchr/testify/assert" ) diff --git a/discord/integration.go b/discord/integration.go index c4209b13..58a712eb 100644 --- a/discord/integration.go +++ b/discord/integration.go @@ -3,15 +3,14 @@ package discord import ( "fmt" - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" ) // IntegrationType the type of Integration type IntegrationType string // All IntegrationType(s) -//goland:noinspection GoUnusedConst const ( IntegrationTypeTwitch IntegrationType = "twitch" IntegrationTypeYouTube IntegrationType = "youtube" @@ -31,7 +30,7 @@ type IntegrationApplication struct { Icon string `json:"icon"` Description string `json:"description"` Summary string `json:"summary"` - Bot User `json:"bot"` + Client User `json:"bot"` } // Integration (https://discord.com/developers/docs/resources/guild#integration-object) diff --git a/discord/interaction.go b/discord/interaction.go index ff345855..814d62fd 100644 --- a/discord/interaction.go +++ b/discord/interaction.go @@ -3,8 +3,8 @@ package discord import ( "fmt" - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" ) // InteractionType is the type of Interaction @@ -19,25 +19,28 @@ const ( InteractionTypeModalSubmit ) -// Interaction is used for easier unmarshalling of different Interaction(s) -type Interaction interface { - Type() InteractionType - interaction() -} - -type BaseInteraction struct { +type rawInteraction struct { ID snowflake.Snowflake `json:"id"` + Type InteractionType `json:"type"` ApplicationID snowflake.Snowflake `json:"application_id"` Token string `json:"token"` Version int `json:"version"` GuildID *snowflake.Snowflake `json:"guild_id,omitempty"` - ChannelID snowflake.Snowflake `json:"channel_id"` - Locale Locale `json:"locale"` + ChannelID snowflake.Snowflake `json:"channel_id,omitempty"` + Locale Locale `json:"locale,omitempty"` GuildLocale *Locale `json:"guild_locale,omitempty"` - Member *Member `json:"member,omitempty"` + Member *ResolvedMember `json:"member,omitempty"` User *User `json:"user,omitempty"` } +// Interaction is used for easier unmarshalling of different Interaction(s) +type Interaction interface { + Type() InteractionType + BaseInteraction + + interaction() +} + type UnmarshalInteraction struct { Interaction } @@ -52,431 +55,58 @@ func (i *UnmarshalInteraction) UnmarshalJSON(data []byte) error { } var ( - interaction Interaction - err error + vInteraction Interaction + err error ) switch iType.Type { case InteractionTypePing: v := PingInteraction{} err = json.Unmarshal(data, &v) - interaction = v + vInteraction = v case InteractionTypeApplicationCommand: v := ApplicationCommandInteraction{} err = json.Unmarshal(data, &v) - interaction = v + vInteraction = v case InteractionTypeComponent: v := ComponentInteraction{} err = json.Unmarshal(data, &v) - interaction = v + vInteraction = v case InteractionTypeAutocomplete: v := AutocompleteInteraction{} err = json.Unmarshal(data, &v) - interaction = v + vInteraction = v case InteractionTypeModalSubmit: v := ModalSubmitInteraction{} err = json.Unmarshal(data, &v) - interaction = v - - default: - return fmt.Errorf("unkown interaction with type %d received", iType.Type) - } - if err != nil { - return err - } - - i.Interaction = interaction - return nil -} - -var _ Interaction = (*PingInteraction)(nil) - -type PingInteraction struct { - ID snowflake.Snowflake `json:"id"` - ApplicationID snowflake.Snowflake `json:"application_id"` - Token string `json:"token"` - Version int `json:"version"` -} - -func (PingInteraction) interaction() {} -func (PingInteraction) Type() InteractionType { - return InteractionTypePing -} - -var ( - _ Interaction = (*ApplicationCommandInteraction)(nil) -) - -type ApplicationCommandInteraction struct { - BaseInteraction - Data ApplicationCommandInteractionData `json:"data"` -} - -func (ApplicationCommandInteraction) interaction() {} -func (ApplicationCommandInteraction) Type() InteractionType { - return InteractionTypeApplicationCommand -} - -func (i *ApplicationCommandInteraction) UnmarshalJSON(data []byte) error { - type applicationCommandInteraction ApplicationCommandInteraction - var interaction struct { - Data json.RawMessage `json:"data"` - applicationCommandInteraction - } - - if err := json.Unmarshal(data, &interaction); err != nil { - return err - } - var cType struct { - Type ApplicationCommandType `json:"type"` - } - if err := json.Unmarshal(interaction.Data, &cType); err != nil { - return err - } - - var ( - interactionData ApplicationCommandInteractionData - err error - ) - - switch cType.Type { - case ApplicationCommandTypeSlash: - v := SlashCommandInteractionData{} - err = json.Unmarshal(interaction.Data, &v) - interactionData = v - - case ApplicationCommandTypeUser: - v := UserCommandInteractionData{} - err = json.Unmarshal(interaction.Data, &v) - interactionData = v - - case ApplicationCommandTypeMessage: - v := MessageCommandInteractionData{} - err = json.Unmarshal(interaction.Data, &v) - interactionData = v + vInteraction = v default: - return fmt.Errorf("unkown application interaction data with type %d received", cType.Type) + return fmt.Errorf("unkown rawInteraction with type %d received", iType.Type) } if err != nil { return err } - *i = ApplicationCommandInteraction(interaction.applicationCommandInteraction) - - i.Data = interactionData + i.Interaction = vInteraction return nil } -type ApplicationCommandInteractionData interface { - applicationCommandInteractionData() - Type() ApplicationCommandType - ID() snowflake.Snowflake - Name() string -} - -type SlashCommandInteractionData struct { - CommandID snowflake.Snowflake `json:"id"` - CommandName string `json:"name"` - Resolved SlashCommandResolved `json:"resolved"` - Options []SlashCommandOption `json:"options"` -} - -func (SlashCommandInteractionData) applicationCommandInteractionData() {} -func (SlashCommandInteractionData) Type() ApplicationCommandType { - return ApplicationCommandTypeSlash -} -func (d SlashCommandInteractionData) ID() snowflake.Snowflake { - return d.CommandID -} -func (d SlashCommandInteractionData) Name() string { - return d.CommandName -} - -func (d *SlashCommandInteractionData) UnmarshalJSON(data []byte) error { - type slashCommandInteractionData SlashCommandInteractionData - var iData struct { - Options []UnmarshalSlashCommandOption `json:"options"` - slashCommandInteractionData +type ( + ResolvedMember struct { + Member + Permissions Permissions `json:"permissions,omitempty"` } - - if err := json.Unmarshal(data, &iData); err != nil { - return err + ResolvedChannel struct { + ID snowflake.Snowflake `json:"id"` + Name string `json:"name"` + Type ChannelType `json:"type"` + Permissions Permissions `json:"permissions"` + ThreadMetadata ThreadMetadata `json:"thread_metadata"` + ParentID snowflake.Snowflake `json:"parent_id"` } - - *d = SlashCommandInteractionData(iData.slashCommandInteractionData) - - if len(iData.Options) > 0 { - d.Options = make([]SlashCommandOption, len(iData.Options)) - for i := range iData.Options { - d.Options[i] = iData.Options[i].SlashCommandOption - } - } - - return nil -} - -type SlashCommandResolved struct { - Users map[snowflake.Snowflake]User `json:"users,omitempty"` - Members map[snowflake.Snowflake]Member `json:"members,omitempty"` - Roles map[snowflake.Snowflake]Role `json:"roles,omitempty"` - Channels map[snowflake.Snowflake]Channel `json:"channels,omitempty"` -} - -var ( - _ ApplicationCommandInteractionData = (*UserCommandInteractionData)(nil) -) - -type UserCommandInteractionData struct { - CommandID snowflake.Snowflake `json:"id"` - CommandName string `json:"name"` - Resolved UserCommandResolved `json:"resolved"` - TargetID snowflake.Snowflake `json:"target_id"` -} - -func (UserCommandInteractionData) applicationCommandInteractionData() {} -func (UserCommandInteractionData) Type() ApplicationCommandType { - return ApplicationCommandTypeUser -} -func (d UserCommandInteractionData) ID() snowflake.Snowflake { - return d.CommandID -} -func (d UserCommandInteractionData) Name() string { - return d.CommandName -} - -type UserCommandResolved struct { - Users map[snowflake.Snowflake]User `json:"users,omitempty"` - Members map[snowflake.Snowflake]Member `json:"members,omitempty"` -} - -var ( - _ ApplicationCommandInteractionData = (*MessageCommandInteractionData)(nil) ) - -type MessageCommandInteractionData struct { - CommandID snowflake.Snowflake `json:"id"` - CommandName string `json:"name"` - Resolved MessageCommandResolved `json:"resolved"` - TargetID snowflake.Snowflake `json:"target_id"` -} - -func (MessageCommandInteractionData) applicationCommandInteractionData() {} -func (MessageCommandInteractionData) Type() ApplicationCommandType { - return ApplicationCommandTypeMessage -} -func (d MessageCommandInteractionData) ID() snowflake.Snowflake { - return d.CommandID -} -func (d MessageCommandInteractionData) Name() string { - return d.CommandName -} - -type MessageCommandResolved struct { - Messages map[snowflake.Snowflake]Message `json:"messages,omitempty"` -} - -var ( - _ Interaction = (*ComponentInteraction)(nil) -) - -type ComponentInteraction struct { - BaseInteraction - Data ComponentInteractionData `json:"data"` - Message Message `json:"message"` -} - -func (ComponentInteraction) interaction() {} -func (ComponentInteraction) Type() InteractionType { - return InteractionTypeComponent -} - -func (i *ComponentInteraction) UnmarshalJSON(data []byte) error { - type componentInteraction ComponentInteraction - var interaction struct { - Data json.RawMessage `json:"data"` - componentInteraction - } - - if err := json.Unmarshal(data, &interaction); err != nil { - return err - } - - var cType struct { - Type ComponentType `json:"component_type"` - } - - if err := json.Unmarshal(interaction.Data, &cType); err != nil { - return err - } - - var ( - interactionData ComponentInteractionData - err error - ) - switch cType.Type { - case ComponentTypeButton: - v := ButtonInteractionData{} - err = json.Unmarshal(interaction.Data, &v) - interactionData = v - - case ComponentTypeSelectMenu: - v := SelectMenuInteractionData{} - err = json.Unmarshal(interaction.Data, &v) - interactionData = v - - default: - return fmt.Errorf("unkown component interaction data with type %d received", cType.Type) - } - if err != nil { - return err - } - - *i = ComponentInteraction(interaction.componentInteraction) - - i.Data = interactionData - return nil -} - -type ComponentInteractionData interface { - componentInteractionData() - Type() ComponentType - ID() CustomID -} - -type ButtonInteractionData struct { - CustomID CustomID `json:"custom_id"` -} - -func (ButtonInteractionData) componentInteractionData() {} -func (ButtonInteractionData) Type() ComponentType { - return ComponentTypeButton -} -func (d ButtonInteractionData) ID() CustomID { - return d.CustomID -} - -var ( - _ ComponentInteractionData = (*SelectMenuInteractionData)(nil) -) - -type SelectMenuInteractionData struct { - CustomID CustomID `json:"custom_id"` - Values []string `json:"values"` -} - -func (SelectMenuInteractionData) componentInteractionData() {} -func (SelectMenuInteractionData) Type() ComponentType { - return ComponentTypeSelectMenu -} -func (d SelectMenuInteractionData) ID() CustomID { - return d.CustomID -} - -var ( - _ Interaction = (*AutocompleteInteraction)(nil) -) - -type AutocompleteInteraction struct { - BaseInteraction - Data AutocompleteInteractionData `json:"data"` -} - -func (AutocompleteInteraction) interaction() {} -func (AutocompleteInteraction) Type() InteractionType { - return InteractionTypeAutocomplete -} - -type AutocompleteInteractionData struct { - CommandID snowflake.Snowflake `json:"id"` - CommandName string `json:"name"` - Options []AutocompleteOption `json:"options"` -} - -func (d *AutocompleteInteractionData) UnmarshalJSON(data []byte) error { - type autocompleteInteractionData AutocompleteInteractionData - var iData struct { - Options []UnmarshalAutocompleteOption `json:"options"` - autocompleteInteractionData - } - - if err := json.Unmarshal(data, &iData); err != nil { - return err - } - - *d = AutocompleteInteractionData(iData.autocompleteInteractionData) - if len(iData.Options) > 0 { - d.Options = make([]AutocompleteOption, len(iData.Options)) - for i := range iData.Options { - d.Options[i] = iData.Options[i].AutocompleteOption - } - } - - return nil -} - -var ( - _ Interaction = (*ModalSubmitInteraction)(nil) -) - -type ModalSubmitInteraction struct { - BaseInteraction - Data ModalSubmitInteractionData `json:"data"` -} - -func (ModalSubmitInteraction) interaction() {} - -func (ModalSubmitInteraction) Type() InteractionType { - return InteractionTypeModalSubmit -} - -type ModalSubmitInteractionData struct { - CustomID CustomID `json:"custom_id"` - Components []ContainerComponent `json:"components"` -} - -func (d *ModalSubmitInteractionData) UnmarshalJSON(data []byte) error { - type modalSubmitInteractionData ModalSubmitInteractionData - var iData struct { - Components []UnmarshalComponent `json:"components"` - modalSubmitInteractionData - } - - if err := json.Unmarshal(data, &iData); err != nil { - return err - } - - *d = ModalSubmitInteractionData(iData.modalSubmitInteractionData) - - if len(iData.Components) > 0 { - d.Components = make([]ContainerComponent, len(iData.Components)) - for i := range iData.Components { - d.Components[i] = iData.Components[i].Component.(ContainerComponent) - } - } - - return nil -} - -// to consider using them in Resolved -/* -type ResolvedMember struct { - GuildID snowflake.Snowflake `json:"guild_id"` - User User `json:"user"` - Nick *string `json:"nick"` - RoleIDs []snowflake.Snowflake `json:"roles,omitempty"` - JoinedAt Time `json:"joined_at"` - PremiumSince *Time `json:"premium_since,omitempty"` - Permissions Permissions `json:"permissions,omitempty"` -} - -type ResolvedChannel struct { - CommandID snowflake.Snowflake `json:"id"` - CommandName string `json:"name"` - InteractionType ChannelType `json:"type"` - Permissions Permissions `json:"permissions"` -}*/ diff --git a/discord/interaction_application_command.go b/discord/interaction_application_command.go new file mode 100644 index 00000000..337033b7 --- /dev/null +++ b/discord/interaction_application_command.go @@ -0,0 +1,652 @@ +package discord + +import ( + "fmt" + + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" +) + +var ( + _ Interaction = (*ApplicationCommandInteraction)(nil) +) + +type ApplicationCommandInteraction struct { + BaseInteraction + Data ApplicationCommandInteractionData `json:"data"` +} + +func (i *ApplicationCommandInteraction) UnmarshalJSON(data []byte) error { + var baseInteraction baseInteractionImpl + if err := json.Unmarshal(data, &baseInteraction); err != nil { + return err + } + + var interaction struct { + Data json.RawMessage `json:"data"` + } + if err := json.Unmarshal(data, &interaction); err != nil { + return err + } + var cType struct { + Type ApplicationCommandType `json:"type"` + } + if err := json.Unmarshal(interaction.Data, &cType); err != nil { + return err + } + + var ( + interactionData ApplicationCommandInteractionData + err error + ) + + switch cType.Type { + case ApplicationCommandTypeSlash: + v := SlashCommandInteractionData{} + err = json.Unmarshal(interaction.Data, &v) + interactionData = v + + case ApplicationCommandTypeUser: + v := UserCommandInteractionData{} + err = json.Unmarshal(interaction.Data, &v) + interactionData = v + + case ApplicationCommandTypeMessage: + v := MessageCommandInteractionData{} + err = json.Unmarshal(interaction.Data, &v) + interactionData = v + + default: + return fmt.Errorf("unkown application rawInteraction data with type %d received", cType.Type) + } + if err != nil { + return err + } + + i.BaseInteraction = baseInteraction + + i.Data = interactionData + return nil +} + +func (ApplicationCommandInteraction) Type() InteractionType { + return InteractionTypeApplicationCommand +} + +func (i ApplicationCommandInteraction) SlashCommandInteractionData() SlashCommandInteractionData { + return i.Data.(SlashCommandInteractionData) +} + +func (i ApplicationCommandInteraction) UserCommandInteractionData() UserCommandInteractionData { + return i.Data.(UserCommandInteractionData) +} + +func (i ApplicationCommandInteraction) MessageCommandInteractionData() MessageCommandInteractionData { + return i.Data.(MessageCommandInteractionData) +} + +func (ApplicationCommandInteraction) interaction() {} + +type ApplicationCommandInteractionData interface { + Type() ApplicationCommandType + CommandID() snowflake.Snowflake + CommandName() string + + applicationCommandInteractionData() +} + +type rawSlashCommandInteractionData struct { + ID snowflake.Snowflake `json:"id"` + Name string `json:"name"` + Resolved SlashCommandResolved `json:"resolved"` + Options []SlashCommandOption `json:"options"` +} + +func (d *rawSlashCommandInteractionData) UnmarshalJSON(data []byte) error { + type alias rawSlashCommandInteractionData + var v struct { + Options []UnmarshalSlashCommandOption `json:"options"` + alias + } + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + *d = rawSlashCommandInteractionData(v.alias) + d.Options = make([]SlashCommandOption, len(v.Options)) + for i := range v.Options { + d.Options[i] = v.Options[i].SlashCommandOption + } + + return nil +} + +type SlashCommandInteractionData struct { + id snowflake.Snowflake + name string + SubCommandName *string + SubCommandGroupName *string + Resolved SlashCommandResolved + Options map[string]SlashCommandOption +} + +func (d *SlashCommandInteractionData) UnmarshalJSON(data []byte) error { + var iData rawSlashCommandInteractionData + + if err := json.Unmarshal(data, &iData); err != nil { + return err + } + d.id = iData.ID + d.name = iData.Name + d.Resolved = iData.Resolved + + d.Options = make(map[string]SlashCommandOption) + if len(iData.Options) > 0 { + flattenedOptions := iData.Options + + unmarshalOption := flattenedOptions[0] + if option, ok := unmarshalOption.(SlashCommandOptionSubCommandGroup); ok { + d.SubCommandGroupName = &option.OptionName + flattenedOptions = make([]SlashCommandOption, len(option.Options)) + for ii := range option.Options { + flattenedOptions[ii] = option.Options[ii] + } + unmarshalOption = option.Options[0] + } + if option, ok := unmarshalOption.(SlashCommandOptionSubCommand); ok { + d.SubCommandName = &option.OptionName + flattenedOptions = option.Options + } + + for _, option := range flattenedOptions { + d.Options[option.Name()] = option + } + } + return nil +} + +func (d SlashCommandInteractionData) MarshalJSON() ([]byte, error) { + options := make([]SlashCommandOption, len(d.Options)) + i := 0 + for _, option := range d.Options { + options[i] = option + i++ + } + + if d.SubCommandName != nil { + options = []SlashCommandOption{ + SlashCommandOptionSubCommand{ + OptionName: *d.SubCommandName, + Options: options, + }, + } + } + if d.SubCommandGroupName != nil { + subCommandOptions := make([]SlashCommandOptionSubCommand, len(options)) + for ii := range options { + subCommandOptions[ii] = options[ii].(SlashCommandOptionSubCommand) + } + options = []SlashCommandOption{ + SlashCommandOptionSubCommandGroup{ + OptionName: *d.SubCommandGroupName, + Options: subCommandOptions, + }, + } + } + + return json.Marshal(rawSlashCommandInteractionData{ + ID: d.id, + Name: d.name, + Resolved: d.Resolved, + Options: options, + }) +} + +func (SlashCommandInteractionData) Type() ApplicationCommandType { + return ApplicationCommandTypeSlash +} + +func (d SlashCommandInteractionData) CommandID() snowflake.Snowflake { + return d.id +} + +func (d SlashCommandInteractionData) CommandName() string { + return d.name +} + +func (d SlashCommandInteractionData) Option(name string) (SlashCommandOption, bool) { + option, ok := d.Options[name] + return option, ok +} + +func (d SlashCommandInteractionData) StringOption(name string) (SlashCommandOptionString, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(SlashCommandOptionString) + return opt, ok + } + return SlashCommandOptionString{}, false +} + +func (d SlashCommandInteractionData) OptString(name string) (string, bool) { + if option, ok := d.StringOption(name); ok { + return option.Value, true + } + return "", false +} + +func (d SlashCommandInteractionData) String(name string) string { + if option, ok := d.OptString(name); ok { + return option + } + return "" +} + +func (d SlashCommandInteractionData) IntOption(name string) (SlashCommandOptionInt, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(SlashCommandOptionInt) + return opt, ok + } + return SlashCommandOptionInt{}, false +} + +func (d SlashCommandInteractionData) OptInt(name string) (int, bool) { + if option, ok := d.IntOption(name); ok { + return option.Value, true + } + return 0, false +} + +func (d SlashCommandInteractionData) Int(name string) int { + if option, ok := d.OptInt(name); ok { + return option + } + return 0 +} + +func (d SlashCommandInteractionData) BoolOption(name string) (SlashCommandOptionBool, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(SlashCommandOptionBool) + return opt, ok + } + return SlashCommandOptionBool{}, false +} + +func (d SlashCommandInteractionData) OptBool(name string) (bool, bool) { + if option, ok := d.BoolOption(name); ok { + return option.Value, true + } + return false, false +} + +func (d SlashCommandInteractionData) Bool(name string) bool { + if option, ok := d.OptBool(name); ok { + return option + } + return false +} + +func (d SlashCommandInteractionData) UserOption(name string) (SlashCommandOptionUser, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(SlashCommandOptionUser) + return opt, ok + } + return SlashCommandOptionUser{}, false +} + +func (d SlashCommandInteractionData) OptUser(name string) (User, bool) { + if option, ok := d.Option(name); ok { + var ( + userID snowflake.Snowflake + userIDOk bool + ) + switch opt := option.(type) { + case SlashCommandOptionUser: + opt, ok := option.(SlashCommandOptionUser) + userID = opt.Value + userIDOk = ok + case SlashCommandOptionMentionable: + opt, ok := option.(SlashCommandOptionMentionable) + userID = opt.Value + userIDOk = ok + } + if userIDOk { + user, userOk := d.Resolved.Users[userID] + return user, userOk + } + } + return User{}, false +} + +func (d SlashCommandInteractionData) User(name string) User { + if user, ok := d.OptUser(name); ok { + return user + } + return User{} +} + +func (d SlashCommandInteractionData) OptMember(name string) (ResolvedMember, bool) { + if option, ok := d.Option(name); ok { + var ( + userID snowflake.Snowflake + userIDOk bool + ) + switch opt := option.(type) { + case SlashCommandOptionUser: + opt, ok := option.(SlashCommandOptionUser) + userID = opt.Value + userIDOk = ok + case SlashCommandOptionMentionable: + opt, ok := option.(SlashCommandOptionMentionable) + userID = opt.Value + userIDOk = ok + } + if userIDOk { + member, memberOk := d.Resolved.Members[userID] + return member, memberOk + } + } + return ResolvedMember{}, false +} + +func (d SlashCommandInteractionData) Member(name string) ResolvedMember { + if member, ok := d.OptMember(name); ok { + return member + } + return ResolvedMember{} +} + +func (d SlashCommandInteractionData) ChannelOption(name string) (SlashCommandOptionChannel, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(SlashCommandOptionChannel) + return opt, ok + } + return SlashCommandOptionChannel{}, false +} + +func (d SlashCommandInteractionData) OptChannel(name string) (ResolvedChannel, bool) { + if option, ok := d.ChannelOption(name); ok { + channel, ok := d.Resolved.Channels[option.Value] + return channel, ok + } + return ResolvedChannel{}, false +} + +func (d SlashCommandInteractionData) Channel(name string) ResolvedChannel { + if channel, ok := d.OptChannel(name); ok { + return channel + } + return ResolvedChannel{} +} + +func (d SlashCommandInteractionData) RoleOption(name string) (SlashCommandOptionRole, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(SlashCommandOptionRole) + return opt, ok + } + return SlashCommandOptionRole{}, false +} + +func (d SlashCommandInteractionData) OptRole(name string) (Role, bool) { + if option, ok := d.Option(name); ok { + var ( + roleID snowflake.Snowflake + roleIDOk bool + ) + switch opt := option.(type) { + case SlashCommandOptionRole: + opt, ok := option.(SlashCommandOptionRole) + roleID = opt.Value + roleIDOk = ok + case SlashCommandOptionMentionable: + opt, ok := option.(SlashCommandOptionMentionable) + roleID = opt.Value + roleIDOk = ok + } + if roleIDOk { + role, roleOk := d.Resolved.Roles[roleID] + return role, roleOk + } + } + return Role{}, false +} + +func (d SlashCommandInteractionData) Role(name string) Role { + if role, ok := d.OptRole(name); ok { + return role + } + return Role{} +} + +func (d SlashCommandInteractionData) MentionableOption(name string) (SlashCommandOptionMentionable, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(SlashCommandOptionMentionable) + return opt, ok + } + return SlashCommandOptionMentionable{}, false +} + +func (d SlashCommandInteractionData) OptSnowflake(name string) (snowflake.Snowflake, bool) { + if option, ok := d.Option(name); ok { + switch opt := option.(type) { + case SlashCommandOptionChannel: + return opt.Value, true + case SlashCommandOptionRole: + return opt.Value, true + case SlashCommandOptionUser: + return opt.Value, true + case SlashCommandOptionMentionable: + return opt.Value, true + } + } + return "", false +} + +func (d SlashCommandInteractionData) Snowflake(name string) snowflake.Snowflake { + if id, ok := d.OptSnowflake(name); ok { + return id + } + return "" +} + +func (d SlashCommandInteractionData) FloatOption(name string) (SlashCommandOptionFloat, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(SlashCommandOptionFloat) + return opt, ok + } + return SlashCommandOptionFloat{}, false +} + +func (d SlashCommandInteractionData) OptFloat(name string) (float64, bool) { + if option, ok := d.FloatOption(name); ok { + return option.Value, true + } + return 0, false +} + +func (d SlashCommandInteractionData) Float(name string) float64 { + if option, ok := d.FloatOption(name); ok { + return option.Value + } + return 0 +} + +func (d SlashCommandInteractionData) All() []SlashCommandOption { + options := make([]SlashCommandOption, len(d.Options)) + i := 0 + for _, option := range d.Options { + options[i] = option + i++ + } + return options +} + +func (d SlashCommandInteractionData) GetByType(optionType ApplicationCommandOptionType) []SlashCommandOption { + return d.FindAll(func(option SlashCommandOption) bool { + return option.Type() == optionType + }) +} + +func (d SlashCommandInteractionData) Find(optionFindFunc func(option SlashCommandOption) bool) (SlashCommandOption, bool) { + for _, option := range d.Options { + if optionFindFunc(option) { + return option, true + } + } + return nil, false +} + +func (d SlashCommandInteractionData) FindAll(optionFindFunc func(option SlashCommandOption) bool) []SlashCommandOption { + var options []SlashCommandOption + for _, option := range d.Options { + if optionFindFunc(option) { + options = append(options, option) + } + } + return options +} + +func (SlashCommandInteractionData) applicationCommandInteractionData() {} + +type SlashCommandResolved struct { + Users map[snowflake.Snowflake]User `json:"users,omitempty"` + Members map[snowflake.Snowflake]ResolvedMember `json:"members,omitempty"` + Roles map[snowflake.Snowflake]Role `json:"roles,omitempty"` + Channels map[snowflake.Snowflake]ResolvedChannel `json:"channels,omitempty"` +} + +type ContextCommandInteractionData interface { + ApplicationCommandInteractionData + TargetID() snowflake.Snowflake + + contextCommandInteractionData() +} + +var ( + _ ApplicationCommandInteractionData = (*UserCommandInteractionData)(nil) + _ ContextCommandInteractionData = (*UserCommandInteractionData)(nil) +) + +type rawUserCommandInteractionData struct { + ID snowflake.Snowflake `json:"id"` + Name string `json:"name"` + Resolved UserCommandResolved `json:"resolved"` + TargetID snowflake.Snowflake `json:"target_id"` +} + +type UserCommandInteractionData struct { + id snowflake.Snowflake + name string + Resolved UserCommandResolved `json:"resolved"` + targetID snowflake.Snowflake +} + +func (d *UserCommandInteractionData) UnmarshalJSON(data []byte) error { + var iData rawUserCommandInteractionData + if err := json.Unmarshal(data, &iData); err != nil { + return err + } + d.id = iData.ID + d.name = iData.Name + d.Resolved = iData.Resolved + d.targetID = iData.TargetID + return nil +} + +func (d *UserCommandInteractionData) MarshalJSON() ([]byte, error) { + return json.Marshal(rawUserCommandInteractionData{ + ID: d.id, + Name: d.name, + Resolved: d.Resolved, + TargetID: d.targetID, + }) +} + +func (UserCommandInteractionData) Type() ApplicationCommandType { + return ApplicationCommandTypeUser +} +func (d UserCommandInteractionData) CommandID() snowflake.Snowflake { + return d.id +} +func (d UserCommandInteractionData) CommandName() string { + return d.name +} +func (d UserCommandInteractionData) TargetID() snowflake.Snowflake { + return d.targetID +} +func (d UserCommandInteractionData) TargetUser() User { + return d.Resolved.Users[d.targetID] +} +func (d UserCommandInteractionData) TargetMember() ResolvedMember { + return d.Resolved.Members[d.targetID] +} + +func (UserCommandInteractionData) applicationCommandInteractionData() {} +func (UserCommandInteractionData) contextCommandInteractionData() {} + +type UserCommandResolved struct { + Users map[snowflake.Snowflake]User `json:"users,omitempty"` + Members map[snowflake.Snowflake]ResolvedMember `json:"members,omitempty"` +} + +var ( + _ ApplicationCommandInteractionData = (*MessageCommandInteractionData)(nil) + _ ContextCommandInteractionData = (*MessageCommandInteractionData)(nil) +) + +type rawMessageCommandInteractionData struct { + ID snowflake.Snowflake `json:"id"` + Name string `json:"name"` + Resolved MessageCommandResolved `json:"resolved"` + TargetID snowflake.Snowflake `json:"target_id"` +} + +type MessageCommandInteractionData struct { + id snowflake.Snowflake + name string + Resolved MessageCommandResolved `json:"resolved"` + targetID snowflake.Snowflake +} + +func (d *MessageCommandInteractionData) UnmarshalJSON(data []byte) error { + var iData rawMessageCommandInteractionData + if err := json.Unmarshal(data, &iData); err != nil { + return err + } + d.id = iData.ID + d.name = iData.Name + d.Resolved = iData.Resolved + d.targetID = iData.TargetID + return nil +} + +func (d *MessageCommandInteractionData) MarshalJSON() ([]byte, error) { + return json.Marshal(rawMessageCommandInteractionData{ + ID: d.id, + Name: d.name, + Resolved: d.Resolved, + TargetID: d.targetID, + }) +} + +func (MessageCommandInteractionData) Type() ApplicationCommandType { + return ApplicationCommandTypeMessage +} +func (d MessageCommandInteractionData) CommandID() snowflake.Snowflake { + return d.id +} +func (d MessageCommandInteractionData) CommandName() string { + return d.name +} +func (d MessageCommandInteractionData) TargetID() snowflake.Snowflake { + return d.targetID +} +func (d MessageCommandInteractionData) TargetMessage() Message { + return d.Resolved.Messages[d.targetID] +} + +func (MessageCommandInteractionData) applicationCommandInteractionData() {} +func (MessageCommandInteractionData) contextCommandInteractionData() {} + +type MessageCommandResolved struct { + Messages map[snowflake.Snowflake]Message `json:"messages,omitempty"` +} diff --git a/discord/interaction_autocomplete.go b/discord/interaction_autocomplete.go new file mode 100644 index 00000000..5cb4b7e5 --- /dev/null +++ b/discord/interaction_autocomplete.go @@ -0,0 +1,326 @@ +package discord + +import ( + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" +) + +var ( + _ Interaction = (*AutocompleteInteraction)(nil) +) + +type AutocompleteInteraction struct { + BaseInteraction + Data AutocompleteInteractionData `json:"data"` +} + +func (i *AutocompleteInteraction) UnmarshalJSON(data []byte) error { + var baseInteraction baseInteractionImpl + if err := json.Unmarshal(data, &baseInteraction); err != nil { + return err + } + + var interaction struct { + Data AutocompleteInteractionData `json:"data"` + } + if err := json.Unmarshal(data, &interaction); err != nil { + return err + } + + i.BaseInteraction = baseInteraction + + i.Data = interaction.Data + return nil +} + +func (AutocompleteInteraction) Type() InteractionType { + return InteractionTypeAutocomplete +} + +func (AutocompleteInteraction) interaction() {} + +type rawAutocompleteInteractionData struct { + ID snowflake.Snowflake `json:"id"` + Name string `json:"name"` + Options []AutocompleteOption `json:"options"` +} + +func (d *rawAutocompleteInteractionData) UnmarshalJSON(data []byte) error { + type alias rawAutocompleteInteractionData + var v struct { + Options []UnmarshalAutocompleteOption `json:"options"` + alias + } + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + *d = rawAutocompleteInteractionData(v.alias) + d.Options = make([]AutocompleteOption, len(v.Options)) + for i := range v.Options { + d.Options[i] = v.Options[i].AutocompleteOption + } + + return nil +} + +type AutocompleteInteractionData struct { + CommandID snowflake.Snowflake + CommandName string + SubCommandName *string + SubCommandGroupName *string + Options map[string]AutocompleteOption +} + +func (d *AutocompleteInteractionData) UnmarshalJSON(data []byte) error { + var iData rawAutocompleteInteractionData + + if err := json.Unmarshal(data, &iData); err != nil { + return err + } + d.CommandID = iData.ID + d.CommandName = iData.Name + + d.Options = make(map[string]AutocompleteOption) + if len(iData.Options) > 0 { + flattenedOptions := iData.Options + + unmarshalOption := flattenedOptions[0] + if option, ok := unmarshalOption.(AutocompleteOptionSubCommandGroup); ok { + d.SubCommandGroupName = &option.OptionName + flattenedOptions = make([]AutocompleteOption, len(option.Options)) + for ii := range option.Options { + flattenedOptions[ii] = option.Options[ii] + } + unmarshalOption = option.Options[0] + } + if option, ok := unmarshalOption.(AutocompleteOptionSubCommand); ok { + d.SubCommandName = &option.OptionName + flattenedOptions = option.Options + } + + for _, option := range flattenedOptions { + d.Options[option.Name()] = option + } + } + return nil +} + +func (d AutocompleteInteractionData) MarshalJSON() ([]byte, error) { + options := make([]AutocompleteOption, len(d.Options)) + i := 0 + for _, option := range d.Options { + options[i] = option + i++ + } + + if d.SubCommandName != nil { + options = []AutocompleteOption{ + AutocompleteOptionSubCommand{ + OptionName: *d.SubCommandName, + Options: options, + }, + } + } + if d.SubCommandGroupName != nil { + subCommandOptions := make([]AutocompleteOptionSubCommand, len(options)) + for ii := range options { + subCommandOptions[ii] = options[ii].(AutocompleteOptionSubCommand) + } + options = []AutocompleteOption{ + AutocompleteOptionSubCommandGroup{ + OptionName: *d.SubCommandGroupName, + Options: subCommandOptions, + }, + } + } + + return json.Marshal(rawAutocompleteInteractionData{ + ID: d.CommandID, + Name: d.CommandName, + Options: options, + }) +} + +func (d AutocompleteInteractionData) Option(name string) (AutocompleteOption, bool) { + option, ok := d.Options[name] + return option, ok +} + +func (d AutocompleteInteractionData) StringOption(name string) (AutocompleteOptionString, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(AutocompleteOptionString) + return opt, ok + } + return AutocompleteOptionString{}, false +} + +func (d AutocompleteInteractionData) OptString(name string) (string, bool) { + if option, ok := d.StringOption(name); ok { + return option.Value, true + } + return "", false +} + +func (d AutocompleteInteractionData) String(name string) string { + if option, ok := d.OptString(name); ok { + return option + } + return "" +} + +func (d AutocompleteInteractionData) IntOption(name string) (AutocompleteOptionInt, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(AutocompleteOptionInt) + return opt, ok + } + return AutocompleteOptionInt{}, false +} + +func (d AutocompleteInteractionData) OptInt(name string) (int, bool) { + if option, ok := d.IntOption(name); ok { + return option.Value, true + } + return 0, false +} + +func (d AutocompleteInteractionData) Int(name string) int { + if option, ok := d.OptInt(name); ok { + return option + } + return 0 +} + +func (d AutocompleteInteractionData) BoolOption(name string) (AutocompleteOptionBool, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(AutocompleteOptionBool) + return opt, ok + } + return AutocompleteOptionBool{}, false +} + +func (d AutocompleteInteractionData) OptBool(name string) (bool, bool) { + if option, ok := d.BoolOption(name); ok { + return option.Value, true + } + return false, false +} + +func (d AutocompleteInteractionData) Bool(name string) bool { + if option, ok := d.OptBool(name); ok { + return option + } + return false +} + +func (d AutocompleteInteractionData) UserOption(name string) (AutocompleteOptionUser, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(AutocompleteOptionUser) + return opt, ok + } + return AutocompleteOptionUser{}, false +} + +func (d AutocompleteInteractionData) ChannelOption(name string) (AutocompleteOptionChannel, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(AutocompleteOptionChannel) + return opt, ok + } + return AutocompleteOptionChannel{}, false +} + +func (d AutocompleteInteractionData) RoleOption(name string) (AutocompleteOptionRole, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(AutocompleteOptionRole) + return opt, ok + } + return AutocompleteOptionRole{}, false +} + +func (d AutocompleteInteractionData) MentionableOption(name string) (AutocompleteOptionMentionable, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(AutocompleteOptionMentionable) + return opt, ok + } + return AutocompleteOptionMentionable{}, false +} + +func (d AutocompleteInteractionData) OptSnowflake(name string) (snowflake.Snowflake, bool) { + if option, ok := d.Option(name); ok { + switch opt := option.(type) { + case AutocompleteOptionChannel: + return opt.Value, true + case AutocompleteOptionRole: + return opt.Value, true + case AutocompleteOptionUser: + return opt.Value, true + case AutocompleteOptionMentionable: + return opt.Value, true + } + } + return "", false +} + +func (d AutocompleteInteractionData) Snowflake(name string) snowflake.Snowflake { + if id, ok := d.OptSnowflake(name); ok { + return id + } + return "" +} + +func (d AutocompleteInteractionData) FloatOption(name string) (AutocompleteOptionFloat, bool) { + if option, ok := d.Option(name); ok { + opt, ok := option.(AutocompleteOptionFloat) + return opt, ok + } + return AutocompleteOptionFloat{}, false +} + +func (d AutocompleteInteractionData) OptFloat(name string) (float64, bool) { + if option, ok := d.FloatOption(name); ok { + return option.Value, true + } + return 0, false +} + +func (d AutocompleteInteractionData) Float(name string) float64 { + if option, ok := d.FloatOption(name); ok { + return option.Value + } + return 0 +} + +func (d AutocompleteInteractionData) All() []AutocompleteOption { + options := make([]AutocompleteOption, len(d.Options)) + i := 0 + for _, option := range d.Options { + options[i] = option + i++ + } + return options +} + +func (d AutocompleteInteractionData) GetByType(optionType ApplicationCommandOptionType) []AutocompleteOption { + return d.FindAll(func(option AutocompleteOption) bool { + return option.Type() == optionType + }) +} + +func (d AutocompleteInteractionData) Find(optionFindFunc func(option AutocompleteOption) bool) (AutocompleteOption, bool) { + for _, option := range d.Options { + if optionFindFunc(option) { + return option, true + } + } + return nil, false +} + +func (d AutocompleteInteractionData) FindAll(optionFindFunc func(option AutocompleteOption) bool) []AutocompleteOption { + var options []AutocompleteOption + for _, option := range d.Options { + if optionFindFunc(option) { + options = append(options, option) + } + } + return options +} diff --git a/discord/interaction_base.go b/discord/interaction_base.go new file mode 100644 index 00000000..67926e9d --- /dev/null +++ b/discord/interaction_base.go @@ -0,0 +1,100 @@ +package discord + +import ( + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" +) + +type BaseInteraction interface { + ID() snowflake.Snowflake + ApplicationID() snowflake.Snowflake + Token() string + Version() int + GuildID() *snowflake.Snowflake + ChannelID() snowflake.Snowflake + Locale() Locale + GuildLocale() *Locale + Member() *ResolvedMember + User() User +} + +type baseInteractionImpl struct { + id snowflake.Snowflake + applicationID snowflake.Snowflake + token string + version int + guildID *snowflake.Snowflake + channelID snowflake.Snowflake + locale Locale + guildLocale *Locale + member *ResolvedMember + user *User +} + +func (i *baseInteractionImpl) UnmarshalJSON(data []byte) error { + var v rawInteraction + if err := json.Unmarshal(data, &v); err != nil { + return err + } + i.id = v.ID + i.applicationID = v.ApplicationID + i.token = v.Token + i.version = v.Version + i.guildID = v.GuildID + i.channelID = v.ChannelID + i.locale = v.Locale + i.guildLocale = v.GuildLocale + i.member = v.Member + i.user = v.User + return nil +} + +func (i baseInteractionImpl) MarshalJSON() ([]byte, error) { + return json.Marshal(rawInteraction{ + ID: i.id, + ApplicationID: i.applicationID, + Token: i.token, + Version: i.version, + GuildID: i.guildID, + ChannelID: i.channelID, + Locale: i.locale, + GuildLocale: i.guildLocale, + Member: i.member, + User: i.user, + }) +} + +func (i baseInteractionImpl) ID() snowflake.Snowflake { + return i.id +} +func (i baseInteractionImpl) ApplicationID() snowflake.Snowflake { + return i.applicationID +} +func (i baseInteractionImpl) Token() string { + return i.token +} +func (i baseInteractionImpl) Version() int { + return i.version +} +func (i baseInteractionImpl) GuildID() *snowflake.Snowflake { + return i.guildID +} +func (i baseInteractionImpl) ChannelID() snowflake.Snowflake { + return i.channelID +} +func (i baseInteractionImpl) Locale() Locale { + return i.locale +} +func (i baseInteractionImpl) GuildLocale() *Locale { + return i.guildLocale +} +func (i baseInteractionImpl) Member() *ResolvedMember { + return i.member +} +func (i baseInteractionImpl) User() User { + if i.user != nil { + return *i.user + } + return i.member.User +} +func (baseInteractionImpl) interaction() {} diff --git a/discord/interaction_callback.go b/discord/interaction_callback.go index 6223d456..9b39d0cf 100644 --- a/discord/interaction_callback.go +++ b/discord/interaction_callback.go @@ -8,11 +8,11 @@ const ( InteractionCallbackTypePong InteractionCallbackType = iota + 1 _ _ - InteractionCallbackTypeChannelMessageWithSource - InteractionCallbackTypeDeferredChannelMessageWithSource + InteractionCallbackTypeCreateMessage + InteractionCallbackTypeDeferredCreateMessage InteractionCallbackTypeDeferredUpdateMessage InteractionCallbackTypeUpdateMessage - InteractionCallbackTypeAutocompleteResult + InteractionCallbackTypeApplicationCommandAutocompleteResult InteractionCallbackTypeModal ) @@ -23,7 +23,7 @@ type InteractionResponse struct { } // ToBody returns the InteractionResponse ready for body -func (r InteractionResponse) ToBody() (interface{}, error) { +func (r InteractionResponse) ToBody() (any, error) { if v, ok := r.Data.(InteractionResponseCreator); ok { return v.ToResponseBody(r) } @@ -35,7 +35,7 @@ type InteractionCallbackData interface { } type InteractionResponseCreator interface { - ToResponseBody(response InteractionResponse) (interface{}, error) + ToResponseBody(response InteractionResponse) (any, error) } type AutocompleteResult struct { @@ -49,22 +49,25 @@ type AutocompleteChoice interface { } type AutocompleteChoiceString struct { - Name string `json:"name"` - Value string `json:"value"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Value string `json:"value"` } func (AutocompleteChoiceString) autoCompleteChoice() {} type AutocompleteChoiceInt struct { - Name string `json:"name"` - Value int `json:"value"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Value int `json:"value"` } func (AutocompleteChoiceInt) autoCompleteChoice() {} type AutocompleteChoiceFloat struct { - Name string `json:"name"` - Value float64 `json:"value"` + Name string `json:"name"` + NameLocalizations map[Locale]string `json:"name_localizations,omitempty"` + Value float64 `json:"value"` } func (AutocompleteChoiceFloat) autoCompleteChoice() {} diff --git a/discord/interaction_component.go b/discord/interaction_component.go new file mode 100644 index 00000000..5498d6d6 --- /dev/null +++ b/discord/interaction_component.go @@ -0,0 +1,163 @@ +package discord + +import ( + "fmt" + + "github.com/disgoorg/disgo/json" +) + +var ( + _ Interaction = (*ComponentInteraction)(nil) +) + +type ComponentInteraction struct { + BaseInteraction + Data ComponentInteractionData `json:"data"` + Message Message `json:"message"` +} + +func (i *ComponentInteraction) UnmarshalJSON(data []byte) error { + var baseInteraction baseInteractionImpl + if err := json.Unmarshal(data, &baseInteraction); err != nil { + return err + } + + var interaction struct { + Data json.RawMessage `json:"data"` + Message Message `json:"message"` + } + if err := json.Unmarshal(data, &interaction); err != nil { + return err + } + + var cType struct { + Type ComponentType `json:"component_type"` + } + + if err := json.Unmarshal(interaction.Data, &cType); err != nil { + return err + } + + var ( + interactionData ComponentInteractionData + err error + ) + switch cType.Type { + case ComponentTypeButton: + v := ButtonInteractionData{} + err = json.Unmarshal(interaction.Data, &v) + interactionData = v + + case ComponentTypeSelectMenu: + v := SelectMenuInteractionData{} + err = json.Unmarshal(interaction.Data, &v) + interactionData = v + + default: + return fmt.Errorf("unkown component interaction data with type %d received", cType.Type) + } + if err != nil { + return err + } + + i.BaseInteraction = baseInteraction + + i.Data = interactionData + i.Message = interaction.Message + return nil +} + +func (ComponentInteraction) Type() InteractionType { + return InteractionTypeComponent +} + +func (i ComponentInteraction) ButtonInteractionData() ButtonInteractionData { + return i.Data.(ButtonInteractionData) +} + +func (i ComponentInteraction) SelectMenuInteractionData() SelectMenuInteractionData { + return i.Data.(SelectMenuInteractionData) +} + +func (ComponentInteraction) interaction() {} + +type ComponentInteractionData interface { + Type() ComponentType + CustomID() CustomID + + componentInteractionData() +} + +type rawButtonInteractionData struct { + Custom CustomID `json:"custom_id"` +} + +type ButtonInteractionData struct { + customID CustomID +} + +func (d *ButtonInteractionData) UnmarshalJSON(data []byte) error { + var v rawButtonInteractionData + if err := json.Unmarshal(data, &v); err != nil { + return err + } + d.customID = v.Custom + return nil +} + +func (d *ButtonInteractionData) MarshalJSON() ([]byte, error) { + return json.Marshal(rawButtonInteractionData{ + Custom: d.customID, + }) +} + +func (ButtonInteractionData) Type() ComponentType { + return ComponentTypeButton +} + +func (d ButtonInteractionData) CustomID() CustomID { + return d.customID +} + +func (ButtonInteractionData) componentInteractionData() {} + +var ( + _ ComponentInteractionData = (*SelectMenuInteractionData)(nil) +) + +type rawSelectMenuInteractionData struct { + Custom CustomID `json:"custom_id"` + Values []string `json:"values"` +} + +type SelectMenuInteractionData struct { + customID CustomID + Values []string +} + +func (d *SelectMenuInteractionData) UnmarshalJSON(data []byte) error { + var v rawSelectMenuInteractionData + if err := json.Unmarshal(data, &v); err != nil { + return err + } + d.customID = v.Custom + d.Values = v.Values + return nil +} + +func (d SelectMenuInteractionData) MarshalJSON() ([]byte, error) { + return json.Marshal(rawSelectMenuInteractionData{ + Custom: d.customID, + Values: d.Values, + }) +} + +func (SelectMenuInteractionData) Type() ComponentType { + return ComponentTypeSelectMenu +} + +func (d SelectMenuInteractionData) CustomID() CustomID { + return d.customID +} + +func (SelectMenuInteractionData) componentInteractionData() {} diff --git a/discord/interaction_modal_submit.go b/discord/interaction_modal_submit.go new file mode 100644 index 00000000..4704c1fa --- /dev/null +++ b/discord/interaction_modal_submit.go @@ -0,0 +1,94 @@ +package discord + +import "github.com/disgoorg/disgo/json" + +var ( + _ Interaction = (*ModalSubmitInteraction)(nil) +) + +type ModalSubmitInteraction struct { + BaseInteraction + Data ModalSubmitInteractionData `json:"data"` +} + +func (i *ModalSubmitInteraction) UnmarshalJSON(data []byte) error { + var baseInteraction baseInteractionImpl + if err := json.Unmarshal(data, &baseInteraction); err != nil { + return err + } + + var interaction struct { + Data ModalSubmitInteractionData `json:"data"` + } + if err := json.Unmarshal(data, &interaction); err != nil { + return err + } + + i.BaseInteraction = baseInteraction + i.Data = interaction.Data + return nil +} + +func (ModalSubmitInteraction) Type() InteractionType { + return InteractionTypeModalSubmit +} + +func (ModalSubmitInteraction) interaction() {} + +type ModalSubmitInteractionData struct { + CustomID CustomID `json:"custom_id"` + Components map[CustomID]InputComponent `json:"components"` +} + +func (d *ModalSubmitInteractionData) UnmarshalJSON(data []byte) error { + type modalSubmitInteractionData ModalSubmitInteractionData + var iData struct { + Components []UnmarshalComponent `json:"components"` + modalSubmitInteractionData + } + + if err := json.Unmarshal(data, &iData); err != nil { + return err + } + + *d = ModalSubmitInteractionData(iData.modalSubmitInteractionData) + + if len(iData.Components) > 0 { + d.Components = make(map[CustomID]InputComponent, len(iData.Components)) + for _, containerComponent := range iData.Components { + for _, component := range containerComponent.Component.(ContainerComponent).Components() { + if inputComponent, ok := component.(InputComponent); ok { + d.Components[inputComponent.ID()] = inputComponent + } + } + } + } + return nil +} + +func (d ModalSubmitInteractionData) Component(customID CustomID) (InputComponent, bool) { + component, ok := d.Components[customID] + return component, ok +} + +func (d ModalSubmitInteractionData) TextInputComponent(customID CustomID) (TextInputComponent, bool) { + if component, ok := d.Component(customID); ok { + textInputComponent, ok := component.(TextInputComponent) + return textInputComponent, ok + } + return TextInputComponent{}, false +} + +func (d ModalSubmitInteractionData) OptText(customID CustomID) (string, bool) { + if textInputComponent, ok := d.TextInputComponent(customID); ok { + return textInputComponent.Value, true + } + return "", false +} + +func (d ModalSubmitInteractionData) Text(customID CustomID) string { + if text, ok := d.OptText(customID); ok { + return text + } + return "" +} diff --git a/discord/interaction_ping.go b/discord/interaction_ping.go new file mode 100644 index 00000000..19a8b42a --- /dev/null +++ b/discord/interaction_ping.go @@ -0,0 +1,85 @@ +package discord + +import ( + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" +) + +var _ Interaction = (*PingInteraction)(nil) + +type PingInteraction struct { + id snowflake.Snowflake + applicationID snowflake.Snowflake + token string + version int +} + +func (i *PingInteraction) UnmarshalJSON(data []byte) error { + var v rawInteraction + + if err := json.Unmarshal(data, &v); err != nil { + return err + } + + i.id = v.ID + i.applicationID = v.ApplicationID + i.token = v.Token + i.version = v.Version + return nil +} + +func (i PingInteraction) MarshalJSON() ([]byte, error) { + return json.Marshal(rawInteraction{ + ID: i.id, + Type: i.Type(), + ApplicationID: i.applicationID, + Token: i.token, + Version: i.version, + }) +} + +func (PingInteraction) Type() InteractionType { + return InteractionTypePing +} + +func (i PingInteraction) ID() snowflake.Snowflake { + return i.id +} + +func (i PingInteraction) ApplicationID() snowflake.Snowflake { + return i.applicationID +} + +func (i PingInteraction) Token() string { + return i.token +} + +func (i PingInteraction) Version() int { + return i.version +} + +func (PingInteraction) GuildID() *snowflake.Snowflake { + return nil +} + +func (PingInteraction) ChannelID() snowflake.Snowflake { + return "" +} + +func (PingInteraction) Locale() Locale { + return "" +} + +func (PingInteraction) GuildLocale() *Locale { + return nil +} + +func (PingInteraction) Member() *ResolvedMember { + return nil +} + +func (PingInteraction) User() User { + return User{} +} + +func (PingInteraction) interaction() {} diff --git a/discord/invite.go b/discord/invite.go index e664d1bf..c07c6caa 100644 --- a/discord/invite.go +++ b/discord/invite.go @@ -1,12 +1,14 @@ package discord -import "github.com/DisgoOrg/snowflake" +import ( + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" +) // InviteTargetType is type of target an Invite uses type InviteTargetType int // Constants for TargetType -//goland:noinspection GoUnusedConst const ( InviteTargetTypeStream InviteTargetType = iota + 1 InviteTargetTypeEmbeddedApplication @@ -16,19 +18,44 @@ const ( type Invite struct { Code string `json:"code"` Guild *InviteGuild `json:"guild"` - GuildID *snowflake.Snowflake `json:"guild_id"` - Channel PartialChannel `json:"channel"` + Channel *InviteChannel `json:"channel"` ChannelID snowflake.Snowflake `json:"channel_id"` Inviter *User `json:"inviter"` TargetUser *User `json:"target_user"` - TargetType *InviteTargetType `json:"target_user_type"` - ApproximatePresenceCount *int `json:"approximate_presence_count"` - ApproximateMemberCount *int `json:"approximate_member_count"` - Uses *int `json:"uses"` - MaxUses *int `json:"max_uses"` - MaxAge *int `json:"max_age"` - Temporary *bool `json:"temporary"` - CreatedAt *Time `json:"created_at"` + TargetType InviteTargetType `json:"target_user_type"` + ApproximatePresenceCount int `json:"approximate_presence_count"` + ApproximateMemberCount int `json:"approximate_member_count"` + ExpiresAt *Time `json:"created_at"` + GuildScheduledEvent *GuildScheduledEvent `json:"guild_scheduled_event"` +} + +func (i Invite) URL() string { + if compiledRoute, err := route.InviteURL.Compile(nil, i.Code); err == nil { + return compiledRoute.URL() + } + return "" +} + +type ExtendedInvite struct { + Invite + Uses int `json:"uses"` + MaxUses int `json:"max_uses"` + MaxAge int `json:"max_age"` + Temporary bool `json:"temporary"` + CreatedAt Time `json:"created_at"` +} + +type InviteChannel struct { + ID snowflake.Snowflake `json:"id"` + Type ChannelType `json:"type"` + Name string `json:"name"` + Icon *string `json:"icon,omitempty"` +} + +// IconURL returns the Icon URL of this channel. +// This will be nil for every ChannelType except ChannelTypeGroupDM +func (c InviteChannel) IconURL(opts ...CDNOpt) *string { + return formatAssetURL(route.ChannelIcon, opts, c.ID, c.Icon) } // An InviteGuild is the Guild of an Invite diff --git a/discord/locale.go b/discord/locale.go index 1bfac365..d18a2751 100644 --- a/discord/locale.go +++ b/discord/locale.go @@ -6,7 +6,7 @@ func (l Locale) String() string { if name, ok := Locales[l]; ok { return name } - return Unknown.String() + return LocaleUnknown.String() } func (l Locale) Code() string { @@ -14,69 +14,69 @@ func (l Locale) Code() string { } const ( - EnglishUS Locale = "en-US" - EnglishGB Locale = "en-GB" - Bulgarian Locale = "bg" - ChineseCN Locale = "zh-CN" - ChineseTW Locale = "zh-TW" - Croatian Locale = "hr" - Czech Locale = "cs" - Danish Locale = "da" - Dutch Locale = "nl" - Finnish Locale = "fi" - French Locale = "fr" - German Locale = "de" - Greek Locale = "el" - Hindi Locale = "hi" - Hungarian Locale = "hu" - Italian Locale = "it" - Japanese Locale = "ja" - Korean Locale = "ko" - Lithuanian Locale = "lt" - Norwegian Locale = "no" - Polish Locale = "pl" - PortugueseBR Locale = "pt-BR" - Romanian Locale = "ro" - Russian Locale = "ru" - SpanishES Locale = "es-ES" - Swedish Locale = "sv-SE" - Thai Locale = "th" - Turkish Locale = "tr" - Ukrainian Locale = "uk" - Vietnamese Locale = "vi" - Unknown Locale = "" + LocaleEnglishUS Locale = "en-US" + LocaleEnglishGB Locale = "en-GB" + LocaleBulgarian Locale = "bg" + LocaleChineseCN Locale = "zh-CN" + LocaleChineseTW Locale = "zh-TW" + LocaleCroatian Locale = "hr" + LocaleCzech Locale = "cs" + LocaleDanish Locale = "da" + LocaleDutch Locale = "nl" + LocaleFinnish Locale = "fi" + LocaleFrench Locale = "fr" + LocaleGerman Locale = "de" + LocaleGreek Locale = "el" + LocaleHindi Locale = "hi" + LocaleHungarian Locale = "hu" + LocaleItalian Locale = "it" + LocaleJapanese Locale = "ja" + LocaleKorean Locale = "ko" + LocaleLithuanian Locale = "lt" + LocaleNorwegian Locale = "no" + LocalePolish Locale = "pl" + LocalePortugueseBR Locale = "pt-BR" + LocaleRomanian Locale = "ro" + LocaleRussian Locale = "ru" + LocaleSpanishES Locale = "es-ES" + LocaleSwedish Locale = "sv-SE" + LocaleThai Locale = "th" + LocaleTurkish Locale = "tr" + LocaleUkrainian Locale = "uk" + LocaleVietnamese Locale = "vi" + LocaleUnknown Locale = "" ) var Locales = map[Locale]string{ - EnglishUS: "English (United States)", - EnglishGB: "English (Great Britain)", - Bulgarian: "Bulgarian", - ChineseCN: "Chinese (China)", - ChineseTW: "Chinese (Taiwan)", - Croatian: "Croatian", - Czech: "Czech", - Danish: "Danish", - Dutch: "Dutch", - Finnish: "Finnish", - French: "French", - German: "German", - Greek: "Greek", - Hindi: "Hindi", - Hungarian: "Hungarian", - Italian: "Italian", - Japanese: "Japanese", - Korean: "Korean", - Lithuanian: "Lithuanian", - Norwegian: "Norwegian", - Polish: "Polish", - PortugueseBR: "Portuguese (Brazil)", - Romanian: "Romanian", - Russian: "Russian", - SpanishES: "Spanish (Spain)", - Swedish: "Swedish", - Thai: "Thai", - Turkish: "Turkish", - Ukrainian: "Ukrainian", - Vietnamese: "Vietnamese", - Unknown: "unknown", + LocaleEnglishUS: "English (United States)", + LocaleEnglishGB: "English (Great Britain)", + LocaleBulgarian: "Bulgarian", + LocaleChineseCN: "Chinese (China)", + LocaleChineseTW: "Chinese (Taiwan)", + LocaleCroatian: "Croatian", + LocaleCzech: "Czech", + LocaleDanish: "Danish", + LocaleDutch: "Dutch", + LocaleFinnish: "Finnish", + LocaleFrench: "French", + LocaleGerman: "German", + LocaleGreek: "Greek", + LocaleHindi: "Hindi", + LocaleHungarian: "Hungarian", + LocaleItalian: "Italian", + LocaleJapanese: "Japanese", + LocaleKorean: "Korean", + LocaleLithuanian: "Lithuanian", + LocaleNorwegian: "Norwegian", + LocalePolish: "Polish", + LocalePortugueseBR: "Portuguese (Brazil)", + LocaleRomanian: "Romanian", + LocaleRussian: "Russian", + LocaleSpanishES: "Spanish (Spain)", + LocaleSwedish: "Swedish", + LocaleThai: "Thai", + LocaleTurkish: "Turkish", + LocaleUkrainian: "Ukrainian", + LocaleVietnamese: "Vietnamese", + LocaleUnknown: "unknown", } diff --git a/discord/member.go b/discord/member.go index 91e90253..946286cc 100644 --- a/discord/member.go +++ b/discord/member.go @@ -1,6 +1,10 @@ package discord -import "github.com/DisgoOrg/snowflake" +import ( + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" +) var _ Mentionable = (*Member)(nil) @@ -17,7 +21,14 @@ type Member struct { Mute bool `json:"mute,omitempty"` Pending bool `json:"pending"` CommunicationDisabledUntil *Time `json:"communication_disabled_until"` - Permissions *Permissions `json:"permissions"` // only sent from slash commands & should not be cached +} + +func (m Member) String() string { + return MemberMention(m.User.ID) +} + +func (m Member) Mention() string { + return m.String() } // EffectiveName returns either the nickname or username depending on if the user has a nickname @@ -28,12 +39,18 @@ func (m Member) EffectiveName() string { return m.User.Username } -func (m Member) String() string { - return memberMention(m.User.ID) +func (m Member) EffectiveAvatarURL(opts ...CDNOpt) string { + if m.Avatar == nil { + return m.User.EffectiveAvatarURL(opts...) + } + if avatar := m.AvatarURL(opts...); avatar != nil { + return *avatar + } + return "" } -func (m Member) Mention() string { - return m.String() +func (m Member) AvatarURL(opts ...CDNOpt) *string { + return formatAssetURL(route.MemberAvatar, opts, m.User.ID, m.Avatar) } // MemberAdd is used to add a member via the oauth2 access token to a guild @@ -52,7 +69,7 @@ type MemberUpdate struct { Roles []snowflake.Snowflake `json:"roles,omitempty"` Mute *bool `json:"mute,omitempty"` Deaf *bool `json:"deaf,omitempty"` - CommunicationDisabledUntil *NullTime `json:"communication_disabled_until,omitempty"` + CommunicationDisabledUntil *json.Nullable[Time] `json:"communication_disabled_until,omitempty"` } // SelfNickUpdate is used to update your own nick diff --git a/discord/mentionable.go b/discord/mentionable.go index 3ec3f5c1..9cf1aa06 100644 --- a/discord/mentionable.go +++ b/discord/mentionable.go @@ -4,69 +4,60 @@ import ( "fmt" "regexp" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/snowflake" ) type MentionType struct { *regexp.Regexp } -//goland:noinspection GoUnusedGlobalVariable var ( MentionTypeUser = MentionType{regexp.MustCompile(`<@!?(\d+)>`)} MentionTypeRole = MentionType{regexp.MustCompile(`<@&(\d+)>`)} MentionTypeChannel = MentionType{regexp.MustCompile(`<#(\d+)>`)} - MentionTypeEmoji = MentionType{regexp.MustCompile(``)} + MentionTypeEmoji = MentionType{regexp.MustCompile(``)} MentionTypeTimestamp = MentionType{regexp.MustCompile(`-?\d{1,17})(?::(?P[tTdDfFR]))?>`)} MentionTypeHere = MentionType{regexp.MustCompile(`@here`)} MentionTypeEveryone = MentionType{regexp.MustCompile(`@everyone`)} ) type Mentionable interface { + fmt.Stringer Mention() string } -//goland:noinspection GoUnusedFunction -func channelMention(id snowflake.Snowflake) string { +func ChannelMention(id snowflake.Snowflake) string { return fmt.Sprintf("<#%s>", id) } -//goland:noinspection GoUnusedFunction -func userTag(username string, discriminator string) string { +func UserTag(username string, discriminator string) string { return fmt.Sprintf("%s#%s", username, discriminator) } -//goland:noinspection GoUnusedFunction -func userMention(id snowflake.Snowflake) string { +func UserMention(id snowflake.Snowflake) string { return fmt.Sprintf("<@%s>", id) } -//goland:noinspection GoUnusedFunction -func memberMention(id snowflake.Snowflake) string { +func MemberMention(id snowflake.Snowflake) string { return fmt.Sprintf("<@!%s>", id) } -//goland:noinspection GoUnusedFunction -func roleMention(id snowflake.Snowflake) string { +func RoleMention(id snowflake.Snowflake) string { return fmt.Sprintf("<@&%s>", id) } -//goland:noinspection GoUnusedFunction -func emojiMention(id snowflake.Snowflake, name string) string { +func EmojiMention(id snowflake.Snowflake, name string) string { return fmt.Sprintf("<:%s:%s>", name, id) } -//goland:noinspection GoUnusedFunction -func animatedEmojiMention(id snowflake.Snowflake, name string) string { +func AnimatedEmojiMention(id snowflake.Snowflake, name string) string { return fmt.Sprintf("", name, id) } -//goland:noinspection GoUnusedFunction -func timestampMention(timestamp int64) string { - return fmt.Sprintf("", timestamp) +func TimestampMention(timestamp int64) string { + return TimestampStyleNone.Format(timestamp) } -//goland:noinspection GoUnusedFunction -func formattedTimestampMention(timestamp int64, style TimestampStyle) string { - return fmt.Sprintf("", timestamp, style) +func FormattedTimestampMention(timestamp int64, style TimestampStyle) string { + return style.Format(timestamp) } diff --git a/discord/message.go b/discord/message.go index 99f9526d..92a38a79 100644 --- a/discord/message.go +++ b/discord/message.go @@ -1,15 +1,14 @@ package discord import ( - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" ) // The MessageType indicates the Message type type MessageType int // Constants for the MessageType -//goland:noinspection GoUnusedConst const ( MessageTypeDefault MessageType = iota MessageTypeRecipientAdd @@ -47,7 +46,7 @@ type Message struct { Embeds []Embed `json:"embeds,omitempty"` Components []ContainerComponent `json:"components,omitempty"` CreatedAt Time `json:"timestamp"` - Mentions []interface{} `json:"mentions"` + Mentions []any `json:"mentions"` MentionEveryone bool `json:"mention_everyone"` MentionRoles []snowflake.Snowflake `json:"mention_roles"` MentionChannels []Channel `json:"mention_channels"` @@ -98,6 +97,90 @@ func (m *Message) UnmarshalJSON(data []byte) error { return nil } +// ActionRows returns all ActionRowComponent(s) from this Message +func (m *Message) ActionRows() []ActionRowComponent { + var actionRows []ActionRowComponent + for i := range m.Components { + if actionRow, ok := m.Components[i].(ActionRowComponent); ok { + actionRows = append(actionRows, actionRow) + } + } + return actionRows +} + +// InteractiveComponents returns the InteractiveComponent(s) from this Message +func (m *Message) InteractiveComponents() []InteractiveComponent { + var interactiveComponents []InteractiveComponent + for i := range m.Components { + for ii := range m.Components[i].Components() { + interactiveComponents = append(interactiveComponents, m.Components[i].Components()[ii]) + } + } + return interactiveComponents +} + +// ComponentByID returns the Component with the specific CustomID +func (m *Message) ComponentByID(customID CustomID) InteractiveComponent { + for i := range m.Components { + for ii := range m.Components[i].Components() { + if m.Components[i].Components()[ii].ID() == customID { + return m.Components[i].Components()[ii] + } + } + } + return nil +} + +// Buttons returns all ButtonComponent(s) from this Message +func (m *Message) Buttons() []ButtonComponent { + var buttons []ButtonComponent + for i := range m.Components { + for ii := range m.Components[i].Components() { + if button, ok := m.Components[i].Components()[ii].(ButtonComponent); ok { + buttons = append(buttons, button) + } + } + } + return buttons +} + +// ButtonByID returns a ButtonComponent with the specific customID from this Message +func (m *Message) ButtonByID(customID CustomID) *ButtonComponent { + for i := range m.Components { + for ii := range m.Components[i].Components() { + if button, ok := m.Components[i].Components()[ii].(*ButtonComponent); ok && button.ID() == customID { + return button + } + } + } + return nil +} + +// SelectMenus returns all SelectMenuComponent(s) from this Message +func (m *Message) SelectMenus() []SelectMenuComponent { + var selectMenus []SelectMenuComponent + for i := range m.Components { + for ii := range m.Components[i].Components() { + if button, ok := m.Components[i].Components()[ii].(SelectMenuComponent); ok { + selectMenus = append(selectMenus, button) + } + } + } + return selectMenus +} + +// SelectMenuByID returns a SelectMenuComponent with the specific customID from this Message +func (m *Message) SelectMenuByID(customID CustomID) *SelectMenuComponent { + for i := range m.Components { + for ii := range m.Components[i].Components() { + if button, ok := m.Components[i].Components()[ii].(*SelectMenuComponent); ok && button.ID() == customID { + return button + } + } + } + return nil +} + type MessageSticker struct { ID snowflake.Snowflake `json:"id"` Name string `json:"name"` @@ -111,11 +194,10 @@ type MessageReaction struct { Emoji Emoji `json:"emoji"` } -// MessageActivityType is the type of MessageActivity https://discord.com/developers/docs/resources/channel#message-object-message-activity-types +// MessageActivityType is the type of MessageActivity https://com/developers/docs/resources/channel#message-object-message-activity-types type MessageActivityType int //Constants for MessageActivityType -//goland:noinspection GoUnusedConst const ( MessageActivityTypeJoin MessageActivityType = iota + 1 MessageActivityTypeSpectate @@ -163,7 +245,6 @@ type MessageBulkDelete struct { type MessageFlags int64 // Constants for MessageFlags -//goland:noinspection GoUnusedConst const ( MessageFlagCrossposted MessageFlags = 1 << iota MessageFlagIsCrosspost diff --git a/discord/message_create.go b/discord/message_create.go index 94af856c..6baceb87 100644 --- a/discord/message_create.go +++ b/discord/message_create.go @@ -1,6 +1,8 @@ package discord -import "github.com/DisgoOrg/snowflake" +import ( + "github.com/disgoorg/snowflake" +) // MessageCreate is the struct to create a new Message with type MessageCreate struct { @@ -11,6 +13,7 @@ type MessageCreate struct { Components []ContainerComponent `json:"components,omitempty"` StickerIDs []snowflake.Snowflake `json:"sticker_ids,omitempty"` Files []*File `json:"-"` + Attachments []AttachmentCreate `json:"attachments,omitempty"` AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"` MessageReference *MessageReference `json:"message_reference,omitempty"` Flags MessageFlags `json:"flags,omitempty"` @@ -19,15 +22,17 @@ type MessageCreate struct { func (MessageCreate) interactionCallbackData() {} // ToBody returns the MessageCreate ready for body -func (m MessageCreate) ToBody() (interface{}, error) { +func (m MessageCreate) ToBody() (any, error) { if len(m.Files) > 0 { + m.Attachments = parseAttachments(m.Files) return PayloadWithFiles(m, m.Files...) } return m, nil } -func (m MessageCreate) ToResponseBody(response InteractionResponse) (interface{}, error) { +func (m MessageCreate) ToResponseBody(response InteractionResponse) (any, error) { if len(m.Files) > 0 { + m.Attachments = parseAttachments(m.Files) return PayloadWithFiles(response, m.Files...) } return response, nil diff --git a/discord/message_create_builder.go b/discord/message_create_builder.go index 426d283f..e18ae3ad 100644 --- a/discord/message_create_builder.go +++ b/discord/message_create_builder.go @@ -4,7 +4,7 @@ import ( "fmt" "io" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/snowflake" ) // MessageCreateBuilder helper to build Message(s) easier @@ -13,7 +13,6 @@ type MessageCreateBuilder struct { } // NewMessageCreateBuilder creates a new MessageCreateBuilder to be built later -//goland:noinspection GoUnusedExportedFunction func NewMessageCreateBuilder() *MessageCreateBuilder { return &MessageCreateBuilder{ MessageCreate: MessageCreate{ @@ -29,7 +28,7 @@ func (b *MessageCreateBuilder) SetContent(content string) *MessageCreateBuilder } // SetContentf sets the content of the Message but with format -func (b *MessageCreateBuilder) SetContentf(content string, a ...interface{}) *MessageCreateBuilder { +func (b *MessageCreateBuilder) SetContentf(content string, a ...any) *MessageCreateBuilder { return b.SetContent(fmt.Sprintf(content, a...)) } @@ -152,8 +151,8 @@ func (b *MessageCreateBuilder) AddFiles(files ...*File) *MessageCreateBuilder { } // AddFile adds a discord.File to the discord.MessageCreate -func (b *MessageCreateBuilder) AddFile(name string, reader io.Reader, flags ...FileFlags) *MessageCreateBuilder { - b.Files = append(b.Files, NewFile(name, reader, flags...)) +func (b *MessageCreateBuilder) AddFile(name string, description string, reader io.Reader, flags ...FileFlags) *MessageCreateBuilder { + b.Files = append(b.Files, NewFile(name, description, reader, flags...)) return b } diff --git a/discord/message_update.go b/discord/message_update.go index 43156ffe..d04e6dcc 100644 --- a/discord/message_update.go +++ b/discord/message_update.go @@ -5,7 +5,7 @@ type MessageUpdate struct { Content *string `json:"content,omitempty"` Embeds *[]Embed `json:"embeds,omitempty"` Components *[]ContainerComponent `json:"components,omitempty"` - Attachments *[]Attachment `json:"attachments,omitempty"` + Attachments *[]AttachmentUpdate `json:"attachments,omitempty"` Files []*File `json:"-"` AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"` Flags *MessageFlags `json:"flags,omitempty"` @@ -14,15 +14,27 @@ type MessageUpdate struct { func (MessageUpdate) interactionCallbackData() {} // ToBody returns the MessageUpdate ready for body -func (m MessageUpdate) ToBody() (interface{}, error) { +func (m MessageUpdate) ToBody() (any, error) { if len(m.Files) > 0 { + for _, attachmentCreate := range parseAttachments(m.Files) { + if m.Attachments == nil { + m.Attachments = new([]AttachmentUpdate) + } + *m.Attachments = append(*m.Attachments, attachmentCreate) + } return PayloadWithFiles(m, m.Files...) } return m, nil } -func (m MessageUpdate) ToResponseBody(response InteractionResponse) (interface{}, error) { +func (m MessageUpdate) ToResponseBody(response InteractionResponse) (any, error) { if len(m.Files) > 0 { + for _, attachmentCreate := range parseAttachments(m.Files) { + if m.Attachments == nil { + m.Attachments = &[]AttachmentUpdate{} + } + *m.Attachments = append(*m.Attachments, attachmentCreate) + } return PayloadWithFiles(response, m.Files...) } return response, nil diff --git a/discord/message_update_builder.go b/discord/message_update_builder.go index bf3ccb83..b4f20d1f 100644 --- a/discord/message_update_builder.go +++ b/discord/message_update_builder.go @@ -4,7 +4,7 @@ import ( "fmt" "io" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/snowflake" ) // MessageUpdateBuilder helper to build MessageUpdate easier @@ -28,7 +28,7 @@ func (b *MessageUpdateBuilder) SetContent(content string) *MessageUpdateBuilder } // SetContentf sets content of the Message -func (b *MessageUpdateBuilder) SetContentf(content string, a ...interface{}) *MessageUpdateBuilder { +func (b *MessageUpdateBuilder) SetContentf(content string, a ...any) *MessageUpdateBuilder { return b.SetContent(fmt.Sprintf(content, a...)) } @@ -159,8 +159,8 @@ func (b *MessageUpdateBuilder) AddFiles(files ...*File) *MessageUpdateBuilder { } // AddFile adds a new discord.File to the discord.MessageUpdate -func (b *MessageUpdateBuilder) AddFile(name string, reader io.Reader, flags ...FileFlags) *MessageUpdateBuilder { - b.Files = append(b.Files, NewFile(name, reader, flags...)) +func (b *MessageUpdateBuilder) AddFile(name string, description string, reader io.Reader, flags ...FileFlags) *MessageUpdateBuilder { + b.Files = append(b.Files, NewFile(name, description, reader, flags...)) return b } @@ -181,19 +181,21 @@ func (b *MessageUpdateBuilder) RemoveFile(i int) *MessageUpdateBuilder { // RetainAttachments removes all Attachment(s) from this Message except the ones provided func (b *MessageUpdateBuilder) RetainAttachments(attachments ...Attachment) *MessageUpdateBuilder { if b.Attachments == nil { - b.Attachments = new([]Attachment) + b.Attachments = new([]AttachmentUpdate) + } + for _, attachment := range attachments { + *b.Attachments = append(*b.Attachments, AttachmentKeep{ID: attachment.ID}) } - *b.Attachments = append(*b.Attachments, attachments...) return b } // RetainAttachmentsByID removes all Attachment(s) from this Message except the ones provided func (b *MessageUpdateBuilder) RetainAttachmentsByID(attachmentIDs ...snowflake.Snowflake) *MessageUpdateBuilder { if b.Attachments == nil { - b.Attachments = new([]Attachment) + b.Attachments = new([]AttachmentUpdate) } for _, attachmentID := range attachmentIDs { - *b.Attachments = append(*b.Attachments, Attachment{ID: attachmentID}) + *b.Attachments = append(*b.Attachments, AttachmentKeep{ID: attachmentID}) } return b } diff --git a/discord/modal_create.go b/discord/modal_create.go index f7af29ac..247684ad 100644 --- a/discord/modal_create.go +++ b/discord/modal_create.go @@ -11,7 +11,6 @@ type ModalCreate struct { func (ModalCreate) interactionCallbackData() {} // NewModalCreateBuilder creates a new ModalCreateBuilder to be built later -//goland:noinspection GoUnusedExportedFunction func NewModalCreateBuilder() *ModalCreateBuilder { return &ModalCreateBuilder{} } diff --git a/discord/null_types.go b/discord/null_types.go deleted file mode 100644 index 52608c0e..00000000 --- a/discord/null_types.go +++ /dev/null @@ -1,33 +0,0 @@ -package discord - -import ( - "time" -) - -type NullTime *Time - -//goland:noinspection GoUnusedExportedFunction -func NewTime(time time.Time) *NullTime { - ot := NullTime(&Time{Time: time}) - return &ot -} - -//goland:noinspection GoUnusedExportedFunction -func NewNullTime() *NullTime { - ot := NullTime(nil) - return &ot -} - -type NullIcon *Icon - -//goland:noinspection GoUnusedExportedFunction -func NewNIcon(icon Icon) *NullIcon { - oi := NullIcon(&icon) - return &oi -} - -//goland:noinspection GoUnusedExportedFunction -func NewNullIcon() *NullIcon { - oi := NullIcon(nil) - return &oi -} diff --git a/discord/opcodes.go b/discord/opcodes.go index 1dd4dc08..52a065e7 100644 --- a/discord/opcodes.go +++ b/discord/opcodes.go @@ -6,7 +6,6 @@ import "github.com/gorilla/websocket" type GatewayOpcode int // https://discord.com/developers/docs/topics/opcodes-and-status-codes#gateway-gateway-opcodes -//goland:noinspection GoUnusedConst const ( GatewayOpcodeDispatch GatewayOpcode = iota GatewayOpcodeHeartbeat @@ -24,7 +23,6 @@ const ( type GatewayCloseEventCode int -//goland:noinspection GoUnusedConst const ( GatewayCloseEventCodeUnknownError GatewayCloseEventCode = iota + 4000 GatewayCloseEventCodeUnknownOpcode @@ -61,7 +59,6 @@ func (c GatewayCloseEventCode) ShouldReconnect() bool { type VoiceOpcode int -//goland:noinspection GoUnusedConst const ( VoiceOpcodeIdentify VoiceOpcode = iota VoiceOpcodeSelectProtocol @@ -81,7 +78,6 @@ const ( type VoiceCloseEventCode int -//goland:noinspection GoUnusedConst const ( VoiceCloseEventCodeUnknownOpcode VoiceCloseEventCode = iota + 4001 VoiceCloseEventCodeDecodeError diff --git a/discord/permission_overwrite.go b/discord/permission_overwrite.go index c54e11fe..0e12b2dd 100644 --- a/discord/permission_overwrite.go +++ b/discord/permission_overwrite.go @@ -3,15 +3,14 @@ package discord import ( "fmt" - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" ) // PermissionOverwriteType is the type of PermissionOverwrite type PermissionOverwriteType int // Constants for PermissionOverwriteType -//goland:noinspection GoUnusedConst const ( PermissionOverwriteTypeRole PermissionOverwriteType = iota PermissionOverwriteTypeMember diff --git a/discord/permissions.go b/discord/permissions.go index 42e31f25..76cd831a 100644 --- a/discord/permissions.go +++ b/discord/permissions.go @@ -4,14 +4,13 @@ import ( "bytes" "strconv" - "github.com/DisgoOrg/disgo/json" + "github.com/disgoorg/disgo/json" ) // Permissions extends the Bit structure, and is used within roles and channels (https://discord.com/developers/docs/topics/permissions#permissions) type Permissions int64 // Constants for the different bit offsets of text channel permissions -//goland:noinspection GoUnusedConst const ( PermissionSendMessages Permissions = 1 << (iota + 11) PermissionSendTTSMessages @@ -24,7 +23,6 @@ const ( ) // Constants for the different bit offsets of voice permissions -//goland:noinspection GoUnusedConst const ( PermissionVoiceConnect Permissions = 1 << (iota + 20) PermissionVoiceSpeak @@ -36,7 +34,6 @@ const ( ) // Constants for general management. -//goland:noinspection GoUnusedConst const ( PermissionChangeNickname Permissions = 1 << (iota + 26) PermissionManageNicknames @@ -56,7 +53,6 @@ const ( ) // Constants for the different bit offsets of general permissions -//goland:noinspection GoUnusedConst const ( PermissionCreateInstantInvite Permissions = 1 << iota PermissionKickMembers diff --git a/discord/permissions_test.go b/discord/permissions_test.go index 87b7301c..408dd7e9 100644 --- a/discord/permissions_test.go +++ b/discord/permissions_test.go @@ -3,7 +3,7 @@ package discord import ( "testing" - "github.com/DisgoOrg/disgo/json" + "github.com/disgoorg/disgo/json" "github.com/stretchr/testify/assert" ) diff --git a/discord/presence.go b/discord/presence.go index 38fc4f72..e5f76af9 100644 --- a/discord/presence.go +++ b/discord/presence.go @@ -1,6 +1,10 @@ package discord -import "github.com/DisgoOrg/snowflake" +import ( + "time" + + "github.com/disgoorg/snowflake" +) // Presence (https://discord.com/developers/docs/topics/gateway#presence-update) type Presence struct { @@ -18,7 +22,6 @@ type PresenceUser struct { // OnlineStatus (https://discord.com/developers/docs/topics/gateway#update-presence-status-types) type OnlineStatus string -//goland:noinspection GoUnusedConst const ( OnlineStatusOnline OnlineStatus = "online" OnlineStatusDND OnlineStatus = "dnd" @@ -33,3 +36,56 @@ type ClientStatus struct { Mobile OnlineStatus `json:"mobile,omitempty"` Web OnlineStatus `json:"web,omitempty"` } + +// NewPresence creates a new Presence with the provided properties +func NewPresence(activityType ActivityType, name string, url string, status OnlineStatus, afk bool) GatewayMessageDataPresenceUpdate { + var since *int64 + if status == OnlineStatusIdle { + unix := time.Now().Unix() + since = &unix + } + + var activities []Activity + if name != "" { + activity := Activity{ + Name: name, + Type: activityType, + } + if activityType == ActivityTypeStreaming && url != "" { + activity.URL = &url + } + activities = append(activities, activity) + } + + return GatewayMessageDataPresenceUpdate{ + Since: since, + Activities: activities, + Status: status, + AFK: afk, + } +} + +// NewGamePresence creates a new Presence of type ActivityTypeGame +func NewGamePresence(name string, status OnlineStatus, afk bool) GatewayMessageDataPresenceUpdate { + return NewPresence(ActivityTypeGame, name, "", status, afk) +} + +// NewStreamingPresence creates a new Presence of type ActivityTypeStreaming +func NewStreamingPresence(name string, url string, status OnlineStatus, afk bool) GatewayMessageDataPresenceUpdate { + return NewPresence(ActivityTypeStreaming, name, url, status, afk) +} + +// NewListeningPresence creates a new Presence of type ActivityTypeListening +func NewListeningPresence(name string, status OnlineStatus, afk bool) GatewayMessageDataPresenceUpdate { + return NewPresence(ActivityTypeListening, name, "", status, afk) +} + +// NewWatchingPresence creates a new Presence of type ActivityTypeWatching +func NewWatchingPresence(name string, status OnlineStatus, afk bool) GatewayMessageDataPresenceUpdate { + return NewPresence(ActivityTypeWatching, name, "", status, afk) +} + +// NewCompetingPresence creates a new Presence of type ActivityTypeCompeting +func NewCompetingPresence(name string, status OnlineStatus, afk bool) GatewayMessageDataPresenceUpdate { + return NewPresence(ActivityTypeCompeting, name, "", status, afk) +} diff --git a/discord/role.go b/discord/role.go index 384e57be..e67cf896 100644 --- a/discord/role.go +++ b/discord/role.go @@ -1,8 +1,9 @@ package discord import ( - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) var _ Mentionable = (*Role)(nil) @@ -10,7 +11,6 @@ var _ Mentionable = (*Role)(nil) // Role is a Guild Role object type Role struct { ID snowflake.Snowflake `json:"id"` - GuildID snowflake.Snowflake `json:"guild_id"` Name string `json:"name"` Color int `json:"color"` Hoist bool `json:"hoist"` @@ -24,13 +24,17 @@ type Role struct { } func (r Role) String() string { - return roleMention(r.ID) + return RoleMention(r.ID) } func (r Role) Mention() string { return r.String() } +func (r Role) IconURL(opts ...CDNOpt) *string { + return formatAssetURL(route.RoleIcon, opts, r.ID, r.Icon) +} + // RoleTag are tags a Role has type RoleTag struct { BotID *snowflake.Snowflake `json:"bot_id,omitempty"` @@ -51,13 +55,13 @@ type RoleCreate struct { // RoleUpdate is the payload to update a Role type RoleUpdate struct { - Name *string `json:"name"` - Permissions *Permissions `json:"permissions"` - Color *int `json:"color"` - Hoist *bool `json:"hoist"` - Icon *NullIcon `json:"icon,omitempty"` - Emoji *json.NullString `json:"unicode_emoji,omitempty"` - Mentionable *bool `json:"mentionable"` + Name *string `json:"name"` + Permissions *Permissions `json:"permissions"` + Color *int `json:"color"` + Hoist *bool `json:"hoist"` + Icon *json.Nullable[Icon] `json:"icon,omitempty"` + Emoji *string `json:"unicode_emoji,omitempty"` + Mentionable *bool `json:"mentionable"` } // RolePositionUpdate is the payload to update a Role(s) position diff --git a/discord/slash_command_option.go b/discord/slash_command_option.go index 749a8c54..cf75f68a 100644 --- a/discord/slash_command_option.go +++ b/discord/slash_command_option.go @@ -3,8 +3,8 @@ package discord import ( "fmt" - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" ) type SlashCommandOption interface { @@ -101,9 +101,8 @@ func (o *UnmarshalSlashCommandOption) UnmarshalJSON(data []byte) error { var _ SlashCommandOption = (*SlashCommandOptionSubCommand)(nil) type SlashCommandOptionSubCommand struct { - OptionName string `json:"name"` - Description string `json:"description"` - Options []SlashCommandOption `json:"options,omitempty"` + OptionName string `json:"name"` + Options []SlashCommandOption `json:"options,omitempty"` } func (o *SlashCommandOptionSubCommand) UnmarshalJSON(data []byte) error { @@ -140,9 +139,8 @@ func (o SlashCommandOptionSubCommand) Name() string { var _ SlashCommandOption = (*SlashCommandOptionSubCommandGroup)(nil) type SlashCommandOptionSubCommandGroup struct { - OptionName string `json:"name"` - Description string `json:"description"` - Options []SlashCommandOptionSubCommand `json:"options,omitempty"` + OptionName string `json:"name"` + Options []SlashCommandOptionSubCommand `json:"options,omitempty"` } func (SlashCommandOptionSubCommandGroup) slashCommandOption() {} diff --git a/discord/stage_instance.go b/discord/stage_instance.go index dcbfa798..c9edddd0 100644 --- a/discord/stage_instance.go +++ b/discord/stage_instance.go @@ -1,10 +1,9 @@ package discord -import "github.com/DisgoOrg/snowflake" +import "github.com/disgoorg/snowflake" type StagePrivacyLevel int -//goland:noinspection GoUnusedConst const ( StagePrivacyLevelPublic StagePrivacyLevel = iota + 1 StagePrivacyLevelGuildOnly diff --git a/discord/sticker.go b/discord/sticker.go index 79736523..35dfe015 100644 --- a/discord/sticker.go +++ b/discord/sticker.go @@ -1,8 +1,8 @@ package discord import ( - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) // Sticker is a sticker sent with a Message @@ -10,7 +10,7 @@ type Sticker struct { ID snowflake.Snowflake `json:"id"` PackID *snowflake.Snowflake `json:"pack_id"` Name string `json:"name"` - Description *string `json:"description"` + Description string `json:"description"` Tags string `json:"tags"` Type StickerType `json:"type"` FormatType StickerFormatType `json:"format_type"` @@ -20,9 +20,19 @@ type Sticker struct { SortValue *int `json:"sort_value"` } +func (s Sticker) URL(opts ...CDNOpt) string { + format := route.PNG + if s.FormatType == StickerFormatTypeLottie { + format = route.Lottie + } + if avatar := formatAssetURL(route.CustomSticker, append(opts, WithFormat(format)), s.ID); avatar != nil { + return *avatar + } + return "" +} + type StickerType int -//goland:noinspection GoUnusedConst const ( StickerTypeStandard StickerType = iota + 1 StickerTypeGuild @@ -32,7 +42,6 @@ const ( type StickerFormatType int // Constants for StickerFormatType -//goland:noinspection GoUnusedConst const ( StickerFormatTypePNG StickerFormatType = iota + 1 StickerFormatTypeAPNG @@ -47,7 +56,7 @@ type StickerCreate struct { } // ToBody returns the MessageCreate ready for body -func (c *StickerCreate) ToBody() (interface{}, error) { +func (c *StickerCreate) ToBody() (any, error) { if c.File != nil { return PayloadWithFiles(c, c.File) } @@ -55,7 +64,25 @@ func (c *StickerCreate) ToBody() (interface{}, error) { } type StickerUpdate struct { - Name *string `json:"name,omitempty"` - Description *json.NullString `json:"description,omitempty"` - Tags *string `json:"tags,omitempty"` + Name *string `json:"name,omitempty"` + Description *string `json:"description,omitempty"` + Tags *string `json:"tags,omitempty"` +} + +type StickerPack struct { + ID snowflake.Snowflake `json:"id"` + Stickers []Sticker `json:"stickers"` + Name string `json:"name"` + SkuID snowflake.Snowflake `json:"sku_id"` + CoverStickerID snowflake.Snowflake `json:"cover_sticker_id"` + Description string `json:"description"` + BannerAssetID snowflake.Snowflake `json:"banner_asset_id"` +} + +func (p StickerPack) BannerURL(opts ...CDNOpt) *string { + return formatAssetURL(route.StickerPackBanner, opts, p.BannerAssetID) +} + +type StickerPacks struct { + StickerPacks []StickerPack `json:"sticker_packs"` } diff --git a/discord/sticker_pack.go b/discord/sticker_pack.go deleted file mode 100644 index 00a2454d..00000000 --- a/discord/sticker_pack.go +++ /dev/null @@ -1,17 +0,0 @@ -package discord - -import "github.com/DisgoOrg/snowflake" - -type StickerPack struct { - ID snowflake.Snowflake `json:"id"` - Stickers []Sticker `json:"stickers"` - Name string `json:"name"` - SkuID snowflake.Snowflake `json:"sku_id"` - CoverStickerID snowflake.Snowflake `json:"cover_sticker_id"` - Description string `json:"description"` - BannerAssetID snowflake.Snowflake `json:"banner_asset_id"` -} - -type StickerPacks struct { - StickerPacks []StickerPack `json:"sticker_packs"` -} diff --git a/discord/thread.go b/discord/thread.go index a9e3a325..6b486a98 100644 --- a/discord/thread.go +++ b/discord/thread.go @@ -1,6 +1,6 @@ package discord -import "github.com/DisgoOrg/disgo/json" +import "github.com/disgoorg/disgo/json" type ThreadCreateWithMessage struct { Name string `json:"name"` diff --git a/discord/thread_member.go b/discord/thread_member.go index 1bf7c826..58d6dcba 100644 --- a/discord/thread_member.go +++ b/discord/thread_member.go @@ -1,6 +1,6 @@ package discord -import "github.com/DisgoOrg/snowflake" +import "github.com/disgoorg/snowflake" type ThreadMember struct { ThreadID snowflake.Snowflake `json:"id"` diff --git a/discord/time.go b/discord/time.go index 8b42dfff..706c5a03 100644 --- a/discord/time.go +++ b/discord/time.go @@ -5,7 +5,7 @@ import ( "strconv" "time" - "github.com/DisgoOrg/disgo/json" + "github.com/disgoorg/disgo/json" ) const TimeFormat = "2006-01-02T15:04:05+00:00" diff --git a/discord/time_test.go b/discord/time_test.go index 68b4c952..4fe641ee 100644 --- a/discord/time_test.go +++ b/discord/time_test.go @@ -4,7 +4,7 @@ import ( "testing" "time" - "github.com/DisgoOrg/disgo/json" + "github.com/disgoorg/disgo/json" "github.com/stretchr/testify/assert" ) diff --git a/discord/timestamp.go b/discord/timestamp.go index 4413a12b..61be5d16 100644 --- a/discord/timestamp.go +++ b/discord/timestamp.go @@ -1,11 +1,10 @@ package discord import ( + "errors" "fmt" "strconv" "time" - - "github.com/pkg/errors" ) // ErrNoTimestampMatch is returned when no valid Timestamp is found in the Message @@ -14,7 +13,6 @@ var ErrNoTimestampMatch = errors.New("no matching timestamp found in string") // TimestampStyle is used to determine how to display the Timestamp for the User in the client type TimestampStyle string -//goland:noinspection GoUnusedConst const ( // TimestampStyleNone formats as default TimestampStyleNone TimestampStyle = "" @@ -49,9 +47,9 @@ func (f TimestampStyle) FormatTime(time time.Time) string { // Format returns the seconds formatted as markdown string func (f TimestampStyle) Format(seconds int64) string { if f == TimestampStyleNone { - return timestampMention(seconds) + return TimestampMention(seconds) } - return formattedTimestampMention(seconds, f) + return FormattedTimestampMention(seconds, f) } // ParseTimestamps parses all Timestamp(s) found in the provided string @@ -77,7 +75,6 @@ func ParseTimestamps(str string, n int) ([]Timestamp, error) { } // ParseTimestamp parses the first Timestamp found in the provided string -//goland:noinspection GoUnusedExportedFunction func ParseTimestamp(str string) (*Timestamp, error) { timestamps, err := ParseTimestamps(str, 1) if err != nil { diff --git a/discord/user.go b/discord/user.go index c5725919..3b80c8ee 100644 --- a/discord/user.go +++ b/discord/user.go @@ -1,12 +1,17 @@ package discord -import "github.com/DisgoOrg/snowflake" +import ( + "strconv" + + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" +) // UserFlags defines certain flags/badges a user can have (https://discord.com/developers/docs/resources/user#user-object-user-flags) type UserFlags int // All UserFlags -//goland:noinspection GoUnusedConst const ( UserFlagDiscordEmployee UserFlags = 1 << iota UserFlagPartneredServerOwner @@ -47,7 +52,7 @@ type User struct { } func (u User) String() string { - return userMention(u.ID) + return UserMention(u.ID) } func (u User) Mention() string { @@ -55,7 +60,36 @@ func (u User) Mention() string { } func (u User) Tag() string { - return userTag(u.Username, u.Discriminator) + return UserTag(u.Username, u.Discriminator) +} + +func (u User) EffectiveAvatarURL(opts ...CDNOpt) string { + if u.Avatar == nil { + return u.DefaultAvatarURL(opts...) + } + if avatar := u.AvatarURL(opts...); avatar != nil { + return *avatar + } + return "" +} + +func (u User) AvatarURL(opts ...CDNOpt) *string { + return formatAssetURL(route.UserAvatar, opts, u.ID, u.Avatar) +} + +func (u User) DefaultAvatarURL(opts ...CDNOpt) string { + discrim, err := strconv.Atoi(u.Discriminator) + if err != nil { + return "" + } + if avatar := formatAssetURL(route.DefaultUserAvatar, opts, discrim%5); avatar != nil { + return *avatar + } + return "" +} + +func (u User) BannerURL(opts ...CDNOpt) *string { + return formatAssetURL(route.UserBanner, opts, u.ID, u.Avatar) } // OAuth2User represents a full User returned by the oauth2 endpoints @@ -76,7 +110,6 @@ type OAuth2User struct { type PremiumType int // All PremiumType(s) -//goland:noinspection GoUnusedConst const ( PremiumTypeNone PremiumType = iota PremiumTypeNitroClassic @@ -85,6 +118,6 @@ const ( // SelfUserUpdate is the payload used to update the OAuth2User type SelfUserUpdate struct { - Username string `json:"username"` - Avatar *NullIcon `json:"avatar"` + Username string `json:"username"` + Avatar *json.Nullable[Icon] `json:"avatar"` } diff --git a/discord/util.go b/discord/util.go deleted file mode 100644 index 2d82d261..00000000 --- a/discord/util.go +++ /dev/null @@ -1,24 +0,0 @@ -package discord - -import ( - "strings" - - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" -) - -func FormatAssetURL(cdnRoute *route.CDNRoute, entityId snowflake.Snowflake, assetId *string, size int) *string { - if assetId == nil { - return nil - } - format := route.PNG - if strings.HasPrefix(*assetId, "a_") { - format = route.GIF - } - compiledRoute, err := cdnRoute.Compile(nil, format, size, entityId, *assetId) - if err != nil { - return nil - } - url := compiledRoute.URL() - return &url -} diff --git a/discord/voice_region.go b/discord/voice_region.go index 160c57da..6be5f8f3 100644 --- a/discord/voice_region.go +++ b/discord/voice_region.go @@ -1,6 +1,6 @@ package discord -import "github.com/DisgoOrg/snowflake" +import "github.com/disgoorg/snowflake" // VoiceRegion (https://discord.com/developers/docs/resources/voice#voice-region-object) type VoiceRegion struct { diff --git a/discord/voice_server_update.go b/discord/voice_server_update.go index 9f1ee88c..680579a9 100644 --- a/discord/voice_server_update.go +++ b/discord/voice_server_update.go @@ -1,6 +1,6 @@ package discord -import "github.com/DisgoOrg/snowflake" +import "github.com/disgoorg/snowflake" type VoiceServerUpdate struct { Token string `json:"token"` diff --git a/discord/voice_state.go b/discord/voice_state.go index 2bd6959e..cbd76625 100644 --- a/discord/voice_state.go +++ b/discord/voice_state.go @@ -1,6 +1,9 @@ package discord -import "github.com/DisgoOrg/snowflake" +import ( + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/snowflake" +) // VoiceState from Discord type VoiceState struct { @@ -20,7 +23,7 @@ type VoiceState struct { } type UserVoiceStateUpdate struct { - ChannelID snowflake.Snowflake `json:"channel_id"` - Suppress *bool `json:"suppress,omitempty"` - RequestToSpeakTimestamp *NullTime `json:"request_to_speak_timestamp,omitempty"` + ChannelID snowflake.Snowflake `json:"channel_id"` + Suppress *bool `json:"suppress,omitempty"` + RequestToSpeakTimestamp *json.Nullable[Time] `json:"request_to_speak_timestamp,omitempty"` } diff --git a/discord/webhook.go b/discord/webhook.go index f6f5e247..3f9503fd 100644 --- a/discord/webhook.go +++ b/discord/webhook.go @@ -3,15 +3,15 @@ package discord import ( "fmt" - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) // WebhookType (https: //discord.com/developers/docs/resources/webhook#webhook-object-webhook-types) type WebhookType int // All WebhookType(s) -//goland:noinspection GoUnusedConst const ( WebhookTypeIncoming WebhookType = iota + 1 WebhookTypeChannelFollower @@ -23,6 +23,9 @@ type Webhook interface { json.Marshaler Type() WebhookType ID() snowflake.Snowflake + Name() string + Avatar() *string + AvatarURL(opts ...CDNOpt) *string webhook() } @@ -75,9 +78,9 @@ func (w *UnmarshalWebhook) UnmarshalJSON(data []byte) error { var _ Webhook = (*IncomingWebhook)(nil) type IncomingWebhook struct { - WebhookID snowflake.Snowflake `json:"id"` - Name string `json:"name"` - Avatar *string `json:"avatar"` + id snowflake.Snowflake + name string + avatar *string ChannelID snowflake.Snowflake `json:"channel_id"` GuildID snowflake.Snowflake `json:"guild_id"` Token string `json:"token"` @@ -85,6 +88,24 @@ type IncomingWebhook struct { User User `json:"user"` } +func (w *IncomingWebhook) UnmarshalJSON(data []byte) error { + type incomingWebhook IncomingWebhook + var v struct { + ID snowflake.Snowflake `json:"id"` + Name string `json:"name"` + Avatar *string `json:"avatar"` + incomingWebhook + } + if err := json.Unmarshal(data, &v); err != nil { + return err + } + *w = IncomingWebhook(v.incomingWebhook) + w.id = v.ID + w.name = v.Name + w.avatar = v.Avatar + return nil +} + func (w IncomingWebhook) MarshalJSON() ([]byte, error) { type incomingWebhook IncomingWebhook return json.Marshal(struct { @@ -100,18 +121,54 @@ func (IncomingWebhook) Type() WebhookType { return WebhookTypeIncoming } -func (IncomingWebhook) webhook() {} - func (w IncomingWebhook) ID() snowflake.Snowflake { - return w.WebhookID + return w.id +} + +func (w IncomingWebhook) Name() string { + return w.name +} + +func (w IncomingWebhook) Avatar() *string { + return w.avatar +} + +func (w IncomingWebhook) EffectiveAvatarURL(opts ...CDNOpt) string { + if w.Avatar() == nil { + return w.DefaultAvatarURL(opts...) + } + if avatar := w.AvatarURL(opts...); avatar != nil { + return *avatar + } + return "" +} + +func (w IncomingWebhook) AvatarURL(opts ...CDNOpt) *string { + return formatAssetURL(route.UserAvatar, opts, w.ID(), w.Avatar()) } +func (w IncomingWebhook) DefaultAvatarURL(opts ...CDNOpt) string { + if avatar := formatAssetURL(route.DefaultUserAvatar, opts, 0); avatar != nil { + return *avatar + } + return "" +} + +func (w IncomingWebhook) URL() string { + if compiledRoute, err := route.WebhookURL.Compile(nil, w.ID(), w.Token); err == nil { + return compiledRoute.URL() + } + return "" +} + +func (IncomingWebhook) webhook() {} + var _ Webhook = (*ChannelFollowerWebhook)(nil) type ChannelFollowerWebhook struct { - WebhookID snowflake.Snowflake `json:"id"` - Name string `json:"name"` - Avatar *string `json:"avatar"` + id snowflake.Snowflake + name string + avatar *string ChannelID snowflake.Snowflake `json:"channel_id"` GuildID snowflake.Snowflake `json:"guild_id"` SourceGuild WebhookSourceGuild `json:"source_guild"` @@ -119,6 +176,24 @@ type ChannelFollowerWebhook struct { User User `json:"user"` } +func (w *ChannelFollowerWebhook) UnmarshalJSON(data []byte) error { + type channelFollowerWebhook ChannelFollowerWebhook + var v struct { + ID snowflake.Snowflake `json:"id"` + Name string `json:"name"` + Avatar *string `json:"avatar"` + channelFollowerWebhook + } + if err := json.Unmarshal(data, &v); err != nil { + return err + } + *w = ChannelFollowerWebhook(v.channelFollowerWebhook) + w.id = v.ID + w.name = v.Name + w.avatar = v.Avatar + return nil +} + func (w ChannelFollowerWebhook) MarshalJSON() ([]byte, error) { type channelFollowerWebhook ChannelFollowerWebhook return json.Marshal(struct { @@ -134,19 +209,65 @@ func (ChannelFollowerWebhook) Type() WebhookType { return WebhookTypeChannelFollower } -func (ChannelFollowerWebhook) webhook() {} - func (w ChannelFollowerWebhook) ID() snowflake.Snowflake { - return w.WebhookID + return w.id +} + +func (w ChannelFollowerWebhook) Name() string { + return w.name +} + +func (w ChannelFollowerWebhook) Avatar() *string { + return w.avatar +} + +func (w ChannelFollowerWebhook) EffectiveAvatarURL(opts ...CDNOpt) string { + if w.Avatar() == nil { + return w.DefaultAvatarURL(opts...) + } + if avatar := w.AvatarURL(opts...); avatar != nil { + return *avatar + } + return "" +} + +func (w ChannelFollowerWebhook) AvatarURL(opts ...CDNOpt) *string { + return formatAssetURL(route.UserAvatar, opts, w.ID(), w.Avatar()) +} + +func (w ChannelFollowerWebhook) DefaultAvatarURL(opts ...CDNOpt) string { + if avatar := formatAssetURL(route.DefaultUserAvatar, opts, 0); avatar != nil { + return *avatar + } + return "" } +func (ChannelFollowerWebhook) webhook() {} + var _ Webhook = (*ApplicationWebhook)(nil) type ApplicationWebhook struct { - WebhookID snowflake.Snowflake `json:"id"` - Name string `json:"name"` - Avatar *string `json:"avatar"` - ApplicationID snowflake.Snowflake `json:"application_id"` + id snowflake.Snowflake + name string + avatar *string + ApplicationID snowflake.Snowflake +} + +func (w *ApplicationWebhook) UnmarshalJSON(data []byte) error { + var v struct { + ID snowflake.Snowflake `json:"id"` + Name string `json:"name"` + Avatar *string `json:"avatar"` + ApplicationID snowflake.Snowflake `json:"application_id"` + } + if err := json.Unmarshal(data, &v); err != nil { + return err + } + w.id = v.ID + w.name = v.Name + w.avatar = v.Avatar + w.ApplicationID = v.ApplicationID + return nil } func (w ApplicationWebhook) MarshalJSON() ([]byte, error) { @@ -164,16 +285,45 @@ func (ApplicationWebhook) Type() WebhookType { return WebhookTypeApplication } -func (ApplicationWebhook) webhook() {} - func (w ApplicationWebhook) ID() snowflake.Snowflake { - return w.WebhookID + return w.id +} + +func (w ApplicationWebhook) Name() string { + return w.name +} + +func (w ApplicationWebhook) Avatar() *string { + return w.avatar +} + +func (w ApplicationWebhook) EffectiveAvatarURL(opts ...CDNOpt) string { + if w.Avatar() == nil { + return w.DefaultAvatarURL(opts...) + } + if avatar := w.AvatarURL(opts...); avatar != nil { + return *avatar + } + return "" } +func (w ApplicationWebhook) AvatarURL(opts ...CDNOpt) *string { + return formatAssetURL(route.UserAvatar, opts, w.ID(), w.Avatar()) +} + +func (w ApplicationWebhook) DefaultAvatarURL(opts ...CDNOpt) string { + if avatar := formatAssetURL(route.DefaultUserAvatar, opts, 0); avatar != nil { + return *avatar + } + return "" +} + +func (ApplicationWebhook) webhook() {} + type WebhookSourceGuild struct { - ID snowflake.Snowflake `json:"id"` - Name string `json:"name"` - Icon *string `json:"icon"` + ID snowflake.Snowflake `json:"id"` + Name string `json:"name"` + Icon *json.Nullable[Icon] `json:"icon"` } type WebhookSourceChannel struct { @@ -190,12 +340,12 @@ type WebhookCreate struct { // WebhookUpdate is used to update a Webhook type WebhookUpdate struct { Name *string `json:"name,omitempty"` - Avatar *NullIcon `json:"avatar,omitempty"` + Avatar *json.Nullable[Icon] `json:"avatar,omitempty"` ChannelID *snowflake.Snowflake `json:"channel_id"` } // WebhookUpdateWithToken is used to update a Webhook with the token type WebhookUpdateWithToken struct { - Name *string `json:"name,omitempty"` - Avatar *NullIcon `json:"avatar,omitempty"` + Name *string `json:"name,omitempty"` + Avatar *string `json:"avatar,omitempty"` } diff --git a/discord/webhook_message_create.go b/discord/webhook_message_create.go index eeb79580..3fd4a4ed 100644 --- a/discord/webhook_message_create.go +++ b/discord/webhook_message_create.go @@ -7,13 +7,15 @@ type WebhookMessageCreate struct { TTS bool `json:"tts,omitempty"` Embeds []Embed `json:"embeds,omitempty"` Components []ContainerComponent `json:"components,omitempty"` + Attachments []AttachmentCreate `json:"attachments,omitempty"` Files []*File `json:"-"` AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"` } // ToBody returns the MessageCreate ready for body -func (m WebhookMessageCreate) ToBody() (interface{}, error) { +func (m WebhookMessageCreate) ToBody() (any, error) { if len(m.Files) > 0 { + m.Attachments = parseAttachments(m.Files) return PayloadWithFiles(m, m.Files...) } return m, nil diff --git a/discord/webhook_message_create_builder.go b/discord/webhook_message_create_builder.go index 311f9b5f..f2d7e348 100644 --- a/discord/webhook_message_create_builder.go +++ b/discord/webhook_message_create_builder.go @@ -11,7 +11,6 @@ type WebhookMessageCreateBuilder struct { } // NewWebhookMessageCreateBuilder creates a new WebhookMessageCreateBuilder to be built later -//goland:noinspection GoUnusedExportedFunction func NewWebhookMessageCreateBuilder() *WebhookMessageCreateBuilder { return &WebhookMessageCreateBuilder{ WebhookMessageCreate: WebhookMessageCreate{ @@ -27,7 +26,7 @@ func (b *WebhookMessageCreateBuilder) SetContent(content string) *WebhookMessage } // SetContentf sets content of the Message -func (b *WebhookMessageCreateBuilder) SetContentf(content string, a ...interface{}) *WebhookMessageCreateBuilder { +func (b *WebhookMessageCreateBuilder) SetContentf(content string, a ...any) *WebhookMessageCreateBuilder { return b.SetContent(fmt.Sprintf(content, a...)) } @@ -142,8 +141,8 @@ func (b *WebhookMessageCreateBuilder) AddFiles(files ...*File) *WebhookMessageCr } // AddFile adds a discord.File to the discord.MessageCreate -func (b *WebhookMessageCreateBuilder) AddFile(name string, reader io.Reader, flags ...FileFlags) *WebhookMessageCreateBuilder { - b.Files = append(b.Files, NewFile(name, reader, flags...)) +func (b *WebhookMessageCreateBuilder) AddFile(name string, description string, reader io.Reader, flags ...FileFlags) *WebhookMessageCreateBuilder { + b.Files = append(b.Files, NewFile(name, description, reader, flags...)) return b } diff --git a/discord/webhook_message_update.go b/discord/webhook_message_update.go index 719bd281..c2733f99 100644 --- a/discord/webhook_message_update.go +++ b/discord/webhook_message_update.go @@ -5,14 +5,20 @@ type WebhookMessageUpdate struct { Content *string `json:"content,omitempty"` Embeds *[]Embed `json:"embeds,omitempty"` Components *[]ContainerComponent `json:"components,omitempty"` - Attachments *[]Attachment `json:"attachments,omitempty"` + Attachments *[]AttachmentUpdate `json:"attachments,omitempty"` Files []*File `json:"-"` AllowedMentions *AllowedMentions `json:"allowed_mentions,omitempty"` } // ToBody returns the WebhookMessageUpdate ready for body -func (m WebhookMessageUpdate) ToBody() (interface{}, error) { +func (m WebhookMessageUpdate) ToBody() (any, error) { if len(m.Files) > 0 { + for _, attachmentCreate := range parseAttachments(m.Files) { + if m.Attachments == nil { + m.Attachments = new([]AttachmentUpdate) + } + *m.Attachments = append(*m.Attachments, attachmentCreate) + } return PayloadWithFiles(m, m.Files...) } return m, nil diff --git a/discord/webhook_message_update_builder.go b/discord/webhook_message_update_builder.go index 78caff06..863baee5 100644 --- a/discord/webhook_message_update_builder.go +++ b/discord/webhook_message_update_builder.go @@ -4,7 +4,7 @@ import ( "fmt" "io" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/snowflake" ) // WebhookMessageUpdateBuilder helper to build MessageUpdate easier @@ -13,7 +13,6 @@ type WebhookMessageUpdateBuilder struct { } // NewWebhookMessageUpdateBuilder creates a new WebhookMessageUpdateBuilder to be built later -//goland:noinspection GoUnusedExportedFunction func NewWebhookMessageUpdateBuilder() *WebhookMessageUpdateBuilder { return &WebhookMessageUpdateBuilder{ WebhookMessageUpdate: WebhookMessageUpdate{ @@ -29,7 +28,7 @@ func (b *WebhookMessageUpdateBuilder) SetContent(content string) *WebhookMessage } // SetContentf sets content of the Message -func (b *WebhookMessageUpdateBuilder) SetContentf(content string, a ...interface{}) *WebhookMessageUpdateBuilder { +func (b *WebhookMessageUpdateBuilder) SetContentf(content string, a ...any) *WebhookMessageUpdateBuilder { return b.SetContent(fmt.Sprintf(content, a...)) } @@ -160,8 +159,8 @@ func (b *WebhookMessageUpdateBuilder) AddFiles(files ...*File) *WebhookMessageUp } // AddFile adds a new discord.File to the discord.MessageUpdate -func (b *WebhookMessageUpdateBuilder) AddFile(name string, reader io.Reader, flags ...FileFlags) *WebhookMessageUpdateBuilder { - b.Files = append(b.Files, NewFile(name, reader, flags...)) +func (b *WebhookMessageUpdateBuilder) AddFile(name string, description string, reader io.Reader, flags ...FileFlags) *WebhookMessageUpdateBuilder { + b.Files = append(b.Files, NewFile(name, description, reader, flags...)) return b } @@ -182,19 +181,21 @@ func (b *WebhookMessageUpdateBuilder) RemoveFile(i int) *WebhookMessageUpdateBui // RetainAttachments removes all Attachment(s) from this Message except the ones provided func (b *WebhookMessageUpdateBuilder) RetainAttachments(attachments ...Attachment) *WebhookMessageUpdateBuilder { if b.Attachments == nil { - b.Attachments = new([]Attachment) + b.Attachments = new([]AttachmentUpdate) + } + for _, attachment := range attachments { + *b.Attachments = append(*b.Attachments, AttachmentKeep{ID: attachment.ID}) } - *b.Attachments = append(*b.Attachments, attachments...) return b } // RetainAttachmentsByID removes all Attachment(s) from this Message except the ones provided func (b *WebhookMessageUpdateBuilder) RetainAttachmentsByID(attachmentIDs ...snowflake.Snowflake) *WebhookMessageUpdateBuilder { if b.Attachments == nil { - b.Attachments = new([]Attachment) + b.Attachments = new([]AttachmentUpdate) } for _, attachmentID := range attachmentIDs { - *b.Attachments = append(*b.Attachments, Attachment{ID: attachmentID}) + *b.Attachments = append(*b.Attachments, AttachmentKeep{ID: attachmentID}) } return b } diff --git a/disgo.go b/disgo.go index bae4876b..c30466f5 100644 --- a/disgo.go +++ b/disgo.go @@ -1,25 +1,65 @@ package disgo import ( - _ "github.com/DisgoOrg/disgo/core" - _ "github.com/DisgoOrg/disgo/core/bot" - _ "github.com/DisgoOrg/disgo/core/collectors" - _ "github.com/DisgoOrg/disgo/core/events" - _ "github.com/DisgoOrg/disgo/core/handlers" - _ "github.com/DisgoOrg/disgo/discord" - _ "github.com/DisgoOrg/disgo/gateway" - _ "github.com/DisgoOrg/disgo/gateway/grate" - _ "github.com/DisgoOrg/disgo/gateway/sharding" - _ "github.com/DisgoOrg/disgo/gateway/sharding/srate" - _ "github.com/DisgoOrg/disgo/httpserver" - _ "github.com/DisgoOrg/disgo/info" - _ "github.com/DisgoOrg/disgo/internal/insecurerandstr" - _ "github.com/DisgoOrg/disgo/internal/rwsync" - _ "github.com/DisgoOrg/disgo/internal/tokenhelper" - _ "github.com/DisgoOrg/disgo/json" - _ "github.com/DisgoOrg/disgo/oauth2" - _ "github.com/DisgoOrg/disgo/rest" - _ "github.com/DisgoOrg/disgo/rest/route" - _ "github.com/DisgoOrg/disgo/rest/rrate" - _ "github.com/DisgoOrg/disgo/webhook" + "runtime" + "runtime/debug" + "strings" + + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/disgo/gateway/handlers" + "github.com/disgoorg/disgo/httpserver" +) + +const ( + Name = "disgo" + GitHub = "https://github.com/disgoorg/" + Name +) + +var ( + Version = getVersion() + OS = getOS() ) + +func getVersion() string { + bi, ok := debug.ReadBuildInfo() + if ok { + for _, dep := range bi.Deps { + if strings.Contains(GitHub, dep.Path) { + return dep.Version + } + } + } + return "unknown" +} + +func getOS() string { + os := runtime.GOOS + if strings.HasPrefix(os, "windows") { + return "windows" + } + if strings.HasPrefix(os, "darwin") { + return "darwin" + } + return "linux" +} + +// New creates a new core.Client instance with the provided bot token & ConfigOpt(s) +func New(token string, opts ...bot.ConfigOpt) (bot.Client, error) { + config := bot.DefaultConfig(handlers.GetGatewayHandlers(), handlers.GetHTTPServerHandler()) + config.Apply(opts) + + return bot.BuildClient(token, + *config, + func(client bot.Client) gateway.EventHandlerFunc { + return handlers.DefaultGatewayEventHandler(client) + }, + func(client bot.Client) httpserver.EventHandlerFunc { + return handlers.DefaultHTTPServerEventHandler(client) + }, + OS, + Name, + GitHub, + Version, + ) +} diff --git a/events/dm_channel_events.go b/events/dm_channel_events.go new file mode 100644 index 00000000..40dce14b --- /dev/null +++ b/events/dm_channel_events.go @@ -0,0 +1,54 @@ +package events + +import ( + "time" + + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +// GenericDMChannelEvent is called upon receiving DMChannelCreateEvent, DMChannelUpdateEvent, DMChannelDeleteEvent or DMUserTypingStartEvent +type GenericDMChannelEvent struct { + *GenericEvent + Channel discord.DMChannel + ChannelID snowflake.Snowflake +} + +// DMChannelCreateEvent indicates that a new discord.DMChannel got created +type DMChannelCreateEvent struct { + *GenericDMChannelEvent +} + +// DMChannelUpdateEvent indicates that a discord.DMChannel got updated +type DMChannelUpdateEvent struct { + *GenericDMChannelEvent + OldChannel discord.DMChannel +} + +// DMChannelDeleteEvent indicates that a discord.DMChannel got deleted +type DMChannelDeleteEvent struct { + *GenericDMChannelEvent +} + +type DMChannelPinsUpdateEvent struct { + *GenericEvent + ChannelID snowflake.Snowflake + NewLastPinTimestamp *discord.Time + OldLastPinTimestamp *discord.Time +} + +// DMUserTypingStartEvent indicates that a discord.User started typing in a discord.DMChannel(requires discord.GatewayIntentDirectMessageTyping) +type DMUserTypingStartEvent struct { + *GenericEvent + ChannelID snowflake.Snowflake + UserID snowflake.Snowflake + Timestamp time.Time +} + +// Channel returns the discord.DMChannel the DMUserTypingStartEvent happened in +func (e DMUserTypingStartEvent) Channel() (discord.DMChannel, bool) { + if channel, ok := e.Client().Caches().Channels().Get(e.ChannelID); ok { + return channel.(discord.DMChannel), false + } + return discord.DMChannel{}, true +} diff --git a/core/events/events_dm_message_event.go b/events/dm_message_event_events.go similarity index 50% rename from core/events/events_dm_message_event.go rename to events/dm_message_event_events.go index b4ec7c76..de99a92e 100644 --- a/core/events/events_dm_message_event.go +++ b/events/dm_message_event_events.go @@ -1,38 +1,38 @@ package events import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" ) // GenericDMMessageEvent is called upon receiving DMMessageCreateEvent, DMMessageUpdateEvent, DMMessageDeleteEvent, GenericDMMessageReactionEvent, DMMessageReactionAddEvent, DMMessageReactionRemoveEvent, DMMessageReactionRemoveEmojiEvent or DMMessageReactionRemoveAllEvent (requires discord.GatewayIntentsDirectMessage) type GenericDMMessageEvent struct { *GenericEvent MessageID snowflake.Snowflake - Message *core.Message + Message discord.Message ChannelID snowflake.Snowflake } // Channel returns the Channel the GenericDMMessageEvent happened in -func (e GenericDMMessageEvent) Channel() *core.DMChannel { - if ch := e.Bot().Caches.Channels().Get(e.ChannelID); ch != nil { - return ch.(*core.DMChannel) +func (e GenericDMMessageEvent) Channel() (discord.DMChannel, bool) { + if ch, ok := e.Client().Caches().Channels().Get(e.ChannelID); ok { + return ch.(discord.DMChannel), true } - return nil + return discord.DMChannel{}, false } -// DMMessageCreateEvent is called upon receiving a core.Message in a Channel (requires discord.GatewayIntentsDirectMessage) +// DMMessageCreateEvent is called upon receiving a discord.Message in a Channel (requires discord.GatewayIntentsDirectMessage) type DMMessageCreateEvent struct { *GenericDMMessageEvent } -// DMMessageUpdateEvent is called upon editing a core.Message in a Channel (requires discord.GatewayIntentsDirectMessage) +// DMMessageUpdateEvent is called upon editing a discord.Message in a Channel (requires discord.GatewayIntentsDirectMessage) type DMMessageUpdateEvent struct { *GenericDMMessageEvent - OldMessage *core.Message + OldMessage discord.Message } -// DMMessageDeleteEvent is called upon deleting a core.Message in a Channel (requires discord.GatewayIntentsDirectMessage) +// DMMessageDeleteEvent is called upon deleting a discord.Message in a Channel (requires discord.GatewayIntentsDirectMessage) type DMMessageDeleteEvent struct { *GenericDMMessageEvent } diff --git a/core/events/events_dm_message_reaction.go b/events/dm_message_reaction_events.go similarity index 53% rename from core/events/events_dm_message_reaction.go rename to events/dm_message_reaction_events.go index b566dc40..77b14b54 100644 --- a/core/events/events_dm_message_reaction.go +++ b/events/dm_message_reaction_events.go @@ -1,9 +1,8 @@ package events import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" ) // GenericDMMessageReactionEvent is called upon receiving DMMessageReactionAddEvent or DMMessageReactionRemoveEvent (requires the discord.GatewayIntentDirectMessageReactions) @@ -15,23 +14,17 @@ type GenericDMMessageReactionEvent struct { Emoji discord.ReactionEmoji } -// User returns the User who owns the discord.MessageReaction. -// This will only check cached users! -func (e *GenericDMMessageReactionEvent) User() *core.User { - return e.Bot().Caches.Users().Get(e.UserID) -} - -// DMMessageReactionAddEvent indicates that a core.User added a discord.MessageReaction to a core.Message in a Channel (requires the discord.GatewayIntentDirectMessageReactions) +// DMMessageReactionAddEvent indicates that a discord.User added a discord.MessageReaction to a discord.Message in a Channel (requires the discord.GatewayIntentDirectMessageReactions) type DMMessageReactionAddEvent struct { *GenericDMMessageReactionEvent } -// DMMessageReactionRemoveEvent indicates that a core.User removed a discord.MessageReaction from a core.Message in a Channel (requires the discord.GatewayIntentDirectMessageReactions) +// DMMessageReactionRemoveEvent indicates that a discord.User removed a discord.MessageReaction from a discord.Message in a Channel (requires the discord.GatewayIntentDirectMessageReactions) type DMMessageReactionRemoveEvent struct { *GenericDMMessageReactionEvent } -// DMMessageReactionRemoveEmojiEvent indicates someone removed all discord.MessageReaction(s) of a specific core.Emoji from a core.Message in a Channel (requires the discord.GatewayIntentDirectMessageReactions) +// DMMessageReactionRemoveEmojiEvent indicates someone removed all discord.MessageReaction(s) of a specific discord.Emoji from a discord.Message in a Channel (requires the discord.GatewayIntentDirectMessageReactions) type DMMessageReactionRemoveEmojiEvent struct { *GenericEvent ChannelID snowflake.Snowflake @@ -39,7 +32,7 @@ type DMMessageReactionRemoveEmojiEvent struct { Emoji discord.ReactionEmoji } -// DMMessageReactionRemoveAllEvent indicates someone removed all discord.MessageReaction(s) from a core.Message in a Channel (requires the discord.GatewayIntentDirectMessageReactions) +// DMMessageReactionRemoveAllEvent indicates someone removed all discord.MessageReaction(s) from a discord.Message in a Channel (requires the discord.GatewayIntentDirectMessageReactions) type DMMessageReactionRemoveAllEvent struct { *GenericEvent ChannelID snowflake.Snowflake diff --git a/core/events/events_gateway_status.go b/events/gateway_status_events.go similarity index 92% rename from core/events/events_gateway_status.go rename to events/gateway_status_events.go index 57541903..42767344 100644 --- a/core/events/events_gateway_status.go +++ b/events/gateway_status_events.go @@ -1,7 +1,7 @@ package events import ( - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/discord" ) // ReadyEvent indicates we received the ReadyEvent from the gateway.Gateway diff --git a/events/generic_event.go b/events/generic_event.go new file mode 100644 index 00000000..2bfbf8c3 --- /dev/null +++ b/events/generic_event.go @@ -0,0 +1,25 @@ +package events + +import ( + "github.com/disgoorg/disgo/bot" +) + +// NewGenericEvent constructs a new GenericEvent with the provided Client instance +func NewGenericEvent(client bot.Client, sequenceNumber int) *GenericEvent { + return &GenericEvent{client: client, sequenceNumber: sequenceNumber} +} + +// GenericEvent the base event structure +type GenericEvent struct { + client bot.Client + sequenceNumber int +} + +func (e GenericEvent) Client() bot.Client { + return e.client +} + +// SequenceNumber returns the sequence number of the gateway event +func (e GenericEvent) SequenceNumber() int { + return e.sequenceNumber +} diff --git a/core/events/events_guild_channel.go b/events/guild_channel_events.go similarity index 71% rename from core/events/events_guild_channel.go rename to events/guild_channel_events.go index 979d6710..06c3fe7c 100644 --- a/core/events/events_guild_channel.go +++ b/events/guild_channel_events.go @@ -1,37 +1,36 @@ package events import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" ) // GenericGuildChannelEvent is called upon receiving GuildChannelCreateEvent, GuildChannelUpdateEvent or GuildChannelDeleteEvent type GenericGuildChannelEvent struct { *GenericEvent ChannelID snowflake.Snowflake - Channel core.GuildChannel + Channel discord.GuildChannel GuildID snowflake.Snowflake } -// Guild returns the core.Guild the event happened in. +// Guild returns the discord.Guild the event happened in. // This will only check cached guilds! -func (e GenericGuildChannelEvent) Guild() *core.Guild { - return e.Bot().Caches.Guilds().Get(e.GuildID) +func (e GenericGuildChannelEvent) Guild() (discord.Guild, bool) { + return e.Client().Caches().Guilds().Get(e.GuildID) } -// GuildChannelCreateEvent indicates that a new Channel got created in a core.Guild +// GuildChannelCreateEvent indicates that a new Channel got created in a discord.Guild type GuildChannelCreateEvent struct { *GenericGuildChannelEvent } -// GuildChannelUpdateEvent indicates that a Channel got updated in a core.Guild +// GuildChannelUpdateEvent indicates that a Channel got updated in a discord.Guild type GuildChannelUpdateEvent struct { *GenericGuildChannelEvent - OldChannel core.GuildChannel + OldChannel discord.GuildChannel } -// GuildChannelDeleteEvent indicates that a Channel got deleted in a core.Guild +// GuildChannelDeleteEvent indicates that a Channel got deleted in a discord.Guild type GuildChannelDeleteEvent struct { *GenericGuildChannelEvent } diff --git a/events/guild_emoji_events.go b/events/guild_emoji_events.go new file mode 100644 index 00000000..42ba4b07 --- /dev/null +++ b/events/guild_emoji_events.go @@ -0,0 +1,35 @@ +package events + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +type EmojisUpdateEvent struct { + *GenericEvent + GuildID snowflake.Snowflake + Emojis []discord.Emoji +} + +// GenericEmojiEvent is called upon receiving EmojiCreateEvent, EmojiUpdateEvent or EmojiDeleteEvent (requires discord.GatewayIntentGuildEmojisAndStickers) +type GenericEmojiEvent struct { + *GenericEvent + GuildID snowflake.Snowflake + Emoji discord.Emoji +} + +// EmojiCreateEvent indicates that a new discord.Emoji got created in a discord.Guild (requires discord.GatewayIntentGuildEmojisAndStickers) +type EmojiCreateEvent struct { + *GenericEmojiEvent +} + +// EmojiUpdateEvent indicates that a discord.Emoji got updated in a discord.Guild (requires discord.GatewayIntentGuildEmojisAndStickers) +type EmojiUpdateEvent struct { + *GenericEmojiEvent + OldEmoji discord.Emoji +} + +// EmojiDeleteEvent indicates that a discord.Emoji got deleted in a discord.Guild (requires discord.GatewayIntentGuildEmojisAndStickers) +type EmojiDeleteEvent struct { + *GenericEmojiEvent +} diff --git a/events/guild_events.go b/events/guild_events.go new file mode 100644 index 00000000..8a803cfc --- /dev/null +++ b/events/guild_events.go @@ -0,0 +1,64 @@ +package events + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +// GenericGuildEvent is called upon receiving GuildUpdateEvent, GuildAvailableEvent, GuildUnavailableEvent, GuildJoinEvent, GuildLeaveEvent, GuildReadyEvent, GuildBanEvent, GuildUnbanEvent +type GenericGuildEvent struct { + *GenericEvent + GuildID snowflake.Snowflake + Guild discord.Guild +} + +// GuildUpdateEvent is called upon receiving discord.Guild updates +type GuildUpdateEvent struct { + *GenericGuildEvent + OldGuild discord.Guild +} + +// GuildAvailableEvent is called when an unavailable discord.Guild becomes available +type GuildAvailableEvent struct { + *GenericGuildEvent +} + +// GuildUnavailableEvent is called when an available discord.Guild becomes unavailable +type GuildUnavailableEvent struct { + *GenericGuildEvent +} + +// GuildJoinEvent is called when the bot joins a discord.Guild +type GuildJoinEvent struct { + *GenericGuildEvent +} + +// GuildLeaveEvent is called when the bot leaves a discord.Guild +type GuildLeaveEvent struct { + *GenericGuildEvent +} + +// GuildReadyEvent is called when a discord.Guild becomes loaded for the first time +type GuildReadyEvent struct { + *GenericGuildEvent +} + +// GuildsReadyEvent is called when all discord.Guild(s) are loaded after logging in +type GuildsReadyEvent struct { + *GenericEvent + ShardID int +} + +// GuildBanEvent is called when a discord.Member/discord.User is banned from the discord.Guild +type GuildBanEvent struct { + *GenericEvent + GuildID snowflake.Snowflake + User discord.User +} + +// GuildUnbanEvent is called when a discord.Member/discord.User is unbanned from the discord.Guild +type GuildUnbanEvent struct { + *GenericEvent + GuildID snowflake.Snowflake + User discord.User +} diff --git a/core/events/events_integration.go b/events/guild_integration_events.go similarity index 79% rename from core/events/events_integration.go rename to events/guild_integration_events.go index 0df5e046..9c1a87c2 100644 --- a/core/events/events_integration.go +++ b/events/guild_integration_events.go @@ -1,20 +1,20 @@ package events import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" ) type GenericIntegrationEvent struct { *GenericEvent GuildID snowflake.Snowflake - Integration core.Integration + Integration discord.Integration } // Guild returns the Guild this Integration was created in. // This will only check cached guilds! -func (e *GenericIntegrationEvent) Guild() *core.Guild { - return e.Bot().Caches.Guilds().Get(e.GuildID) +func (e *GenericIntegrationEvent) Guild() (discord.Guild, bool) { + return e.Client().Caches().Guilds().Get(e.GuildID) } // IntegrationCreateEvent indicates that a new Integration was created in a Guild diff --git a/events/guild_invite_events.go b/events/guild_invite_events.go new file mode 100644 index 00000000..d20bc38a --- /dev/null +++ b/events/guild_invite_events.go @@ -0,0 +1,30 @@ +package events + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +// GenericInviteEvent is called upon receiving InviteCreateEvent or InviteDeleteEvent (requires discord.GatewayIntentGuildInvites) +type GenericInviteEvent struct { + *GenericEvent + GuildID *snowflake.Snowflake + ChannelID snowflake.Snowflake + Code string +} + +// Channel returns the Channel the GenericInviteEvent happened in. +func (e GenericInviteEvent) Channel() (discord.GuildChannel, bool) { + return e.Client().Caches().Channels().GetGuildChannel(e.ChannelID) +} + +// InviteCreateEvent is called upon creation of a new discord.Invite (requires discord.GatewayIntentGuildInvites) +type InviteCreateEvent struct { + *GenericInviteEvent + Invite discord.Invite +} + +// InviteDeleteEvent is called upon deletion of a discord.Invite (requires discord.GatewayIntentGuildInvites) +type InviteDeleteEvent struct { + *GenericInviteEvent +} diff --git a/events/guild_member_events.go b/events/guild_member_events.go new file mode 100644 index 00000000..add5c9a2 --- /dev/null +++ b/events/guild_member_events.go @@ -0,0 +1,49 @@ +package events + +import ( + "time" + + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +// GenericGuildMemberEvent generic discord.Member event +type GenericGuildMemberEvent struct { + *GenericEvent + GuildID snowflake.Snowflake + Member discord.Member +} + +// GuildMemberJoinEvent indicates that a discord.Member joined the discord.Guild +type GuildMemberJoinEvent struct { + *GenericGuildMemberEvent +} + +// GuildMemberUpdateEvent indicates that a discord.Member updated +type GuildMemberUpdateEvent struct { + *GenericGuildMemberEvent + OldMember discord.Member +} + +// GuildMemberLeaveEvent indicates that a discord.Member left the discord.Guild +type GuildMemberLeaveEvent struct { + *GenericEvent + GuildID snowflake.Snowflake + User discord.User + Member discord.Member +} + +// GuildMemberTypingStartEvent indicates that a discord.Member started typing in a discord.BaseGuildMessageChannel(requires discord.GatewayIntentGuildMessageTyping) +type GuildMemberTypingStartEvent struct { + *GenericEvent + ChannelID snowflake.Snowflake + UserID snowflake.Snowflake + GuildID snowflake.Snowflake + Timestamp time.Time + Member discord.Member +} + +// Channel returns the discord.BaseGuildMessageChannel the GuildMemberTypingStartEvent happened in +func (e GuildMemberTypingStartEvent) Channel() (discord.GuildMessageChannel, bool) { + return e.Client().Caches().Channels().GetGuildMessageChannel(e.ChannelID) +} diff --git a/events/guild_message_events.go b/events/guild_message_events.go new file mode 100644 index 00000000..4eebe831 --- /dev/null +++ b/events/guild_message_events.go @@ -0,0 +1,42 @@ +package events + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +// GenericGuildMessageEvent is called upon receiving GuildMessageCreateEvent, GuildMessageUpdateEvent or GuildMessageDeleteEvent +type GenericGuildMessageEvent struct { + *GenericEvent + MessageID snowflake.Snowflake + Message discord.Message + ChannelID snowflake.Snowflake + GuildID snowflake.Snowflake +} + +// Guild returns the discord.Guild the GenericGuildMessageEvent happened in. +// This will only check cached guilds! +func (e GenericGuildMessageEvent) Guild() (discord.Guild, bool) { + return e.Client().Caches().Guilds().Get(e.GuildID) +} + +// Channel returns the discord.DMChannel where the GenericGuildMessageEvent happened +func (e GenericGuildMessageEvent) Channel() (discord.GuildMessageChannel, bool) { + return e.Client().Caches().Channels().GetGuildMessageChannel(e.ChannelID) +} + +// GuildMessageCreateEvent is called upon receiving a discord.Message in a Channel +type GuildMessageCreateEvent struct { + *GenericGuildMessageEvent +} + +// GuildMessageUpdateEvent is called upon editing a discord.Message in a Channel +type GuildMessageUpdateEvent struct { + *GenericGuildMessageEvent + OldMessage discord.Message +} + +// GuildMessageDeleteEvent is called upon deleting a discord.Message in a Channel +type GuildMessageDeleteEvent struct { + *GenericGuildMessageEvent +} diff --git a/core/events/events_guild_message_reaction.go b/events/guild_message_reaction_events.go similarity index 53% rename from core/events/events_guild_message_reaction.go rename to events/guild_message_reaction_events.go index 446e1de0..a5884bf9 100644 --- a/core/events/events_guild_message_reaction.go +++ b/events/guild_message_reaction_events.go @@ -1,9 +1,8 @@ package events import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" ) // GenericGuildMessageReactionEvent is called upon receiving GuildMessageReactionAddEvent or GuildMessageReactionRemoveEvent @@ -16,26 +15,22 @@ type GenericGuildMessageReactionEvent struct { Emoji discord.ReactionEmoji } -func (e *GenericGuildMessageReactionEvent) User() *core.User { - return e.Bot().Caches.Users().Get(e.UserID) +func (e *GenericGuildMessageReactionEvent) Member() (discord.Member, bool) { + return e.Client().Caches().Members().Get(e.GuildID, e.UserID) } -func (e *GenericGuildMessageReactionEvent) Member() *core.Member { - return e.Bot().Caches.Members().Get(e.GuildID, e.UserID) -} - -// GuildMessageReactionAddEvent indicates that a core.Member added a discord.ReactionEmoji to a core.Message in a core.GuildMessageChannel(requires the discord.GatewayIntentGuildMessageReactions) +// GuildMessageReactionAddEvent indicates that a discord.Member added a discord.ReactionEmoji to a discord.Message in a discord.GuildMessageChannel(requires the discord.GatewayIntentGuildMessageReactions) type GuildMessageReactionAddEvent struct { *GenericGuildMessageReactionEvent - Member *core.Member + Member discord.Member } -// GuildMessageReactionRemoveEvent indicates that a core.Member removed a discord.MessageReaction from a core.Message in a Channel (requires the discord.GatewayIntentGuildMessageReactions) +// GuildMessageReactionRemoveEvent indicates that a discord.Member removed a discord.MessageReaction from a discord.Message in a Channel (requires the discord.GatewayIntentGuildMessageReactions) type GuildMessageReactionRemoveEvent struct { *GenericGuildMessageReactionEvent } -// GuildMessageReactionRemoveEmojiEvent indicates someone removed all discord.MessageReaction of a specific core.Emoji from a core.Message in a Channel (requires the discord.GatewayIntentGuildMessageReactions) +// GuildMessageReactionRemoveEmojiEvent indicates someone removed all discord.MessageReaction of a specific discord.Emoji from a discord.Message in a Channel (requires the discord.GatewayIntentGuildMessageReactions) type GuildMessageReactionRemoveEmojiEvent struct { *GenericEvent ChannelID snowflake.Snowflake @@ -44,7 +39,7 @@ type GuildMessageReactionRemoveEmojiEvent struct { Emoji discord.ReactionEmoji } -// GuildMessageReactionRemoveAllEvent indicates someone removed all discord.MessageReaction(s) from a core.Message in a Channel (requires the discord.GatewayIntentGuildMessageReactions) +// GuildMessageReactionRemoveAllEvent indicates someone removed all discord.MessageReaction(s) from a discord.Message in a Channel (requires the discord.GatewayIntentGuildMessageReactions) type GuildMessageReactionRemoveAllEvent struct { *GenericEvent ChannelID snowflake.Snowflake diff --git a/events/guild_role_events.go b/events/guild_role_events.go new file mode 100644 index 00000000..96b63af6 --- /dev/null +++ b/events/guild_role_events.go @@ -0,0 +1,30 @@ +package events + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +// GenericRoleEvent generic discord.Role event +type GenericRoleEvent struct { + *GenericEvent + GuildID snowflake.Snowflake + RoleID snowflake.Snowflake + Role discord.Role +} + +// RoleCreateEvent indicates that a discord.Role got created +type RoleCreateEvent struct { + *GenericRoleEvent +} + +// RoleUpdateEvent indicates that a discord.Role got updated +type RoleUpdateEvent struct { + *GenericRoleEvent + OldRole discord.Role +} + +// RoleDeleteEvent indicates that a discord.Role got deleted +type RoleDeleteEvent struct { + *GenericRoleEvent +} diff --git a/core/events/events_guild_scheduled_events.go b/events/guild_scheduled_events_events.go similarity index 60% rename from core/events/events_guild_scheduled_events.go rename to events/guild_scheduled_events_events.go index f9f23040..19673cfd 100644 --- a/core/events/events_guild_scheduled_events.go +++ b/events/guild_scheduled_events_events.go @@ -1,13 +1,13 @@ package events import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" ) type GenericGuildScheduledEventEvent struct { *GenericEvent - GuildScheduledEvent *core.GuildScheduledEvent + GuildScheduledEvent discord.GuildScheduledEvent } type GuildScheduledEventCreateEvent struct { @@ -16,7 +16,7 @@ type GuildScheduledEventCreateEvent struct { type GuildScheduledEventUpdateEvent struct { *GenericGuildScheduledEventEvent - OldGuildScheduledEvent *core.GuildScheduledEvent + OldGuildScheduledEvent discord.GuildScheduledEvent } type GuildScheduledEventDeleteEvent struct { @@ -30,16 +30,12 @@ type GenericGuildScheduledEventUserEvent struct { GuildID snowflake.Snowflake } -func (e *GenericGuildScheduledEventUserEvent) GuildScheduledEvent() *core.GuildScheduledEvent { - return e.bot.Caches.GuildScheduledEvents().Get(e.GuildScheduledEventID) +func (e *GenericGuildScheduledEventUserEvent) GuildScheduledEvent() (discord.GuildScheduledEvent, bool) { + return e.Client().Caches().GuildScheduledEvents().Get(e.GuildID, e.GuildScheduledEventID) } -func (e *GenericGuildScheduledEventUserEvent) User() *core.User { - return e.bot.Caches.Users().Get(e.UserID) -} - -func (e *GenericGuildScheduledEventUserEvent) Member() *core.Member { - return e.bot.Caches.Members().Get(e.GuildID, e.UserID) +func (e *GenericGuildScheduledEventUserEvent) Member() (discord.Member, bool) { + return e.Client().Caches().Members().Get(e.GuildID, e.UserID) } type GuildScheduledEventUserAddEvent struct { diff --git a/core/events/events_stage_instance.go b/events/guild_stage_instance_events.go similarity index 80% rename from core/events/events_stage_instance.go rename to events/guild_stage_instance_events.go index 033b7cd0..d34c619b 100644 --- a/core/events/events_stage_instance.go +++ b/events/guild_stage_instance_events.go @@ -1,15 +1,15 @@ package events import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" ) // GenericStageInstanceEvent generic StageInstance event type GenericStageInstanceEvent struct { *GenericEvent StageInstanceID snowflake.Snowflake - StageInstance *core.StageInstance + StageInstance discord.StageInstance } // StageInstanceCreateEvent indicates that a StageInstance got created @@ -20,7 +20,7 @@ type StageInstanceCreateEvent struct { // StageInstanceUpdateEvent indicates that a StageInstance got updated type StageInstanceUpdateEvent struct { *GenericStageInstanceEvent - OldStageInstance *core.StageInstance + OldStageInstance discord.StageInstance } // StageInstanceDeleteEvent indicates that a StageInstance got deleted diff --git a/events/guild_sticker_events.go b/events/guild_sticker_events.go new file mode 100644 index 00000000..67814a3f --- /dev/null +++ b/events/guild_sticker_events.go @@ -0,0 +1,35 @@ +package events + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +type StickersUpdateEvent struct { + *GenericEvent + GuildID snowflake.Snowflake + Stickers []discord.Sticker +} + +// GenericStickerEvent is called upon receiving StickerCreateEvent, StickerUpdateEvent or StickerDeleteEvent (requires discord.GatewayIntentGuildEmojisAndStickers) +type GenericStickerEvent struct { + *GenericEvent + GuildID snowflake.Snowflake + Sticker discord.Sticker +} + +// StickerCreateEvent indicates that a new discord.Sticker got created in a discord.Guild (requires discord.GatewayIntentGuildEmojisAndStickers) +type StickerCreateEvent struct { + *GenericStickerEvent +} + +// StickerUpdateEvent indicates that a discord.Sticker got updated in a discord.Guild (requires discord.GatewayIntentGuildEmojisAndStickers) +type StickerUpdateEvent struct { + *GenericStickerEvent + OldSticker discord.Sticker +} + +// StickerDeleteEvent indicates that a discord.Sticker got deleted in a discord.Guild (requires discord.GatewayIntentGuildEmojisAndStickers) +type StickerDeleteEvent struct { + *GenericStickerEvent +} diff --git a/core/events/thread_events.go b/events/guild_thread_events.go similarity index 77% rename from core/events/thread_events.go rename to events/guild_thread_events.go index a673efbb..903f2844 100644 --- a/core/events/thread_events.go +++ b/events/guild_thread_events.go @@ -1,13 +1,13 @@ package events import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" ) type GenericThreadEvent struct { *GenericEvent - Thread core.GuildThread + Thread discord.GuildThread ThreadID snowflake.Snowflake GuildID snowflake.Snowflake ParentID snowflake.Snowflake @@ -15,11 +15,12 @@ type GenericThreadEvent struct { type ThreadCreateEvent struct { *GenericThreadEvent + ThreadMember discord.ThreadMember } type ThreadUpdateEvent struct { *GenericThreadEvent - OldThread core.GuildThread + OldThread discord.GuildThread } type ThreadDeleteEvent struct { @@ -39,7 +40,7 @@ type GenericThreadMemberEvent struct { GuildID snowflake.Snowflake ThreadID snowflake.Snowflake ThreadMemberID snowflake.Snowflake - ThreadMember *core.ThreadMember + ThreadMember discord.ThreadMember } type ThreadMemberAddEvent struct { @@ -48,7 +49,7 @@ type ThreadMemberAddEvent struct { type ThreadMemberUpdateEvent struct { *GenericThreadMemberEvent - OldThreadMember *core.ThreadMember + OldThreadMember discord.ThreadMember } type ThreadMemberRemoveEvent struct { diff --git a/events/guild_voice_events.go b/events/guild_voice_events.go new file mode 100644 index 00000000..3b7289a2 --- /dev/null +++ b/events/guild_voice_events.go @@ -0,0 +1,39 @@ +package events + +import ( + "github.com/disgoorg/disgo/discord" +) + +// GenericGuildVoiceStateEvent is called upon receiving GuildVoiceJoinEvent, GuildVoiceMoveEvent, GuildVoiceLeaveEvent +type GenericGuildVoiceStateEvent struct { + *GenericEvent + VoiceState discord.VoiceState +} + +// GuildVoiceStateUpdateEvent indicates that the discord.VoiceState of a discord.Member has updated(requires discord.GatewayIntentsGuildVoiceStates) +type GuildVoiceStateUpdateEvent struct { + *GenericGuildVoiceStateEvent + OldVoiceState discord.VoiceState +} + +// GuildVoiceJoinEvent indicates that a discord.Member joined a discord.Channel(requires discord.GatewayIntentsGuildVoiceStates) +type GuildVoiceJoinEvent struct { + *GenericGuildVoiceStateEvent +} + +// GuildVoiceMoveEvent indicates that a discord.Member moved a discord.Channel(requires discord.GatewayIntentsGuildVoiceStates) +type GuildVoiceMoveEvent struct { + *GenericGuildVoiceStateEvent + OldVoiceState discord.VoiceState +} + +// GuildVoiceLeaveEvent indicates that a discord.Member left a discord.Channel(requires discord.GatewayIntentsGuildVoiceStates) +type GuildVoiceLeaveEvent struct { + *GenericGuildVoiceStateEvent + OldVoiceState discord.VoiceState +} + +type VoiceServerUpdateEvent struct { + *GenericEvent + VoiceServerUpdate discord.VoiceServerUpdate +} diff --git a/events/guild_webhooks_update_events.go b/events/guild_webhooks_update_events.go new file mode 100644 index 00000000..96a8a26f --- /dev/null +++ b/events/guild_webhooks_update_events.go @@ -0,0 +1,22 @@ +package events + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +type WebhooksUpdateEvent struct { + *GenericEvent + GuildId snowflake.Snowflake + ChannelID snowflake.Snowflake +} + +// Guild returns the Guild the webhook was updated in. +// This will only check cached guilds! +func (e *WebhooksUpdateEvent) Guild() (discord.Guild, bool) { + return e.Client().Caches().Guilds().Get(e.GuildId) +} + +func (e *WebhooksUpdateEvent) Channel() (discord.GuildMessageChannel, bool) { + return e.Client().Caches().Channels().GetGuildMessageChannel(e.ChannelID) +} diff --git a/core/events/events_heartbeat_event.go b/events/heartbeat_event_events.go similarity index 100% rename from core/events/events_heartbeat_event.go rename to events/heartbeat_event_events.go diff --git a/core/events/events_http_request.go b/events/http_request_events.go similarity index 100% rename from core/events/events_http_request.go rename to events/http_request_events.go diff --git a/events/interaction_events.go b/events/interaction_events.go new file mode 100644 index 00000000..19a7e4f3 --- /dev/null +++ b/events/interaction_events.go @@ -0,0 +1,102 @@ +package events + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest" +) + +type InteractionResponderFunc func(callbackType discord.InteractionCallbackType, data discord.InteractionCallbackData, opts ...rest.RequestOpt) error + +type InteractionEvent struct { + *GenericEvent + discord.Interaction + Respond InteractionResponderFunc +} + +type ApplicationCommandInteractionEvent struct { + *GenericEvent + discord.ApplicationCommandInteraction + Respond InteractionResponderFunc +} + +func (e *ApplicationCommandInteractionEvent) CreateMessage(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) error { + return e.Respond(discord.InteractionCallbackTypeCreateMessage, messageCreate, opts...) +} + +func (e *ApplicationCommandInteractionEvent) DeferCreateMessage(ephemeral bool, opts ...rest.RequestOpt) error { + var messageCreate discord.MessageCreate + if ephemeral { + messageCreate = discord.MessageCreate{Flags: discord.MessageFlagEphemeral} + } + return e.Respond(discord.InteractionCallbackTypeCreateMessage, messageCreate, opts...) +} + +func (e *ApplicationCommandInteractionEvent) CreateModal(modalCreate discord.ModalCreate, opts ...rest.RequestOpt) error { + return e.Respond(discord.InteractionCallbackTypeModal, modalCreate, opts...) +} + +type ComponentInteractionEvent struct { + *GenericEvent + discord.ComponentInteraction + Respond InteractionResponderFunc +} + +func (e *ComponentInteractionEvent) CreateMessage(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) error { + return e.Respond(discord.InteractionCallbackTypeCreateMessage, messageCreate, opts...) +} + +func (e *ComponentInteractionEvent) DeferCreateMessage(ephemeral bool, opts ...rest.RequestOpt) error { + var messageCreate discord.MessageCreate + if ephemeral { + messageCreate = discord.MessageCreate{Flags: discord.MessageFlagEphemeral} + } + return e.Respond(discord.InteractionCallbackTypeCreateMessage, messageCreate, opts...) +} + +func (e *ComponentInteractionEvent) UpdateMessage(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) error { + return e.Respond(discord.InteractionCallbackTypeUpdateMessage, messageUpdate, opts...) +} + +func (e *ComponentInteractionEvent) DeferUpdateMessage(opts ...rest.RequestOpt) error { + return e.Respond(discord.InteractionCallbackTypeDeferredUpdateMessage, nil, opts...) +} + +func (e *ComponentInteractionEvent) CreateModal(modalCreate discord.ModalCreate, opts ...rest.RequestOpt) error { + return e.Respond(discord.InteractionCallbackTypeModal, modalCreate, opts...) +} + +type AutocompleteInteractionEvent struct { + *GenericEvent + discord.AutocompleteInteraction + Respond InteractionResponderFunc +} + +func (e *AutocompleteInteractionEvent) Result(choices []discord.AutocompleteChoice, opts ...rest.RequestOpt) error { + return e.Respond(discord.InteractionCallbackTypeApplicationCommandAutocompleteResult, discord.AutocompleteResult{Choices: choices}, opts...) +} + +type ModalSubmitInteractionEvent struct { + *GenericEvent + discord.ModalSubmitInteraction + Respond InteractionResponderFunc +} + +func (e *ModalSubmitInteractionEvent) CreateMessage(messageCreate discord.MessageCreate, opts ...rest.RequestOpt) error { + return e.Respond(discord.InteractionCallbackTypeCreateMessage, messageCreate, opts...) +} + +func (e *ModalSubmitInteractionEvent) DeferCreateMessage(ephemeral bool, opts ...rest.RequestOpt) error { + var messageCreate discord.MessageCreate + if ephemeral { + messageCreate = discord.MessageCreate{Flags: discord.MessageFlagEphemeral} + } + return e.Respond(discord.InteractionCallbackTypeCreateMessage, messageCreate, opts...) +} + +func (e *ModalSubmitInteractionEvent) UpdateMessage(messageUpdate discord.MessageUpdate, opts ...rest.RequestOpt) error { + return e.Respond(discord.InteractionCallbackTypeUpdateMessage, messageUpdate, opts...) +} + +func (e *ModalSubmitInteractionEvent) DeferUpdateMessage(opts ...rest.RequestOpt) error { + return e.Respond(discord.InteractionCallbackTypeDeferredUpdateMessage, nil, opts...) +} diff --git a/core/events/listener_adapter.go b/events/listener_adapter.go similarity index 94% rename from core/events/listener_adapter.go rename to events/listener_adapter.go index 16f25484..d184d637 100644 --- a/core/events/listener_adapter.go +++ b/events/listener_adapter.go @@ -1,9 +1,11 @@ package events import ( - "github.com/DisgoOrg/disgo/core" + "github.com/disgoorg/disgo/bot" ) +var _ bot.EventListener = (*ListenerAdapter)(nil) + // ListenerAdapter lets you override the handles for receiving events type ListenerAdapter struct { // Other events @@ -45,14 +47,16 @@ type ListenerAdapter struct { OnDMMessageReactionRemoveAll func(event *DMMessageReactionRemoveAllEvent) // Emoji Events - OnEmojiCreate func(event *EmojiCreateEvent) - OnEmojiUpdate func(event *EmojiUpdateEvent) - OnEmojiDelete func(event *EmojiDeleteEvent) + OnEmojisUpdate func(event *EmojisUpdateEvent) + OnEmojiCreate func(event *EmojiCreateEvent) + OnEmojiUpdate func(event *EmojiUpdateEvent) + OnEmojiDelete func(event *EmojiDeleteEvent) // Sticker Events - OnStickerCreate func(event *StickerCreateEvent) - OnStickerUpdate func(event *StickerUpdateEvent) - OnStickerDelete func(event *StickerDeleteEvent) + OnStickersUpdate func(event *StickersUpdateEvent) + OnStickerCreate func(event *StickerCreateEvent) + OnStickerUpdate func(event *StickerUpdateEvent) + OnStickerDelete func(event *StickerDeleteEvent) // gateway status Events OnReady func(event *ReadyEvent) @@ -72,8 +76,8 @@ type ListenerAdapter struct { OnGuildUnban func(event *GuildUnbanEvent) // Guild Invite Events - OnGuildInviteCreate func(event *GuildInviteCreateEvent) - OnGuildInviteDelete func(event *GuildInviteDeleteEvent) + OnGuildInviteCreate func(event *InviteCreateEvent) + OnGuildInviteDelete func(event *InviteDeleteEvent) // Guild Member Events OnGuildMemberJoin func(event *GuildMemberJoinEvent) @@ -159,7 +163,7 @@ type ListenerAdapter struct { } // OnEvent is getting called everytime we receive an event -func (l ListenerAdapter) OnEvent(event core.Event) { +func (l ListenerAdapter) OnEvent(event bot.Event) { switch e := event.(type) { case *HeartbeatEvent: if listener := l.OnHeartbeat; listener != nil { @@ -271,6 +275,10 @@ func (l ListenerAdapter) OnEvent(event core.Event) { } // Emoji Events + case *EmojisUpdateEvent: + if listener := l.OnEmojisUpdate; listener != nil { + listener(e) + } case *EmojiCreateEvent: if listener := l.OnEmojiCreate; listener != nil { listener(e) @@ -285,6 +293,10 @@ func (l ListenerAdapter) OnEvent(event core.Event) { } // Sticker Events + case *StickersUpdateEvent: + if listener := l.OnStickersUpdate; listener != nil { + listener(e) + } case *StickerCreateEvent: if listener := l.OnStickerCreate; listener != nil { listener(e) @@ -355,11 +367,11 @@ func (l ListenerAdapter) OnEvent(event core.Event) { } // Guild Invite Events - case *GuildInviteCreateEvent: + case *InviteCreateEvent: if listener := l.OnGuildInviteCreate; listener != nil { listener(e) } - case *GuildInviteDeleteEvent: + case *InviteDeleteEvent: if listener := l.OnGuildInviteDelete; listener != nil { listener(e) } @@ -608,6 +620,6 @@ func (l ListenerAdapter) OnEvent(event core.Event) { } default: - e.Bot().Logger.Errorf("unexpected event received: '%T', event: '%+v'", event, event) + e.Client().Logger().Errorf("unexpected event received: '%T', event: '%+v'", event, event) } } diff --git a/events/message_events.go b/events/message_events.go new file mode 100644 index 00000000..53dd9202 --- /dev/null +++ b/events/message_events.go @@ -0,0 +1,44 @@ +package events + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +// GenericMessageEvent generic discord.Message event +type GenericMessageEvent struct { + *GenericEvent + MessageID snowflake.Snowflake + Message discord.Message + ChannelID snowflake.Snowflake + GuildID *snowflake.Snowflake +} + +// Channel returns the discord.Channel where the GenericMessageEvent happened +func (e *GenericMessageEvent) Channel() (discord.MessageChannel, bool) { + return e.Client().Caches().Channels().GetMessageChannel(e.ChannelID) +} + +// Guild returns the discord.Guild where the GenericMessageEvent happened or nil if it happened in DMs +func (e *GenericMessageEvent) Guild() (discord.Guild, bool) { + if e.GuildID == nil { + return discord.Guild{}, false + } + return e.Client().Caches().Guilds().Get(*e.GuildID) +} + +// MessageCreateEvent indicates that a discord.Message got received +type MessageCreateEvent struct { + *GenericMessageEvent +} + +// MessageUpdateEvent indicates that a discord.Message got update +type MessageUpdateEvent struct { + *GenericMessageEvent + OldMessage discord.Message +} + +// MessageDeleteEvent indicates that a discord.Message got deleted +type MessageDeleteEvent struct { + *GenericMessageEvent +} diff --git a/events/message_reaction_events.go b/events/message_reaction_events.go new file mode 100644 index 00000000..52d36afb --- /dev/null +++ b/events/message_reaction_events.go @@ -0,0 +1,44 @@ +package events + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +// GenericReactionEvent is called upon receiving MessageReactionAddEvent or MessageReactionRemoveEvent +type GenericReactionEvent struct { + *GenericEvent + UserID snowflake.Snowflake + ChannelID snowflake.Snowflake + MessageID snowflake.Snowflake + GuildID *snowflake.Snowflake + Emoji discord.ReactionEmoji +} + +// MessageReactionAddEvent indicates that a discord.User added a discord.MessageReaction to a discord.Message in a discord.Channel(this+++ requires the discord.GatewayIntentGuildMessageReactions and/or discord.GatewayIntentDirectMessageReactions) +type MessageReactionAddEvent struct { + *GenericReactionEvent + Member *discord.Member +} + +// MessageReactionRemoveEvent indicates that a discord.User removed a discord.MessageReaction from a discord.Message in a discord.GetChannel(requires the discord.GatewayIntentGuildMessageReactions and/or discord.GatewayIntentDirectMessageReactions) +type MessageReactionRemoveEvent struct { + *GenericReactionEvent +} + +// MessageReactionRemoveEmojiEvent indicates someone removed all discord.MessageReaction of a specific discord.Emoji from a discord.Message in a discord.Channel(requires the discord.GatewayIntentGuildMessageReactions and/or discord.GatewayIntentDirectMessageReactions) +type MessageReactionRemoveEmojiEvent struct { + *GenericEvent + ChannelID snowflake.Snowflake + MessageID snowflake.Snowflake + GuildID *snowflake.Snowflake + Emoji discord.ReactionEmoji +} + +// MessageReactionRemoveAllEvent indicates someone removed all discord.MessageReaction(s) from a discord.Message in a discord.Channel(requires the discord.GatewayIntentGuildMessageReactions and/or discord.GatewayIntentDirectMessageReactions) +type MessageReactionRemoveAllEvent struct { + *GenericEvent + ChannelID snowflake.Snowflake + MessageID snowflake.Snowflake + GuildID *snowflake.Snowflake +} diff --git a/events/raw_event.go b/events/raw_event.go new file mode 100644 index 00000000..491b10af --- /dev/null +++ b/events/raw_event.go @@ -0,0 +1,39 @@ +package events + +import ( + "bytes" + "io" + "io/ioutil" + + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/json" + + "github.com/disgoorg/disgo/discord" +) + +func HandleRawEvent(client bot.Client, gatewayEventType discord.GatewayEventType, sequenceNumber int, responseChannel chan<- discord.InteractionResponse, reader io.Reader) io.Reader { + if client.EventManager().RawEventsEnabled() { + var buf bytes.Buffer + data, err := ioutil.ReadAll(io.TeeReader(reader, &buf)) + if err != nil { + client.Logger().Error("error reading raw payload from event") + } + client.EventManager().DispatchEvent(&RawEvent{ + GenericEvent: NewGenericEvent(client, sequenceNumber), + Type: gatewayEventType, + RawPayload: data, + ResponseChannel: responseChannel, + }) + + return &buf + } + return reader +} + +// RawEvent is called for any discord.GatewayEventType we receive if enabled in the bot.Config +type RawEvent struct { + *GenericEvent + Type discord.GatewayEventType + RawPayload json.RawMessage + ResponseChannel chan<- discord.InteractionResponse +} diff --git a/events/self_update_events.go b/events/self_update_events.go new file mode 100644 index 00000000..0da66b44 --- /dev/null +++ b/events/self_update_events.go @@ -0,0 +1,12 @@ +package events + +import ( + "github.com/disgoorg/disgo/discord" +) + +// SelfUpdateEvent is called when something about this discord.User updates +type SelfUpdateEvent struct { + *GenericEvent + SelfUser discord.OAuth2User + OldSelfUser discord.OAuth2User +} diff --git a/core/events/events_user_activity.go b/events/user_activity_events.go similarity index 62% rename from core/events/events_user_activity.go rename to events/user_activity_events.go index db218a11..e3796ca3 100644 --- a/core/events/events_user_activity.go +++ b/events/user_activity_events.go @@ -1,9 +1,8 @@ package events import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" ) // GenericUserActivityEvent generic Activity event @@ -14,22 +13,16 @@ type GenericUserActivityEvent struct { Activity discord.Activity } -// User returns the User that changed their Activity. -// This will only check cached users! -func (g *GenericUserActivityEvent) User() *core.User { - return g.Bot().Caches.Users().Get(g.UserID) -} - // Member returns the Member that changed their Activity. // This will only check cached members! -func (g *GenericUserActivityEvent) Member() *core.Member { - return g.Bot().Caches.Members().Get(g.GuildID, g.UserID) +func (g *GenericUserActivityEvent) Member() (discord.Member, bool) { + return g.Client().Caches().Members().Get(g.GuildID, g.UserID) } // Guild returns the Guild that changed their Activity. // This will only check cached guilds! -func (g *GenericUserActivityEvent) Guild() *core.Guild { - return g.Bot().Caches.Guilds().Get(g.UserID) +func (g *GenericUserActivityEvent) Guild() (discord.Guild, bool) { + return g.Client().Caches().Guilds().Get(g.UserID) } // UserActivityStartEvent indicates that a User started an Activity diff --git a/events/user_events.go b/events/user_events.go new file mode 100644 index 00000000..f52b1c03 --- /dev/null +++ b/events/user_events.go @@ -0,0 +1,35 @@ +package events + +import ( + "time" + + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +// GenericUserEvent is called upon receiving UserUpdateEvent or UserTypingStartEvent +type GenericUserEvent struct { + *GenericEvent + UserID snowflake.Snowflake + User discord.User +} + +// UserUpdateEvent indicates that a discord.User updated +type UserUpdateEvent struct { + *GenericUserEvent + OldUser discord.User +} + +// UserTypingStartEvent indicates that a discord.User started typing in a discord.DMChannel or discord.MessageChanel(requires the discord.GatewayIntentDirectMessageTyping and/or discord.GatewayIntentGuildMessageTyping) +type UserTypingStartEvent struct { + *GenericEvent + ChannelID snowflake.Snowflake + GuildID *snowflake.Snowflake + UserID snowflake.Snowflake + Timestamp time.Time +} + +// Channel returns the discord.MessageChannel the discord.User started typing in +func (e *UserTypingStartEvent) Channel() (discord.MessageChannel, bool) { + return e.Client().Caches().Channels().GetMessageChannel(e.ChannelID) +} diff --git a/events/user_status_events.go b/events/user_status_events.go new file mode 100644 index 00000000..b923d75f --- /dev/null +++ b/events/user_status_events.go @@ -0,0 +1,22 @@ +package events + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" +) + +// UserStatusUpdateEvent generic Status event +type UserStatusUpdateEvent struct { + *GenericEvent + UserID snowflake.Snowflake + OldStatus discord.OnlineStatus + Status discord.OnlineStatus +} + +// UserClientStatusUpdateEvent generic client-specific Status event +type UserClientStatusUpdateEvent struct { + *GenericEvent + UserID snowflake.Snowflake + OldClientStatus *discord.ClientStatus + ClientStatus discord.ClientStatus +} diff --git a/gateway/gateway.go b/gateway/gateway.go index aa92196a..0c6845be 100644 --- a/gateway/gateway.go +++ b/gateway/gateway.go @@ -5,8 +5,8 @@ import ( "io" "time" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/log" ) // Status is the state that the client is currently in @@ -34,19 +34,22 @@ const ( StatusDisconnected ) -type EventHandlerFunc func(gatewayEventType discord.GatewayEventType, sequenceNumber discord.GatewaySequence, payload io.Reader) +type EventHandlerFunc func(gatewayEventType discord.GatewayEventType, sequenceNumber int, payload io.Reader) + +type CreateFunc func(token string, eventHandlerFunc EventHandlerFunc, opts ...ConfigOpt) Gateway // Gateway is what is used to connect to discord type Gateway interface { Logger() log.Logger - Config() Config ShardID() int ShardCount() int + GatewayIntents() discord.GatewayIntents + Open(ctx context.Context) error ReOpen(ctx context.Context, delay time.Duration) error Close(ctx context.Context) CloseWithCode(ctx context.Context, code int, message string) Status() Status - Send(ctx context.Context, command discord.GatewayCommand) error + Send(ctx context.Context, op discord.GatewayOpcode, data discord.GatewayMessageData) error Latency() time.Duration } diff --git a/gateway/gateway_config.go b/gateway/gateway_config.go index 740c10d9..e25e299e 100644 --- a/gateway/gateway_config.go +++ b/gateway/gateway_config.go @@ -1,40 +1,41 @@ package gateway import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway/grate" - "github.com/DisgoOrg/disgo/info" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/gateway/grate" + "github.com/disgoorg/log" ) -//goland:noinspection GoUnusedGlobalVariable -var DefaultConfig = Config{ - LargeThreshold: 50, - GatewayIntents: discord.GatewayIntentsDefault, - Compress: true, - AutoReconnect: true, - MaxReconnectTries: 10, - OS: info.OS, - Browser: info.Name, - Device: info.Name, +func DefaultConfig() *Config { + return &Config{ + LargeThreshold: 50, + GatewayIntents: discord.GatewayIntentsDefault, + Compress: true, + ShardID: 0, + ShardCount: 1, + AutoReconnect: true, + MaxReconnectTries: 10, + } } type Config struct { - Logger log.Logger - EventHandlerFunc EventHandlerFunc - LargeThreshold int - GatewayIntents discord.GatewayIntents - Compress bool - SessionID *string - LastSequenceReceived *discord.GatewaySequence - AutoReconnect bool - MaxReconnectTries int - RateLimiter grate.Limiter - RateLimiterConfig *grate.Config - Presence *discord.UpdatePresenceCommandData - OS string - Browser string - Device string + Logger log.Logger + LargeThreshold int + GatewayIntents discord.GatewayIntents + Compress bool + GatewayURL string + ShardID int + ShardCount int + SessionID *string + LastSequenceReceived *int + AutoReconnect bool + MaxReconnectTries int + RateLimiter grate.Limiter + RateLimiterConfigOpts []grate.ConfigOpt + Presence *discord.GatewayMessageDataPresenceUpdate + OS string + Browser string + Device string } type ConfigOpt func(config *Config) @@ -43,16 +44,23 @@ func (c *Config) Apply(opts []ConfigOpt) { for _, opt := range opts { opt(c) } + if c.RateLimiter == nil { + c.RateLimiter = grate.NewLimiter(c.RateLimiterConfigOpts...) + } +} + +func WithLogger(logger log.Logger) ConfigOpt { + return func(config *Config) { + config.Logger = logger + } } -//goland:noinspection GoUnusedExportedFunction func WithLargeThreshold(largeThreshold int) ConfigOpt { return func(config *Config) { config.LargeThreshold = largeThreshold } } -//goland:noinspection GoUnusedExportedFunction func WithGatewayIntents(gatewayIntents ...discord.GatewayIntents) ConfigOpt { return func(config *Config) { var intents discord.GatewayIntents @@ -63,87 +71,84 @@ func WithGatewayIntents(gatewayIntents ...discord.GatewayIntents) ConfigOpt { } } -//goland:noinspection GoUnusedExportedFunction func WithCompress(compress bool) ConfigOpt { return func(config *Config) { config.Compress = compress } } -//goland:noinspection GoUnusedExportedFunction +func WithGatewayURL(gatewayURL string) ConfigOpt { + return func(config *Config) { + config.GatewayURL = gatewayURL + } +} + +func WithShardID(shardID int) ConfigOpt { + return func(config *Config) { + config.ShardID = shardID + } +} + +func WithShardCount(shardCount int) ConfigOpt { + return func(config *Config) { + config.ShardCount = shardCount + } +} + func WithSessionID(sessionID string) ConfigOpt { return func(config *Config) { config.SessionID = &sessionID } } -//goland:noinspection GoUnusedExportedFunction -func WithSequence(sequence discord.GatewaySequence) ConfigOpt { +func WithSequence(sequence int) ConfigOpt { return func(config *Config) { config.LastSequenceReceived = &sequence } } -//goland:noinspection GoUnusedExportedFunction func WithAutoReconnect(autoReconnect bool) ConfigOpt { return func(config *Config) { config.AutoReconnect = autoReconnect } } -//goland:noinspection GoUnusedExportedFunction func WithMaxReconnectTries(maxReconnectTries int) ConfigOpt { return func(config *Config) { config.MaxReconnectTries = maxReconnectTries } } -//goland:noinspection GoUnusedExportedFunction func WithRateLimiter(rateLimiter grate.Limiter) ConfigOpt { return func(config *Config) { config.RateLimiter = rateLimiter } } -//goland:noinspection GoUnusedExportedFunction -func WithRateLimiterConfig(rateLimiterConfig grate.Config) ConfigOpt { - return func(config *Config) { - config.RateLimiterConfig = &rateLimiterConfig - } -} - -//goland:noinspection GoUnusedExportedFunction func WithRateLimiterConfigOpts(opts ...grate.ConfigOpt) ConfigOpt { return func(config *Config) { - if config.RateLimiterConfig == nil { - config.RateLimiterConfig = &grate.DefaultConfig - } - config.RateLimiterConfig.Apply(opts) + config.RateLimiterConfigOpts = append(config.RateLimiterConfigOpts, opts...) } } -//goland:noinspection GoUnusedExportedFunction -func WithPresence(presence discord.UpdatePresenceCommandData) ConfigOpt { +func WithPresence(presence discord.GatewayMessageDataPresenceUpdate) ConfigOpt { return func(config *Config) { config.Presence = &presence } } -//goland:noinspection GoUnusedExportedFunction func WithOS(os string) ConfigOpt { return func(config *Config) { config.OS = os } } -//goland:noinspection GoUnusedExportedFunction func WithBrowser(browser string) ConfigOpt { return func(config *Config) { config.Browser = browser } } -//goland:noinspection GoUnusedExportedFunction func WithDevice(device string) ConfigOpt { return func(config *Config) { config.Device = device diff --git a/gateway/gateway_impl.go b/gateway/gateway_impl.go index 96e3fe61..dd070e07 100644 --- a/gateway/gateway_impl.go +++ b/gateway/gateway_impl.go @@ -10,53 +10,33 @@ import ( "net/http" "time" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway/grate" - "github.com/DisgoOrg/disgo/internal/tokenhelper" - "github.com/DisgoOrg/disgo/json" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/log" - "github.com/pkg/errors" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/internal/tokenhelper" + "github.com/disgoorg/disgo/json" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/log" "github.com/gorilla/websocket" ) var _ Gateway = (*gatewayImpl)(nil) -func New(token string, url string, shardID int, shardCount int, eventHandlerFunc EventHandlerFunc, config *Config) Gateway { - if config == nil { - config = &DefaultConfig - } - if config.Logger == nil { - config.Logger = log.Default() - } - if config.RateLimiterConfig == nil { - config.RateLimiterConfig = &grate.DefaultConfig - } - if config.RateLimiterConfig.Logger == nil { - config.RateLimiterConfig.Logger = config.Logger - } - if config.RateLimiter == nil { - config.RateLimiter = grate.NewLimiter(config.RateLimiterConfig) - } - config.EventHandlerFunc = eventHandlerFunc +func New(token string, eventHandlerFunc EventHandlerFunc, opts ...ConfigOpt) Gateway { + config := DefaultConfig() + config.Apply(opts) return &gatewayImpl{ - config: *config, - token: token, - url: url, - shardID: shardID, - shardCount: shardCount, - status: StatusUnconnected, + config: *config, + eventHandlerFunc: eventHandlerFunc, + token: token, + status: StatusUnconnected, } } type gatewayImpl struct { - config Config - token string - url string - shardID int - shardCount int + config Config + eventHandlerFunc EventHandlerFunc + token string conn *websocket.Conn heartbeatTicker *time.Ticker @@ -71,28 +51,28 @@ func (g *gatewayImpl) Logger() log.Logger { return g.config.Logger } -func (g *gatewayImpl) Config() Config { - return g.config -} - func (g *gatewayImpl) ShardID() int { - return g.shardID + return g.config.ShardID } func (g *gatewayImpl) ShardCount() int { - return g.shardCount + return g.config.ShardCount +} + +func (g *gatewayImpl) GatewayIntents() discord.GatewayIntents { + return g.config.GatewayIntents } -func (g *gatewayImpl) formatLogsf(format string, a ...interface{}) string { - if g.shardCount > 1 { - return fmt.Sprintf("[%d/%d] %s", g.shardID, g.shardCount, fmt.Sprintf(format, a...)) +func (g *gatewayImpl) formatLogsf(format string, a ...any) string { + if g.config.ShardCount > 1 { + return fmt.Sprintf("[%d/%d] %s", g.config.ShardID, g.config.ShardCount, fmt.Sprintf(format, a...)) } return fmt.Sprintf(format, a...) } -func (g *gatewayImpl) formatLogs(a ...interface{}) string { - if g.shardCount > 1 { - return fmt.Sprintf("[%d/%d] %s", g.shardID, g.shardCount, fmt.Sprint(a...)) +func (g *gatewayImpl) formatLogs(a ...any) string { + if g.config.ShardCount > 1 { + return fmt.Sprintf("[%d/%d] %s", g.config.ShardID, g.config.ShardCount, fmt.Sprint(a...)) } return fmt.Sprint(a...) } @@ -104,7 +84,7 @@ func (g *gatewayImpl) Open(ctx context.Context) error { } g.status = StatusConnecting - gatewayURL := g.url + "?v=" + route.APIVersion + "&encoding=json" + gatewayURL := g.config.GatewayURL + "?v=" + route.APIVersion + "&encoding=json" var rs *http.Response var err error g.conn, rs, err = websocket.DefaultDialer.DialContext(ctx, gatewayURL, nil) @@ -163,7 +143,7 @@ func (g *gatewayImpl) Status() Status { return g.status } -func (g *gatewayImpl) Send(ctx context.Context, command discord.GatewayCommand) error { +func (g *gatewayImpl) Send(ctx context.Context, op discord.GatewayOpcode, d discord.GatewayMessageData) error { if g.conn == nil { return discord.ErrShardNotConnected } @@ -173,7 +153,10 @@ func (g *gatewayImpl) Send(ctx context.Context, command discord.GatewayCommand) } defer g.config.RateLimiter.Unlock() - data, err := json.Marshal(command) + data, err := json.Marshal(discord.GatewayMessage{ + Op: op, + D: d, + }) if err != nil { return err } @@ -191,7 +174,7 @@ func (g *gatewayImpl) ReOpen(ctx context.Context, delay time.Duration) error { func (g *gatewayImpl) reOpen(ctx context.Context, try int, delay time.Duration) error { if try >= g.config.MaxReconnectTries-1 { - return errors.Errorf("failed to reconnect. exceeded max reconnect tries of %d reached", g.config.MaxReconnectTries) + return fmt.Errorf("failed to reconnect. exceeded max reconnect tries of %d reached", g.config.MaxReconnectTries) } timer := time.NewTimer(time.Duration(try) * delay) defer timer.Stop() @@ -238,7 +221,7 @@ func (g *gatewayImpl) sendHeartbeat() { ctx, cancel := context.WithTimeout(context.Background(), g.heartbeatInterval) defer cancel() - if err := g.Send(ctx, discord.NewGatewayCommand(discord.GatewayOpcodeHeartbeat, g.config.LastSequenceReceived)); err != nil && err != discord.ErrShardNotConnected { + if err := g.Send(ctx, discord.GatewayOpcodeHeartbeat, (*discord.GatewayMessageDataHeartbeat)(g.config.LastSequenceReceived)); err != nil && err != discord.ErrShardNotConnected { g.Logger().Error(g.formatLogs("failed to send heartbeat. error: ", err)) g.CloseWithCode(context.TODO(), websocket.CloseServiceRestart, "heartbeat timeout") go g.reconnect(context.TODO()) @@ -251,7 +234,7 @@ func (g *gatewayImpl) connect() { g.status = StatusIdentifying g.Logger().Debug(g.formatLogs("sending Identify command...")) - identify := discord.IdentifyCommandData{ + identify := discord.GatewayMessageDataIdentify{ Token: g.token, Properties: discord.IdentifyCommandDataProperties{ OS: g.config.OS, @@ -267,7 +250,7 @@ func (g *gatewayImpl) connect() { identify.Shard = []int{g.ShardID(), g.ShardCount()} } - if err := g.Send(context.TODO(), discord.NewGatewayCommand(discord.GatewayOpcodeIdentify, identify)); err != nil { + if err := g.Send(context.TODO(), discord.GatewayOpcodeIdentify, identify); err != nil { g.Logger().Error(g.formatLogs("error sending Identify command err: ", err)) } g.status = StatusWaitingForReady @@ -275,14 +258,14 @@ func (g *gatewayImpl) connect() { func (g *gatewayImpl) resume() { g.status = StatusResuming - resume := discord.ResumeCommandData{ + resume := discord.GatewayMessageDataResume{ Token: g.token, SessionID: *g.config.SessionID, Seq: *g.config.LastSequenceReceived, } g.Logger().Info(g.formatLogs("sending Resume command...")) - if err := g.Send(context.TODO(), discord.NewGatewayCommand(discord.GatewayOpcodeResume, resume)); err != nil { + if err := g.Send(context.TODO(), discord.GatewayOpcodeResume, resume); err != nil { g.Logger().Error(g.formatLogs("error sending resume command err: ", err)) } } @@ -327,7 +310,7 @@ func (g *gatewayImpl) listen() { return } - event, err := g.parseGatewayEvent(mt, reader) + event, err := g.parseGatewayMessage(mt, reader) if err != nil { g.Logger().Error(g.formatLogs("error while parsing gateway event. error: ", err)) continue @@ -338,13 +321,7 @@ func (g *gatewayImpl) listen() { g.lastHeartbeatReceived = time.Now().UTC() g.lastHeartbeatSent = time.Now().UTC() - var eventData discord.GatewayEventHello - if err = json.Unmarshal(event.D, &eventData); err != nil { - g.Logger().Error(g.formatLogs("error parsing op hello payload data: ", err)) - continue - } - - g.heartbeatInterval = eventData.HeartbeatInterval * time.Millisecond + g.heartbeatInterval = time.Duration(event.D.(discord.GatewayMessageDataHello).HeartbeatInterval) * time.Millisecond if g.config.LastSequenceReceived == nil || g.config.SessionID == nil { g.connect() @@ -354,7 +331,8 @@ func (g *gatewayImpl) listen() { go g.heartbeat() case discord.GatewayOpcodeDispatch: - g.Logger().Trace(g.formatLogsf("received: OpcodeDispatch %s, data: %s", event.T, string(event.D))) + data := event.D.(discord.GatewayMessageDataDispatch) + g.Logger().Trace(g.formatLogsf("received: OpcodeDispatch %s, data: %s", event.T, string(data))) // set last sequence received g.config.LastSequenceReceived = &event.S @@ -362,7 +340,7 @@ func (g *gatewayImpl) listen() { // get session id here if event.T == discord.GatewayEventTypeReady { var readyEvent discord.GatewayEventReady - if err = json.Unmarshal(event.D, &readyEvent); err != nil { + if err = json.Unmarshal(data, &readyEvent); err != nil { g.Logger().Error(g.formatLogs("Error parsing ready event. error: ", err)) continue } @@ -372,7 +350,7 @@ func (g *gatewayImpl) listen() { } // push event to the command manager - g.config.EventHandlerFunc(event.T, event.S, bytes.NewBuffer(event.D)) + g.eventHandlerFunc(event.T, event.S, bytes.NewBuffer(data)) case discord.GatewayOpcodeHeartbeat: g.Logger().Debug(g.formatLogs("received: OpcodeHeartbeat")) @@ -384,10 +362,7 @@ func (g *gatewayImpl) listen() { go g.reconnect(context.TODO()) case discord.GatewayOpcodeInvalidSession: - var canResume bool - if err = json.Unmarshal(event.D, &canResume); err != nil { - g.Logger().Error(g.formatLogs("error parsing invalid session data. error: ", err)) - } + canResume := event.D.(discord.GatewayMessageDataInvalidSession) g.Logger().Debug(g.formatLogs("received: OpcodeInvalidSession, canResume: ", canResume)) if canResume { g.CloseWithCode(context.TODO(), websocket.CloseServiceRestart, "invalid session") @@ -406,24 +381,24 @@ func (g *gatewayImpl) listen() { } } -func (g *gatewayImpl) parseGatewayEvent(mt int, reader io.Reader) (*discord.GatewayPayload, error) { +func (g *gatewayImpl) parseGatewayMessage(mt int, reader io.Reader) (*discord.GatewayMessage, error) { + var finalReadCloser io.ReadCloser if mt == websocket.BinaryMessage { g.Logger().Trace(g.formatLogs("binary message received. decompressing...")) readCloser, err := zlib.NewReader(reader) if err != nil { - return nil, errors.Wrap(err, "failed to decompress zlib") + return nil, fmt.Errorf("failed to decompress zlib: %w", err) } - defer func() { - _ = readCloser.Close() - }() - reader = readCloser + finalReadCloser = readCloser + } else { + finalReadCloser = io.NopCloser(reader) } + defer finalReadCloser.Close() - decoder := json.NewDecoder(reader) - var event discord.GatewayPayload - if err := decoder.Decode(&event); err != nil { + var message discord.GatewayMessage + if err := json.NewDecoder(finalReadCloser).Decode(&message); err != nil { g.Logger().Error(g.formatLogs("error decoding websocket message: ", err)) return nil, err } - return &event, nil + return &message, nil } diff --git a/gateway/grate/gateway_rate_limiter.go b/gateway/grate/gateway_rate_limiter.go index cf367ae2..34049e68 100644 --- a/gateway/grate/gateway_rate_limiter.go +++ b/gateway/grate/gateway_rate_limiter.go @@ -3,13 +3,13 @@ package grate import ( "context" - "github.com/DisgoOrg/log" + "github.com/disgoorg/log" ) type Limiter interface { Logger() log.Logger Close(ctx context.Context) error - Config() Config + Wait(ctx context.Context) error Unlock() } diff --git a/gateway/grate/gateway_rate_limiter_config.go b/gateway/grate/gateway_rate_limiter_config.go index 98104d53..045b33d1 100644 --- a/gateway/grate/gateway_rate_limiter_config.go +++ b/gateway/grate/gateway_rate_limiter_config.go @@ -1,11 +1,14 @@ package grate import ( - "github.com/DisgoOrg/log" + "github.com/disgoorg/log" ) -var DefaultConfig = Config{ - CommandsPerMinute: 120, +func DefaultConfig() *Config { + return &Config{ + Logger: log.Default(), + CommandsPerMinute: 120, + } } type Config struct { @@ -21,14 +24,12 @@ func (c *Config) Apply(opts []ConfigOpt) { } } -//goland:noinspection GoUnusedExportedFunction func WithLogger(logger log.Logger) ConfigOpt { return func(config *Config) { config.Logger = logger } } -//goland:noinspection GoUnusedExportedFunction func WithCommandsPerMinute(commandsPerMinute int) ConfigOpt { return func(config *Config) { config.CommandsPerMinute = commandsPerMinute diff --git a/gateway/grate/gateway_rate_limiter_impl.go b/gateway/grate/gateway_rate_limiter_impl.go index c2a0ef84..de2dc64c 100644 --- a/gateway/grate/gateway_rate_limiter_impl.go +++ b/gateway/grate/gateway_rate_limiter_impl.go @@ -4,18 +4,14 @@ import ( "context" "time" - "github.com/DisgoOrg/log" + "github.com/disgoorg/log" "github.com/sasha-s/go-csync" ) -//goland:noinspection GoUnusedExportedFunction -func NewLimiter(config *Config) Limiter { - if config == nil { - config = &DefaultConfig - } - if config.Logger == nil { - config.Logger = log.Default() - } +func NewLimiter(opts ...ConfigOpt) Limiter { + config := DefaultConfig() + config.Apply(opts) + return &limiterImpl{ config: *config, } @@ -43,10 +39,6 @@ func (l *limiterImpl) Close(ctx context.Context) error { return nil } -func (l *limiterImpl) Config() Config { - return l.config -} - func (l *limiterImpl) Wait(ctx context.Context) error { l.Logger().Trace("locking gateway rate limiter") if err := l.CLock(ctx); err != nil { @@ -82,7 +74,7 @@ func (l *limiterImpl) Unlock() { now := time.Now() if l.reset.Before(now) { l.reset = now.Add(time.Minute) - l.remaining = l.Config().CommandsPerMinute + l.remaining = l.config.CommandsPerMinute } l.Mutex.Unlock() } diff --git a/core/handlers/all_handlers.go b/gateway/handlers/all_handlers.go similarity index 70% rename from core/handlers/all_handlers.go rename to gateway/handlers/all_handlers.go index 6ee61596..a8c00741 100644 --- a/core/handlers/all_handlers.go +++ b/gateway/handlers/all_handlers.go @@ -3,40 +3,38 @@ package handlers import ( "io" - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/disgo/httpserver" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/disgo/httpserver" ) -func DefaultHTTPServerEventHandler(bot *core.Bot) httpserver.EventHandlerFunc { +func DefaultHTTPServerEventHandler(client bot.Client) httpserver.EventHandlerFunc { return func(responseChannel chan<- discord.InteractionResponse, reader io.Reader) { - bot.EventManager.HandleHTTP(responseChannel, events.HandleRawEvent(bot, discord.GatewayEventTypeInteractionCreate, -1, reader)) + client.EventManager().HandleHTTPEvent(responseChannel, events.HandleRawEvent(client, discord.GatewayEventTypeInteractionCreate, -1, responseChannel, reader)) } } -func GetHTTPServerHandler() core.HTTPServerEventHandler { +func GetHTTPServerHandler() bot.HTTPServerEventHandler { return &httpserverHandlerInteractionCreate{} } -func DefaultGatewayEventHandler(bot *core.Bot) gateway.EventHandlerFunc { - return func(gatewayEventType discord.GatewayEventType, sequenceNumber discord.GatewaySequence, reader io.Reader) { - reader = events.HandleRawEvent(bot, gatewayEventType, sequenceNumber, reader) - - bot.EventManager.HandleGateway(gatewayEventType, sequenceNumber, reader) +func DefaultGatewayEventHandler(client bot.Client) gateway.EventHandlerFunc { + return func(gatewayEventType discord.GatewayEventType, sequenceNumber int, reader io.Reader) { + client.EventManager().HandleGatewayEvent(gatewayEventType, sequenceNumber, events.HandleRawEvent(client, gatewayEventType, sequenceNumber, nil, reader)) } } -func GetGatewayHandlers() map[discord.GatewayEventType]core.GatewayEventHandler { - handlers := make(map[discord.GatewayEventType]core.GatewayEventHandler, len(AllEventHandlers)) +func GetGatewayHandlers() map[discord.GatewayEventType]bot.GatewayEventHandler { + handlers := make(map[discord.GatewayEventType]bot.GatewayEventHandler, len(AllEventHandlers)) for _, handler := range AllEventHandlers { handlers[handler.EventType()] = handler } return handlers } -var AllEventHandlers = []core.GatewayEventHandler{ +var AllEventHandlers = []bot.GatewayEventHandler{ &gatewayHandlerReady{}, &gatewayHandlerResumed{}, diff --git a/gateway/handlers/channel_create_handler.go b/gateway/handlers/channel_create_handler.go new file mode 100644 index 00000000..86ac2acd --- /dev/null +++ b/gateway/handlers/channel_create_handler.go @@ -0,0 +1,45 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerChannelCreate handles core.GatewayEventChannelCreate +type gatewayHandlerChannelCreate struct{} + +// EventType returns the core.GatewayGatewayEventType +func (h *gatewayHandlerChannelCreate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeChannelCreate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerChannelCreate) New() any { + return &discord.UnmarshalChannel{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerChannelCreate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + channel := v.(*discord.UnmarshalChannel).Channel + client.Caches().Channels().Put(channel.ID(), channel) + + if guildChannel, ok := channel.(discord.GuildChannel); ok { + client.EventManager().DispatchEvent(&events.GuildChannelCreateEvent{ + GenericGuildChannelEvent: &events.GenericGuildChannelEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + ChannelID: channel.ID(), + Channel: guildChannel, + GuildID: guildChannel.GuildID(), + }, + }) + } else if dmChannel, ok := channel.(discord.DMChannel); ok { + client.EventManager().DispatchEvent(&events.DMChannelCreateEvent{ + GenericDMChannelEvent: &events.GenericDMChannelEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + ChannelID: channel.ID(), + Channel: dmChannel, + }, + }) + } +} diff --git a/gateway/handlers/channel_delete_handler.go b/gateway/handlers/channel_delete_handler.go new file mode 100644 index 00000000..dfc55555 --- /dev/null +++ b/gateway/handlers/channel_delete_handler.go @@ -0,0 +1,46 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerChannelDelete handles discord.GatewayEventTypeChannelDelete +type gatewayHandlerChannelDelete struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerChannelDelete) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeChannelDelete +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerChannelDelete) New() any { + return &discord.UnmarshalChannel{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerChannelDelete) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + channel := v.(*discord.UnmarshalChannel).Channel + + client.Caches().Channels().Remove(channel.ID()) + + if guildChannel, ok := channel.(discord.GuildChannel); ok { + client.EventManager().DispatchEvent(&events.GuildChannelDeleteEvent{ + GenericGuildChannelEvent: &events.GenericGuildChannelEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + ChannelID: channel.ID(), + Channel: guildChannel, + GuildID: guildChannel.GuildID(), + }, + }) + } else if dmChannel, ok := channel.(discord.DMChannel); ok { + client.EventManager().DispatchEvent(&events.DMChannelDeleteEvent{ + GenericDMChannelEvent: &events.GenericDMChannelEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + ChannelID: channel.ID(), + Channel: dmChannel, + }, + }) + } +} diff --git a/gateway/handlers/channel_pins_update_handler.go b/gateway/handlers/channel_pins_update_handler.go new file mode 100644 index 00000000..a202e450 --- /dev/null +++ b/gateway/handlers/channel_pins_update_handler.go @@ -0,0 +1,50 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerChannelPinsUpdate handles discord.GatewayEventTypeChannelPinsUpdate +type gatewayHandlerChannelPinsUpdate struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerChannelPinsUpdate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeChannelPinsUpdate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerChannelPinsUpdate) New() any { + return &discord.GatewayEventChannelPinsUpdate{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerChannelPinsUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventChannelPinsUpdate) + + var oldTime *discord.Time + channel, ok := client.Caches().Channels().GetMessageChannel(payload.ChannelID) + if ok { + // TODO: update channels last pinned timestamp + oldTime = channel.LastPinTimestamp() + } + + if payload.GuildID == nil { + client.EventManager().DispatchEvent(&events.DMChannelPinsUpdateEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + ChannelID: payload.ChannelID, + OldLastPinTimestamp: oldTime, + NewLastPinTimestamp: payload.LastPinTimestamp, + }) + } else { + client.EventManager().DispatchEvent(&events.GuildChannelPinsUpdateEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: *payload.GuildID, + ChannelID: payload.ChannelID, + OldLastPinTimestamp: oldTime, + NewLastPinTimestamp: payload.LastPinTimestamp, + }) + } + +} diff --git a/gateway/handlers/channel_update_handler.go b/gateway/handlers/channel_update_handler.go new file mode 100644 index 00000000..e1ae34f2 --- /dev/null +++ b/gateway/handlers/channel_update_handler.go @@ -0,0 +1,72 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerChannelUpdate handles core.GatewayEventChannelUpdate +type gatewayHandlerChannelUpdate struct{} + +// EventType returns the core.GatewayGatewayEventType +func (h *gatewayHandlerChannelUpdate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeChannelUpdate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerChannelUpdate) New() any { + return &discord.UnmarshalChannel{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerChannelUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + channel := v.(*discord.UnmarshalChannel).Channel + + if guildChannel, ok := channel.(discord.GuildChannel); ok { + oldGuildChannel, _ := client.Caches().Channels().GetGuildChannel(channel.ID()) + client.Caches().Channels().Put(channel.ID(), channel) + + client.EventManager().DispatchEvent(&events.GuildChannelUpdateEvent{ + GenericGuildChannelEvent: &events.GenericGuildChannelEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + ChannelID: channel.ID(), + Channel: guildChannel, + GuildID: guildChannel.GuildID(), + }, + OldChannel: oldGuildChannel, + }) + + if channel.Type() == discord.ChannelTypeGuildText || channel.Type() == discord.ChannelTypeGuildNews { + if member, ok := client.Caches().Members().Get(guildChannel.GuildID(), client.ID()); ok && + client.Caches().GetMemberPermissionsInChannel(guildChannel, member).Missing(discord.PermissionViewChannel) { + for _, guildThread := range client.Caches().Channels().GuildThreadsInChannel(channel.ID()) { + client.Caches().ThreadMembers().RemoveAll(guildThread.ID()) + client.Caches().Channels().Remove(guildThread.ID()) + client.EventManager().DispatchEvent(&events.ThreadHideEvent{ + GenericThreadEvent: &events.GenericThreadEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + Thread: guildThread, + ThreadID: guildThread.ID(), + GuildID: guildThread.GuildID(), + ParentID: *guildThread.ParentID(), + }, + }) + } + } + + } + } else if dmChannel, ok := channel.(discord.DMChannel); ok { + oldDMChannel, _ := client.Caches().Channels().GetDMChannel(channel.ID()) + client.Caches().Channels().Put(channel.ID(), channel) + + client.EventManager().DispatchEvent(&events.DMChannelUpdateEvent{ + GenericDMChannelEvent: &events.GenericDMChannelEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + ChannelID: channel.ID(), + Channel: dmChannel, + }, + OldChannel: oldDMChannel, + }) + } +} diff --git a/gateway/handlers/guild_ban_add_handler.go b/gateway/handlers/guild_ban_add_handler.go new file mode 100644 index 00000000..c5795245 --- /dev/null +++ b/gateway/handlers/guild_ban_add_handler.go @@ -0,0 +1,31 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerGuildBanAdd handles discord.GatewayEventTypeGuildBanAdd +type gatewayHandlerGuildBanAdd struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerGuildBanAdd) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeGuildBanAdd +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerGuildBanAdd) New() any { + return &discord.GatewayEventGuildBanAdd{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerGuildBanAdd) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventGuildBanAdd) + + client.EventManager().DispatchEvent(&events.GuildBanEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + User: payload.User, + }) +} diff --git a/gateway/handlers/guild_ban_remove_handler.go b/gateway/handlers/guild_ban_remove_handler.go new file mode 100644 index 00000000..9a1db7e5 --- /dev/null +++ b/gateway/handlers/guild_ban_remove_handler.go @@ -0,0 +1,31 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerGuildBanRemove handles discord.GatewayEventTypeGuildBanRemove +type gatewayHandlerGuildBanRemove struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerGuildBanRemove) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeGuildBanRemove +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerGuildBanRemove) New() any { + return &discord.GatewayEventGuildBanRemove{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerGuildBanRemove) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventGuildBanRemove) + + client.EventManager().DispatchEvent(&events.GuildUnbanEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + User: payload.User, + }) +} diff --git a/gateway/handlers/guild_create_handler.go b/gateway/handlers/guild_create_handler.go new file mode 100644 index 00000000..546f397e --- /dev/null +++ b/gateway/handlers/guild_create_handler.go @@ -0,0 +1,108 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerGuildCreate handles core.GuildCreateGatewayEvent +type gatewayHandlerGuildCreate struct{} + +// EventType returns the core.GatewayGatewayEventType +func (h *gatewayHandlerGuildCreate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeGuildCreate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerGuildCreate) New() any { + return &discord.GatewayGuild{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerGuildCreate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + gatewayGuild := *v.(*discord.GatewayGuild) + + shard, _ := client.Shard(gatewayGuild.ID) + shardID := shard.ShardID() + + wasUnready := client.Caches().Guilds().IsUnready(shardID, gatewayGuild.ID) + wasUnavailable := client.Caches().Guilds().IsUnavailable(gatewayGuild.ID) + + for _, channel := range gatewayGuild.Channels { + client.Caches().Channels().Put(channel.ID(), channel) + } + + for _, thread := range gatewayGuild.Threads { + client.Caches().Channels().Put(thread.ID(), thread) + } + + for _, role := range gatewayGuild.Roles { + client.Caches().Roles().Put(gatewayGuild.ID, role.ID, role) + } + + for _, member := range gatewayGuild.Members { + client.Caches().Members().Put(gatewayGuild.ID, member.User.ID, member) + } + + for _, voiceState := range gatewayGuild.VoiceStates { + voiceState.GuildID = gatewayGuild.ID // populate unset field + client.Caches().VoiceStates().Put(voiceState.GuildID, voiceState.UserID, voiceState) + } + + for _, emoji := range gatewayGuild.Emojis { + client.Caches().Emojis().Put(gatewayGuild.ID, emoji.ID, emoji) + } + + for _, sticker := range gatewayGuild.Stickers { + client.Caches().Stickers().Put(gatewayGuild.ID, sticker.ID, sticker) + } + + for _, stageInstance := range gatewayGuild.StageInstances { + client.Caches().StageInstances().Put(gatewayGuild.ID, stageInstance.ID, stageInstance) + } + + for _, guildScheduledEvent := range gatewayGuild.GuildScheduledEvents { + client.Caches().GuildScheduledEvents().Put(gatewayGuild.ID, guildScheduledEvent.ID, guildScheduledEvent) + } + + for _, presence := range gatewayGuild.Presences { + client.Caches().Presences().Put(gatewayGuild.ID, presence.PresenceUser.ID, presence) + } + + genericGuildEvent := &events.GenericGuildEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: gatewayGuild.ID, + Guild: gatewayGuild.Guild, + } + + if wasUnready { + client.Caches().Guilds().SetReady(shardID, gatewayGuild.ID) + client.EventManager().DispatchEvent(&events.GuildReadyEvent{ + GenericGuildEvent: genericGuildEvent, + }) + if len(client.Caches().Guilds().UnreadyGuilds(shardID)) == 0 { + client.EventManager().DispatchEvent(&events.GuildsReadyEvent{ + GenericEvent: events.NewGenericEvent(client, -1), + ShardID: shardID, + }) + } + if client.MemberChunkingManager().MemberChunkingFilter()(gatewayGuild.ID) { + go func() { + if _, err := client.MemberChunkingManager().RequestMembersWithQuery(gatewayGuild.ID, "", 0); err != nil { + client.Logger().Error("failed to chunk guild on guild_create. error: ", err) + } + }() + } + + } else if wasUnavailable { + client.Caches().Guilds().SetAvailable(gatewayGuild.ID) + client.EventManager().DispatchEvent(&events.GuildAvailableEvent{ + GenericGuildEvent: genericGuildEvent, + }) + } else { + client.EventManager().DispatchEvent(&events.GuildJoinEvent{ + GenericGuildEvent: genericGuildEvent, + }) + } +} diff --git a/gateway/handlers/guild_delete_handler.go b/gateway/handlers/guild_delete_handler.go new file mode 100644 index 00000000..5ef7f279 --- /dev/null +++ b/gateway/handlers/guild_delete_handler.go @@ -0,0 +1,67 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/snowflake" +) + +// gatewayHandlerGuildDelete handles discord.GatewayEventTypeGuildDelete +type gatewayHandlerGuildDelete struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerGuildDelete) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeGuildDelete +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerGuildDelete) New() any { + return &discord.UnavailableGuild{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerGuildDelete) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + unavailableGuild := *v.(*discord.UnavailableGuild) + + guild, _ := client.Caches().Guilds().Remove(unavailableGuild.ID) + client.Caches().VoiceStates().RemoveAll(unavailableGuild.ID) + client.Caches().Presences().RemoveAll(unavailableGuild.ID) + client.Caches().Channels().RemoveIf(func(channel discord.Channel) bool { + if guildChannel, ok := channel.(discord.GuildChannel); ok { + return guildChannel.GuildID() == unavailableGuild.ID + } + return false + }) + client.Caches().Emojis().RemoveAll(unavailableGuild.ID) + client.Caches().Stickers().RemoveAll(unavailableGuild.ID) + client.Caches().Roles().RemoveAll(unavailableGuild.ID) + client.Caches().StageInstances().RemoveAll(unavailableGuild.ID) + client.Caches().ThreadMembers().RemoveIf(func(groupID snowflake.Snowflake, threadMember discord.ThreadMember) bool { + // TODO: figure out how to remove thread members from cache via guild id + return false + }) + client.Caches().Messages().RemoveIf(func(channelID snowflake.Snowflake, message discord.Message) bool { + return message.GuildID != nil && *message.GuildID == unavailableGuild.ID + }) + + if unavailableGuild.Unavailable { + client.Caches().Guilds().SetUnavailable(unavailableGuild.ID) + } + + genericGuildEvent := &events.GenericGuildEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: unavailableGuild.ID, + Guild: guild, + } + + if unavailableGuild.Unavailable { + client.EventManager().DispatchEvent(&events.GuildUnavailableEvent{ + GenericGuildEvent: genericGuildEvent, + }) + } else { + client.EventManager().DispatchEvent(&events.GuildLeaveEvent{ + GenericGuildEvent: genericGuildEvent, + }) + } +} diff --git a/gateway/handlers/guild_emojis_update_handler.go b/gateway/handlers/guild_emojis_update_handler.go new file mode 100644 index 00000000..a82d70bc --- /dev/null +++ b/gateway/handlers/guild_emojis_update_handler.go @@ -0,0 +1,104 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/cache" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/snowflake" + "golang.org/x/exp/slices" +) + +// gatewayHandlerGuildEmojisUpdate handles discord.GatewayEventTypeGuildEmojisUpdate +type gatewayHandlerGuildEmojisUpdate struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerGuildEmojisUpdate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeGuildEmojisUpdate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerGuildEmojisUpdate) New() any { + return &discord.GatewayEventGuildEmojisUpdate{} +} + +type updatedEmoji struct { + old discord.Emoji + new discord.Emoji +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerGuildEmojisUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventGuildEmojisUpdate) + + client.EventManager().DispatchEvent(&events.EmojisUpdateEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + Emojis: payload.Emojis, + }) + + if client.Caches().CacheFlags().Missing(cache.FlagEmojis) { + return + } + + createdEmojis := map[snowflake.Snowflake]discord.Emoji{} + deletedEmojis := client.Caches().Emojis().MapGroupAll(payload.GuildID) + updatedEmojis := map[snowflake.Snowflake]updatedEmoji{} + + for _, newEmoji := range payload.Emojis { + oldEmoji, ok := deletedEmojis[newEmoji.ID] + if ok { + delete(deletedEmojis, newEmoji.ID) + if isEmojiUpdated(oldEmoji, newEmoji) { + updatedEmojis[newEmoji.ID] = updatedEmoji{new: newEmoji, old: oldEmoji} + } + continue + } + createdEmojis[newEmoji.ID] = newEmoji + } + + for _, emoji := range createdEmojis { + client.Caches().Emojis().Put(payload.GuildID, emoji.ID, emoji) + client.EventManager().DispatchEvent(&events.EmojiCreateEvent{ + GenericEmojiEvent: &events.GenericEmojiEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + Emoji: emoji, + }, + }) + } + + for _, emoji := range updatedEmojis { + client.Caches().Emojis().Put(payload.GuildID, emoji.new.ID, emoji.new) + client.EventManager().DispatchEvent(&events.EmojiUpdateEvent{ + GenericEmojiEvent: &events.GenericEmojiEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + Emoji: emoji.new, + }, + OldEmoji: emoji.old, + }) + } + + for _, emoji := range deletedEmojis { + client.Caches().Emojis().Remove(payload.GuildID, emoji.ID) + client.EventManager().DispatchEvent(&events.EmojiDeleteEvent{ + GenericEmojiEvent: &events.GenericEmojiEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + Emoji: emoji, + }, + }) + } + +} + +func isEmojiUpdated(old discord.Emoji, new discord.Emoji) bool { + if old.Name != new.Name { + return true + } + if !slices.Equal(old.Roles, new.Roles) { + return true + } + return false +} diff --git a/core/handlers/gateway_handler_guild_integrations_update.go b/gateway/handlers/guild_integrations_update_handler.go similarity index 54% rename from core/handlers/gateway_handler_guild_integrations_update.go rename to gateway/handlers/guild_integrations_update_handler.go index 9b29a2a9..a38736b5 100644 --- a/core/handlers/gateway_handler_guild_integrations_update.go +++ b/gateway/handlers/guild_integrations_update_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerGuildEmojisUpdate handles discord.GatewayEventTypeGuildIntegrationsUpdate @@ -15,16 +15,16 @@ func (h *gatewayHandlerGuildIntegrationsUpdate) EventType() discord.GatewayEvent } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildIntegrationsUpdate) New() interface{} { - return &discord.GuildIntegrationsUpdateGatewayEvent{} +func (h *gatewayHandlerGuildIntegrationsUpdate) New() any { + return &discord.GatewayEventGuildIntegrationsUpdate{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildIntegrationsUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildIntegrationsUpdateGatewayEvent) +func (h *gatewayHandlerGuildIntegrationsUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventGuildIntegrationsUpdate) - bot.EventManager.Dispatch(&events.GuildIntegrationsUpdateEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), + client.EventManager().DispatchEvent(&events.GuildIntegrationsUpdateEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), GuildID: payload.GuildID, }) } diff --git a/gateway/handlers/guild_member_add_handler.go b/gateway/handlers/guild_member_add_handler.go new file mode 100644 index 00000000..361b8df7 --- /dev/null +++ b/gateway/handlers/guild_member_add_handler.go @@ -0,0 +1,38 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerGuildMemberAdd handles discord.GatewayEventTypeGuildMemberAdd +type gatewayHandlerGuildMemberAdd struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerGuildMemberAdd) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeGuildMemberAdd +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerGuildMemberAdd) New() any { + return &discord.Member{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerGuildMemberAdd) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + member := *v.(*discord.Member) + + if guild, ok := client.Caches().Guilds().Get(member.GuildID); ok { + guild.MemberCount++ + client.Caches().Guilds().Put(guild.ID, guild) + } + + client.EventManager().DispatchEvent(&events.GuildMemberJoinEvent{ + GenericGuildMemberEvent: &events.GenericGuildMemberEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: member.GuildID, + Member: member, + }, + }) +} diff --git a/gateway/handlers/guild_member_remove_handler.go b/gateway/handlers/guild_member_remove_handler.go new file mode 100644 index 00000000..b9f3d015 --- /dev/null +++ b/gateway/handlers/guild_member_remove_handler.go @@ -0,0 +1,39 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerGuildMemberRemove handles discord.GatewayEventTypeGuildMemberRemove +type gatewayHandlerGuildMemberRemove struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerGuildMemberRemove) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeGuildMemberRemove +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerGuildMemberRemove) New() any { + return &discord.GatewayEventGuildMemberRemove{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerGuildMemberRemove) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventGuildMemberRemove) + + if guild, ok := client.Caches().Guilds().Get(payload.GuildID); ok { + guild.MemberCount-- + client.Caches().Guilds().Put(guild.ID, guild) + } + + member, _ := client.Caches().Members().Remove(payload.GuildID, payload.User.ID) + + client.EventManager().DispatchEvent(&events.GuildMemberLeaveEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + User: payload.User, + Member: member, + }) +} diff --git a/gateway/handlers/guild_member_update_handler.go b/gateway/handlers/guild_member_update_handler.go new file mode 100644 index 00000000..1aa1a582 --- /dev/null +++ b/gateway/handlers/guild_member_update_handler.go @@ -0,0 +1,37 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerGuildMemberUpdate handles discord.GatewayEventTypeGuildMemberUpdate +type gatewayHandlerGuildMemberUpdate struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerGuildMemberUpdate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeGuildMemberUpdate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerGuildMemberUpdate) New() any { + return &discord.Member{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerGuildMemberUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + member := *v.(*discord.Member) + + oldMember, _ := client.Caches().Members().Get(member.GuildID, member.User.ID) + client.Caches().Members().Put(member.GuildID, member.User.ID, member) + + client.EventManager().DispatchEvent(&events.GuildMemberUpdateEvent{ + GenericGuildMemberEvent: &events.GenericGuildMemberEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: member.GuildID, + Member: member, + }, + OldMember: oldMember, + }) +} diff --git a/core/handlers/gateway_handler_guild_members_chunk.go b/gateway/handlers/guild_members_chunk_handler.go similarity index 51% rename from core/handlers/gateway_handler_guild_members_chunk.go rename to gateway/handlers/guild_members_chunk_handler.go index 8c9d6236..e7fefc83 100644 --- a/core/handlers/gateway_handler_guild_members_chunk.go +++ b/gateway/handlers/guild_members_chunk_handler.go @@ -1,8 +1,8 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" ) // gatewayHandlerGuildMemberUpdate handles discord.GatewayEventTypeGuildMembersChunk @@ -14,15 +14,15 @@ func (h *gatewayHandlerGuildMembersChunk) EventType() discord.GatewayEventType { } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildMembersChunk) New() interface{} { - return &discord.GuildMembersChunkGatewayEvent{} +func (h *gatewayHandlerGuildMembersChunk) New() any { + return &discord.GatewayEventGuildMembersChunk{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildMembersChunk) HandleGatewayEvent(bot *core.Bot, _ discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildMembersChunkGatewayEvent) +func (h *gatewayHandlerGuildMembersChunk) HandleGatewayEvent(client bot.Client, _ int, v any) { + payload := *v.(*discord.GatewayEventGuildMembersChunk) - if bot.MemberChunkingManager != nil { - bot.MemberChunkingManager.HandleChunk(payload) + if client.MemberChunkingManager() != nil { + client.MemberChunkingManager().HandleChunk(payload) } } diff --git a/gateway/handlers/guild_role_create_handler.go b/gateway/handlers/guild_role_create_handler.go new file mode 100644 index 00000000..c2e9d1fe --- /dev/null +++ b/gateway/handlers/guild_role_create_handler.go @@ -0,0 +1,36 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerGuildRoleCreate handles discord.GatewayEventTypeGuildRoleCreate +type gatewayHandlerGuildRoleCreate struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerGuildRoleCreate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeGuildRoleCreate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerGuildRoleCreate) New() any { + return &discord.GatewayEventGuildRoleCreate{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerGuildRoleCreate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventGuildRoleCreate) + + client.Caches().Roles().Put(payload.GuildID, payload.Role.ID, payload.Role) + + client.EventManager().DispatchEvent(&events.RoleCreateEvent{ + GenericRoleEvent: &events.GenericRoleEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + RoleID: payload.Role.ID, + Role: payload.Role, + }, + }) +} diff --git a/gateway/handlers/guild_role_delete_handler.go b/gateway/handlers/guild_role_delete_handler.go new file mode 100644 index 00000000..2ce08981 --- /dev/null +++ b/gateway/handlers/guild_role_delete_handler.go @@ -0,0 +1,36 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerGuildRoleDelete handles discord.GatewayEventTypeGuildRoleDelete +type gatewayHandlerGuildRoleDelete struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerGuildRoleDelete) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeGuildRoleDelete +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerGuildRoleDelete) New() any { + return &discord.GatewayEventGuildRoleDelete{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerGuildRoleDelete) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventGuildRoleDelete) + + role, _ := client.Caches().Roles().Remove(payload.GuildID, payload.RoleID) + + client.EventManager().DispatchEvent(&events.RoleDeleteEvent{ + GenericRoleEvent: &events.GenericRoleEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + RoleID: payload.RoleID, + Role: role, + }, + }) +} diff --git a/gateway/handlers/guild_role_update_handler.go b/gateway/handlers/guild_role_update_handler.go new file mode 100644 index 00000000..ca80a28b --- /dev/null +++ b/gateway/handlers/guild_role_update_handler.go @@ -0,0 +1,38 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerGuildRoleUpdate handles discord.GatewayEventTypeGuildRoleUpdate +type gatewayHandlerGuildRoleUpdate struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerGuildRoleUpdate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeGuildRoleUpdate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerGuildRoleUpdate) New() any { + return &discord.GatewayEventGuildRoleUpdate{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerGuildRoleUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventGuildRoleUpdate) + + oldRole, _ := client.Caches().Roles().Get(payload.GuildID, payload.Role.ID) + client.Caches().Roles().Put(payload.GuildID, payload.Role.ID, payload.Role) + + client.EventManager().DispatchEvent(&events.RoleUpdateEvent{ + GenericRoleEvent: &events.GenericRoleEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + RoleID: payload.Role.ID, + Role: payload.Role, + }, + OldRole: oldRole, + }) +} diff --git a/core/handlers/gateway_handler_guild_scheduled_event_create.go b/gateway/handlers/guild_scheduled_event_create_handler.go similarity index 53% rename from core/handlers/gateway_handler_guild_scheduled_event_create.go rename to gateway/handlers/guild_scheduled_event_create_handler.go index c07f3ae0..96d03d1e 100644 --- a/core/handlers/gateway_handler_guild_scheduled_event_create.go +++ b/gateway/handlers/guild_scheduled_event_create_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerGuildRoleCreate handles discord.GatewayEventTypeGuildRoleCreate @@ -15,18 +15,20 @@ func (h *gatewayHandlerGuildScheduledEventCreate) EventType() discord.GatewayEve } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildScheduledEventCreate) New() interface{} { +func (h *gatewayHandlerGuildScheduledEventCreate) New() any { return &discord.GuildScheduledEvent{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildScheduledEventCreate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildScheduledEvent) +func (h *gatewayHandlerGuildScheduledEventCreate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + guildScheduledEvent := *v.(*discord.GuildScheduledEvent) - bot.EventManager.Dispatch(&events.GuildScheduledEventCreateEvent{ + client.Caches().GuildScheduledEvents().Put(guildScheduledEvent.GuildID, guildScheduledEvent.ID, guildScheduledEvent) + + client.EventManager().DispatchEvent(&events.GuildScheduledEventCreateEvent{ GenericGuildScheduledEventEvent: &events.GenericGuildScheduledEventEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildScheduledEvent: bot.EntityBuilder.CreateGuildScheduledEvent(payload, core.CacheStrategyYes), + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildScheduledEvent: guildScheduledEvent, }, }) } diff --git a/core/handlers/gateway_handler_guild_scheduled_event_delete.go b/gateway/handlers/guild_scheduled_event_delete_handler.go similarity index 53% rename from core/handlers/gateway_handler_guild_scheduled_event_delete.go rename to gateway/handlers/guild_scheduled_event_delete_handler.go index 7f0b72d5..a609f44e 100644 --- a/core/handlers/gateway_handler_guild_scheduled_event_delete.go +++ b/gateway/handlers/guild_scheduled_event_delete_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerGuildRoleCreate handles discord.GatewayEventTypeGuildRoleCreate @@ -15,20 +15,20 @@ func (h *gatewayHandlerGuildScheduledEventDelete) EventType() discord.GatewayEve } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildScheduledEventDelete) New() interface{} { +func (h *gatewayHandlerGuildScheduledEventDelete) New() any { return &discord.GuildScheduledEvent{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildScheduledEventDelete) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildScheduledEvent) +func (h *gatewayHandlerGuildScheduledEventDelete) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + guildScheduledEvent := *v.(*discord.GuildScheduledEvent) - bot.Caches.GuildScheduledEvents().Remove(payload.ID) + client.Caches().GuildScheduledEvents().Remove(guildScheduledEvent.GuildID, guildScheduledEvent.ID) - bot.EventManager.Dispatch(&events.GuildScheduledEventDeleteEvent{ + client.EventManager().DispatchEvent(&events.GuildScheduledEventDeleteEvent{ GenericGuildScheduledEventEvent: &events.GenericGuildScheduledEventEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildScheduledEvent: bot.EntityBuilder.CreateGuildScheduledEvent(payload, core.CacheStrategyNo), + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildScheduledEvent: guildScheduledEvent, }, }) } diff --git a/core/handlers/gateway_handler_guild_scheduled_event_update.go b/gateway/handlers/guild_scheduled_event_update_handler.go similarity index 50% rename from core/handlers/gateway_handler_guild_scheduled_event_update.go rename to gateway/handlers/guild_scheduled_event_update_handler.go index a742a90e..687d171b 100644 --- a/core/handlers/gateway_handler_guild_scheduled_event_update.go +++ b/gateway/handlers/guild_scheduled_event_update_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerGuildRoleCreate handles discord.GatewayEventTypeGuildRoleCreate @@ -15,20 +15,21 @@ func (h *gatewayHandlerGuildScheduledEventUpdate) EventType() discord.GatewayEve } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildScheduledEventUpdate) New() interface{} { +func (h *gatewayHandlerGuildScheduledEventUpdate) New() any { return &discord.GuildScheduledEvent{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildScheduledEventUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildScheduledEvent) +func (h *gatewayHandlerGuildScheduledEventUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + guildScheduledEvent := *v.(*discord.GuildScheduledEvent) - oldGuildScheduledEvent := bot.Caches.GuildScheduledEvents().GetCopy(payload.ID) + oldGuildScheduledEvent, _ := client.Caches().GuildScheduledEvents().Get(guildScheduledEvent.GuildID, guildScheduledEvent.ID) + client.Caches().GuildScheduledEvents().Put(guildScheduledEvent.GuildID, guildScheduledEvent.ID, guildScheduledEvent) - bot.EventManager.Dispatch(&events.GuildScheduledEventUpdateEvent{ + client.EventManager().DispatchEvent(&events.GuildScheduledEventUpdateEvent{ GenericGuildScheduledEventEvent: &events.GenericGuildScheduledEventEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - GuildScheduledEvent: bot.EntityBuilder.CreateGuildScheduledEvent(payload, core.CacheStrategyYes), + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildScheduledEvent: guildScheduledEvent, }, OldGuildScheduledEvent: oldGuildScheduledEvent, }) diff --git a/core/handlers/gateway_handler_guild_scheduled_event_user_add.go b/gateway/handlers/guild_scheduled_event_user_add_handler.go similarity index 61% rename from core/handlers/gateway_handler_guild_scheduled_event_user_add.go rename to gateway/handlers/guild_scheduled_event_user_add_handler.go index 889f55b5..18dc4311 100644 --- a/core/handlers/gateway_handler_guild_scheduled_event_user_add.go +++ b/gateway/handlers/guild_scheduled_event_user_add_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerGuildRoleCreate handles discord.GatewayEventTypeGuildRoleCreate @@ -15,17 +15,17 @@ func (h *gatewayHandlerGuildScheduledEventUserAdd) EventType() discord.GatewayEv } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildScheduledEventUserAdd) New() interface{} { - return &discord.GuildScheduledEventUserEvent{} +func (h *gatewayHandlerGuildScheduledEventUserAdd) New() any { + return &discord.GatewayEventGuildScheduledEventUser{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildScheduledEventUserAdd) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildScheduledEventUserEvent) +func (h *gatewayHandlerGuildScheduledEventUserAdd) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventGuildScheduledEventUser) - bot.EventManager.Dispatch(&events.GuildScheduledEventUserAddEvent{ + client.EventManager().DispatchEvent(&events.GuildScheduledEventUserAddEvent{ GenericGuildScheduledEventUserEvent: &events.GenericGuildScheduledEventUserEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), + GenericEvent: events.NewGenericEvent(client, sequenceNumber), GuildScheduledEventID: payload.GuildScheduledEventID, UserID: payload.UserID, GuildID: payload.GuildID, diff --git a/core/handlers/gateway_handler_guild_scheduled_event_user_remove.go b/gateway/handlers/guild_scheduled_event_user_remove_handler.go similarity index 61% rename from core/handlers/gateway_handler_guild_scheduled_event_user_remove.go rename to gateway/handlers/guild_scheduled_event_user_remove_handler.go index 8bfdaf5d..4d06da7e 100644 --- a/core/handlers/gateway_handler_guild_scheduled_event_user_remove.go +++ b/gateway/handlers/guild_scheduled_event_user_remove_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerGuildRoleCreate handles discord.GatewayEventTypeGuildRoleCreate @@ -15,17 +15,17 @@ func (h *gatewayHandlerGuildScheduledEventUserRemove) EventType() discord.Gatewa } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildScheduledEventUserRemove) New() interface{} { - return &discord.GuildScheduledEventUserEvent{} +func (h *gatewayHandlerGuildScheduledEventUserRemove) New() any { + return &discord.GatewayEventGuildScheduledEventUser{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildScheduledEventUserRemove) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.GuildScheduledEventUserEvent) +func (h *gatewayHandlerGuildScheduledEventUserRemove) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventGuildScheduledEventUser) - bot.EventManager.Dispatch(&events.GuildScheduledEventUserRemoveEvent{ + client.EventManager().DispatchEvent(&events.GuildScheduledEventUserRemoveEvent{ GenericGuildScheduledEventUserEvent: &events.GenericGuildScheduledEventUserEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), + GenericEvent: events.NewGenericEvent(client, sequenceNumber), GuildScheduledEventID: payload.GuildScheduledEventID, UserID: payload.UserID, GuildID: payload.GuildID, diff --git a/gateway/handlers/guild_stickers_update_handler.go b/gateway/handlers/guild_stickers_update_handler.go new file mode 100644 index 00000000..24c4aa5b --- /dev/null +++ b/gateway/handlers/guild_stickers_update_handler.go @@ -0,0 +1,102 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/cache" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/snowflake" +) + +// gatewayHandlerGuildStickersUpdate handles discord.GatewayEventTypeGuildStickersUpdate +type gatewayHandlerGuildStickersUpdate struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerGuildStickersUpdate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeGuildStickersUpdate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerGuildStickersUpdate) New() any { + return &discord.GatewayEventGuildStickersUpdate{} +} + +type updatedSticker struct { + old discord.Sticker + new discord.Sticker +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerGuildStickersUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventGuildStickersUpdate) + + client.EventManager().DispatchEvent(&events.StickersUpdateEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + Stickers: payload.Stickers, + }) + + if client.Caches().CacheFlags().Missing(cache.FlagStickers) { + return + } + + createdStickers := map[snowflake.Snowflake]discord.Sticker{} + deletedStickers := client.Caches().Stickers().MapGroupAll(payload.GuildID) + updatedStickers := map[snowflake.Snowflake]updatedSticker{} + + for _, newSticker := range payload.Stickers { + oldSticker, ok := deletedStickers[newSticker.ID] + if ok { + delete(deletedStickers, newSticker.ID) + if isStickerUpdated(oldSticker, newSticker) { + updatedStickers[newSticker.ID] = updatedSticker{new: newSticker, old: oldSticker} + } + continue + } + createdStickers[newSticker.ID] = newSticker + } + + for _, emoji := range createdStickers { + client.EventManager().DispatchEvent(&events.StickerCreateEvent{ + GenericStickerEvent: &events.GenericStickerEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + Sticker: emoji, + }, + }) + } + + for _, emoji := range updatedStickers { + client.EventManager().DispatchEvent(&events.StickerUpdateEvent{ + GenericStickerEvent: &events.GenericStickerEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + Sticker: emoji.new, + }, + OldSticker: emoji.old, + }) + } + + for _, emoji := range deletedStickers { + client.EventManager().DispatchEvent(&events.StickerDeleteEvent{ + GenericStickerEvent: &events.GenericStickerEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + Sticker: emoji, + }, + }) + } +} + +func isStickerUpdated(old discord.Sticker, new discord.Sticker) bool { + if old.Name != new.Name { + return true + } + if old.Description != new.Description { + return true + } + if old.Tags != new.Tags { + return true + } + return false +} diff --git a/core/handlers/gateway_handler_guild_update.go b/gateway/handlers/guild_update_handler.go similarity index 52% rename from core/handlers/gateway_handler_guild_update.go rename to gateway/handlers/guild_update_handler.go index 7ab64a16..22cda0f4 100644 --- a/core/handlers/gateway_handler_guild_update.go +++ b/gateway/handlers/guild_update_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerGuildUpdate handles discord.GatewayEventTypeGuildUpdate @@ -15,20 +15,21 @@ func (h *gatewayHandlerGuildUpdate) EventType() discord.GatewayEventType { } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerGuildUpdate) New() interface{} { +func (h *gatewayHandlerGuildUpdate) New() any { return &discord.Guild{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerGuildUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { +func (h *gatewayHandlerGuildUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { guild := *v.(*discord.Guild) - oldGuild := bot.Caches.Guilds().GetCopy(guild.ID) + oldGuild, _ := client.Caches().Guilds().Get(guild.ID) + client.Caches().Guilds().Put(guild.ID, guild) - bot.EventManager.Dispatch(&events.GuildUpdateEvent{ + client.EventManager().DispatchEvent(&events.GuildUpdateEvent{ GenericGuildEvent: &events.GenericGuildEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), - Guild: bot.EntityBuilder.CreateGuild(guild, core.CacheStrategyYes), + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + Guild: guild, }, OldGuild: oldGuild, }) diff --git a/gateway/handlers/integration_create_handler.go b/gateway/handlers/integration_create_handler.go new file mode 100644 index 00000000..98a5977e --- /dev/null +++ b/gateway/handlers/integration_create_handler.go @@ -0,0 +1,33 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerGuildBanAdd handles discord.GatewayEventTypeIntegrationCreate +type gatewayHandlerIntegrationCreate struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerIntegrationCreate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeIntegrationCreate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerIntegrationCreate) New() any { + return &discord.GatewayEventIntegrationCreate{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerIntegrationCreate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventIntegrationCreate) + + client.EventManager().DispatchEvent(&events.IntegrationCreateEvent{ + GenericIntegrationEvent: &events.GenericIntegrationEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + Integration: payload.Integration, + }, + }) +} diff --git a/core/handlers/gateway_handler_integration_delete.go b/gateway/handlers/integration_delete_handler.go similarity index 52% rename from core/handlers/gateway_handler_integration_delete.go rename to gateway/handlers/integration_delete_handler.go index b744c856..b55188d8 100644 --- a/core/handlers/gateway_handler_integration_delete.go +++ b/gateway/handlers/integration_delete_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerGuildBanAdd handles discord.GatewayEventTypeIntegrationDelete @@ -15,16 +15,16 @@ func (h *gatewayHandlerIntegrationDelete) EventType() discord.GatewayEventType { } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerIntegrationDelete) New() interface{} { - return &discord.IntegrationDeleteGatewayEvent{} +func (h *gatewayHandlerIntegrationDelete) New() any { + return &discord.GatewayEventIntegrationDelete{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerIntegrationDelete) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.IntegrationDeleteGatewayEvent) +func (h *gatewayHandlerIntegrationDelete) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventIntegrationDelete) - bot.EventManager.Dispatch(&events.IntegrationDeleteEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), + client.EventManager().DispatchEvent(&events.IntegrationDeleteEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), GuildID: payload.GuildID, ID: payload.ID, ApplicationID: payload.ApplicationID, diff --git a/gateway/handlers/integration_update_handler.go b/gateway/handlers/integration_update_handler.go new file mode 100644 index 00000000..c6c9ec7c --- /dev/null +++ b/gateway/handlers/integration_update_handler.go @@ -0,0 +1,33 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerGuildBanAdd handles discord.GatewayEventTypeIntegrationUpdate +type gatewayHandlerIntegrationUpdate struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerIntegrationUpdate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeIntegrationUpdate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerIntegrationUpdate) New() any { + return &discord.GatewayEventIntegrationCreate{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerIntegrationUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventIntegrationUpdate) + + client.EventManager().DispatchEvent(&events.IntegrationUpdateEvent{ + GenericIntegrationEvent: &events.GenericIntegrationEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + Integration: payload.Integration, + }, + }) +} diff --git a/gateway/handlers/interaction_create_handler.go b/gateway/handlers/interaction_create_handler.go new file mode 100644 index 00000000..1e94c14d --- /dev/null +++ b/gateway/handlers/interaction_create_handler.go @@ -0,0 +1,84 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/disgo/rest" +) + +// gatewayHandlerInteractionCreate handles core.InteractionCreateGatewayEvent +type gatewayHandlerInteractionCreate struct{} + +// EventType returns the core.GatewayGatewayEventType +func (h *gatewayHandlerInteractionCreate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeInteractionCreate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerInteractionCreate) New() any { + return &discord.UnmarshalInteraction{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerInteractionCreate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + HandleInteraction(client, sequenceNumber, nil, (*v.(*discord.UnmarshalInteraction)).Interaction) +} + +func respond(client bot.Client, c chan<- discord.InteractionResponse, interaction discord.BaseInteraction) events.InteractionResponderFunc { + return func(callbackType discord.InteractionCallbackType, data discord.InteractionCallbackData, opts ...rest.RequestOpt) error { + response := discord.InteractionResponse{ + Type: callbackType, + Data: data, + } + if c != nil { + c <- response + return nil + } + return client.Rest().Interactions().CreateInteractionResponse(interaction.ID(), interaction.Token(), response, opts...) + } +} + +func HandleInteraction(client bot.Client, sequenceNumber int, c chan<- discord.InteractionResponse, interaction discord.Interaction) { + + genericEvent := events.NewGenericEvent(client, sequenceNumber) + + client.EventManager().DispatchEvent(&events.InteractionEvent{ + GenericEvent: genericEvent, + Interaction: interaction, + Respond: respond(client, c, interaction), + }) + + switch i := interaction.(type) { + case discord.ApplicationCommandInteraction: + client.EventManager().DispatchEvent(&events.ApplicationCommandInteractionEvent{ + GenericEvent: genericEvent, + ApplicationCommandInteraction: i, + Respond: respond(client, c, interaction), + }) + + case discord.ComponentInteraction: + client.EventManager().DispatchEvent(&events.ComponentInteractionEvent{ + GenericEvent: genericEvent, + ComponentInteraction: i, + Respond: respond(client, c, interaction), + }) + + case discord.AutocompleteInteraction: + client.EventManager().DispatchEvent(&events.AutocompleteInteractionEvent{ + GenericEvent: genericEvent, + AutocompleteInteraction: i, + Respond: respond(client, c, interaction), + }) + + case discord.ModalSubmitInteraction: + client.EventManager().DispatchEvent(&events.ModalSubmitInteractionEvent{ + GenericEvent: genericEvent, + ModalSubmitInteraction: i, + Respond: respond(client, c, interaction), + }) + + default: + client.Logger().Errorf("unknown interaction with type %d received", interaction.Type()) + } +} diff --git a/gateway/handlers/interaction_create_http_handler.go b/gateway/handlers/interaction_create_http_handler.go new file mode 100644 index 00000000..001ee769 --- /dev/null +++ b/gateway/handlers/interaction_create_http_handler.go @@ -0,0 +1,29 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" +) + +var _ bot.HTTPServerEventHandler = (*httpserverHandlerInteractionCreate)(nil) + +type httpserverHandlerInteractionCreate struct{} + +func (h *httpserverHandlerInteractionCreate) New() any { + return &discord.UnmarshalInteraction{} +} + +func (h *httpserverHandlerInteractionCreate) HandleHTTPEvent(client bot.Client, c chan<- discord.InteractionResponse, v any) { + interaction := (*v.(*discord.UnmarshalInteraction)).Interaction + + // we just want to pong all pings + // no need for any event + if interaction.Type() == discord.InteractionTypePing { + client.Logger().Debug("received http interaction ping. responding with pong") + c <- discord.InteractionResponse{ + Type: discord.InteractionCallbackTypePong, + } + return + } + HandleInteraction(client, -1, c, interaction) +} diff --git a/gateway/handlers/invite_create_handler.go b/gateway/handlers/invite_create_handler.go new file mode 100644 index 00000000..9fed80ec --- /dev/null +++ b/gateway/handlers/invite_create_handler.go @@ -0,0 +1,41 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/snowflake" +) + +// gatewayHandlerInviteCreate handles discord.GatewayEventTypeInviteCreate +type gatewayHandlerInviteCreate struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerInviteCreate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeInviteCreate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerInviteCreate) New() any { + return &discord.Invite{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerInviteCreate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + invite := *v.(*discord.Invite) + + var guildID *snowflake.Snowflake + if invite.Guild != nil { + guildID = &invite.Guild.ID + } + + client.EventManager().DispatchEvent(&events.InviteCreateEvent{ + GenericInviteEvent: &events.GenericInviteEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: guildID, + Code: invite.Code, + ChannelID: invite.ChannelID, + }, + Invite: invite, + }) +} diff --git a/gateway/handlers/invite_delete_handler.go b/gateway/handlers/invite_delete_handler.go new file mode 100644 index 00000000..98f12473 --- /dev/null +++ b/gateway/handlers/invite_delete_handler.go @@ -0,0 +1,34 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerInviteDelete handles discord.GatewayEventTypeInviteDelete +type gatewayHandlerInviteDelete struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerInviteDelete) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeInviteDelete +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerInviteDelete) New() any { + return &discord.GatewayEventInviteDelete{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerInviteDelete) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventInviteDelete) + + client.EventManager().DispatchEvent(&events.InviteDeleteEvent{ + GenericInviteEvent: &events.GenericInviteEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + GuildID: payload.GuildID, + ChannelID: payload.ChannelID, + Code: payload.Code, + }, + }) +} diff --git a/gateway/handlers/message_create_handler.go b/gateway/handlers/message_create_handler.go new file mode 100644 index 00000000..76f61114 --- /dev/null +++ b/gateway/handlers/message_create_handler.go @@ -0,0 +1,60 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerMessageCreate handles discord.GatewayEventTypeMessageCreate +type gatewayHandlerMessageCreate struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerMessageCreate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeMessageCreate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerMessageCreate) New() any { + return &discord.Message{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerMessageCreate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + message := *v.(*discord.Message) + + client.Caches().Messages().Put(message.ChannelID, message.ID, message) + + genericEvent := events.NewGenericEvent(client, sequenceNumber) + client.EventManager().DispatchEvent(&events.MessageCreateEvent{ + GenericMessageEvent: &events.GenericMessageEvent{ + GenericEvent: genericEvent, + MessageID: message.ID, + Message: message, + ChannelID: message.ChannelID, + GuildID: message.GuildID, + }, + }) + + if message.GuildID == nil { + client.EventManager().DispatchEvent(&events.DMMessageCreateEvent{ + GenericDMMessageEvent: &events.GenericDMMessageEvent{ + GenericEvent: genericEvent, + MessageID: message.ID, + Message: message, + ChannelID: message.ChannelID, + }, + }) + } else { + client.EventManager().DispatchEvent(&events.GuildMessageCreateEvent{ + GenericGuildMessageEvent: &events.GenericGuildMessageEvent{ + GenericEvent: genericEvent, + MessageID: message.ID, + Message: message, + ChannelID: message.ChannelID, + GuildID: *message.GuildID, + }, + }) + } + +} diff --git a/core/handlers/gateway_handler_message_delete_bulk.go b/gateway/handlers/message_delete_bulk_handler.go similarity index 53% rename from core/handlers/gateway_handler_message_delete_bulk.go rename to gateway/handlers/message_delete_bulk_handler.go index 04e06de9..952695a4 100644 --- a/core/handlers/gateway_handler_message_delete_bulk.go +++ b/gateway/handlers/message_delete_bulk_handler.go @@ -1,8 +1,8 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" ) // gatewayHandlerMessageDelete handles discord.GatewayEventTypeMessageDeleteBulk @@ -14,15 +14,15 @@ func (h *gatewayHandlerMessageDeleteBulk) EventType() discord.GatewayEventType { } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerMessageDeleteBulk) New() interface{} { - return &discord.MessageDeleteBulkGatewayEvent{} +func (h *gatewayHandlerMessageDeleteBulk) New() any { + return &discord.GatewayEventMessageDeleteBulk{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerMessageDeleteBulk) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.MessageDeleteBulkGatewayEvent) +func (h *gatewayHandlerMessageDeleteBulk) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventMessageDeleteBulk) for _, messageID := range payload.IDs { - handleMessageDelete(bot, sequenceNumber, messageID, payload.ChannelID, payload.GuildID) + handleMessageDelete(client, sequenceNumber, messageID, payload.ChannelID, payload.GuildID) } } diff --git a/core/handlers/gateway_handler_message_delete.go b/gateway/handlers/message_delete_handler.go similarity index 50% rename from core/handlers/gateway_handler_message_delete.go rename to gateway/handlers/message_delete_handler.go index 0ef9f0d3..c4eca3a8 100644 --- a/core/handlers/gateway_handler_message_delete.go +++ b/gateway/handlers/message_delete_handler.go @@ -1,10 +1,10 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" + "github.com/disgoorg/snowflake" ) // gatewayHandlerMessageDelete handles discord.GatewayEventTypeMessageDelete @@ -16,24 +16,23 @@ func (h *gatewayHandlerMessageDelete) EventType() discord.GatewayEventType { } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerMessageDelete) New() interface{} { - return &discord.MessageDeleteGatewayEvent{} +func (h *gatewayHandlerMessageDelete) New() any { + return &discord.GatewayEventMessageDelete{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerMessageDelete) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.MessageDeleteGatewayEvent) +func (h *gatewayHandlerMessageDelete) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventMessageDelete) - handleMessageDelete(bot, sequenceNumber, payload.ID, payload.ChannelID, payload.GuildID) + handleMessageDelete(client, sequenceNumber, payload.ID, payload.ChannelID, payload.GuildID) } -func handleMessageDelete(bot *core.Bot, sequenceNumber discord.GatewaySequence, messageID snowflake.Snowflake, channelID snowflake.Snowflake, guildID *snowflake.Snowflake) { - genericEvent := events.NewGenericEvent(bot, sequenceNumber) +func handleMessageDelete(client bot.Client, sequenceNumber int, messageID snowflake.Snowflake, channelID snowflake.Snowflake, guildID *snowflake.Snowflake) { + genericEvent := events.NewGenericEvent(client, sequenceNumber) - message := bot.Caches.Messages().GetCopy(channelID, messageID) - bot.Caches.Messages().Remove(channelID, messageID) + message, _ := client.Caches().Messages().Remove(channelID, messageID) - bot.EventManager.Dispatch(&events.MessageDeleteEvent{ + client.EventManager().DispatchEvent(&events.MessageDeleteEvent{ GenericMessageEvent: &events.GenericMessageEvent{ GenericEvent: genericEvent, MessageID: messageID, @@ -43,7 +42,7 @@ func handleMessageDelete(bot *core.Bot, sequenceNumber discord.GatewaySequence, }) if guildID == nil { - bot.EventManager.Dispatch(&events.DMMessageDeleteEvent{ + client.EventManager().DispatchEvent(&events.DMMessageDeleteEvent{ GenericDMMessageEvent: &events.GenericDMMessageEvent{ GenericEvent: genericEvent, MessageID: messageID, @@ -52,7 +51,7 @@ func handleMessageDelete(bot *core.Bot, sequenceNumber discord.GatewaySequence, }, }) } else { - bot.EventManager.Dispatch(&events.GuildMessageDeleteEvent{ + client.EventManager().DispatchEvent(&events.GuildMessageDeleteEvent{ GenericGuildMessageEvent: &events.GenericGuildMessageEvent{ GenericEvent: genericEvent, MessageID: messageID, diff --git a/core/handlers/gateway_handler_message_reaction_add.go b/gateway/handlers/message_reaction_add_handler.go similarity index 67% rename from core/handlers/gateway_handler_message_reaction_add.go rename to gateway/handlers/message_reaction_add_handler.go index d73d1f35..fce85996 100644 --- a/core/handlers/gateway_handler_message_reaction_add.go +++ b/gateway/handlers/message_reaction_add_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerMessageUpdate handles discord.GatewayEventTypeMessageReactionAdd @@ -15,22 +15,21 @@ func (h *gatewayHandlerMessageReactionAdd) EventType() discord.GatewayEventType } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerMessageReactionAdd) New() interface{} { +func (h *gatewayHandlerMessageReactionAdd) New() any { return &discord.GatewayEventMessageReactionAdd{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerMessageReactionAdd) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { +func (h *gatewayHandlerMessageReactionAdd) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { payload := *v.(*discord.GatewayEventMessageReactionAdd) - genericEvent := events.NewGenericEvent(bot, sequenceNumber) + genericEvent := events.NewGenericEvent(client, sequenceNumber) - var member *core.Member if payload.Member != nil { - member = bot.EntityBuilder.CreateMember(*payload.GuildID, *payload.Member, core.CacheStrategyYes) + client.Caches().Members().Put(*payload.GuildID, payload.UserID, *payload.Member) } - bot.EventManager.Dispatch(&events.MessageReactionAddEvent{ + client.EventManager().DispatchEvent(&events.MessageReactionAddEvent{ GenericReactionEvent: &events.GenericReactionEvent{ GenericEvent: genericEvent, MessageID: payload.MessageID, @@ -39,11 +38,11 @@ func (h *gatewayHandlerMessageReactionAdd) HandleGatewayEvent(bot *core.Bot, seq UserID: payload.UserID, Emoji: payload.Emoji, }, - Member: member, + Member: payload.Member, }) if payload.GuildID == nil { - bot.EventManager.Dispatch(&events.DMMessageReactionAddEvent{ + client.EventManager().DispatchEvent(&events.DMMessageReactionAddEvent{ GenericDMMessageReactionEvent: &events.GenericDMMessageReactionEvent{ GenericEvent: genericEvent, MessageID: payload.MessageID, @@ -53,7 +52,7 @@ func (h *gatewayHandlerMessageReactionAdd) HandleGatewayEvent(bot *core.Bot, seq }, }) } else { - bot.EventManager.Dispatch(&events.GuildMessageReactionAddEvent{ + client.EventManager().DispatchEvent(&events.GuildMessageReactionAddEvent{ GenericGuildMessageReactionEvent: &events.GenericGuildMessageReactionEvent{ GenericEvent: genericEvent, MessageID: payload.MessageID, @@ -62,7 +61,7 @@ func (h *gatewayHandlerMessageReactionAdd) HandleGatewayEvent(bot *core.Bot, seq UserID: payload.UserID, Emoji: payload.Emoji, }, - Member: member, + Member: *payload.Member, }) } } diff --git a/core/handlers/gateway_handler_message_reaction_remove_all.go b/gateway/handlers/message_reaction_remove_all_handler.go similarity index 69% rename from core/handlers/gateway_handler_message_reaction_remove_all.go rename to gateway/handlers/message_reaction_remove_all_handler.go index a7932d1e..15a5f062 100644 --- a/core/handlers/gateway_handler_message_reaction_remove_all.go +++ b/gateway/handlers/message_reaction_remove_all_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerMessageUpdate handles discord.GatewayEventTypeMessageReactionRemoveAll @@ -15,17 +15,17 @@ func (h *gatewayHandlerMessageReactionRemoveAll) EventType() discord.GatewayEven } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerMessageReactionRemoveAll) New() interface{} { +func (h *gatewayHandlerMessageReactionRemoveAll) New() any { return &discord.GatewayEventMessageReactionRemoveAll{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerMessageReactionRemoveAll) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { +func (h *gatewayHandlerMessageReactionRemoveAll) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { messageReaction := *v.(*discord.GatewayEventMessageReactionRemoveAll) - genericEvent := events.NewGenericEvent(bot, sequenceNumber) + genericEvent := events.NewGenericEvent(client, sequenceNumber) - bot.EventManager.Dispatch(&events.MessageReactionRemoveAllEvent{ + client.EventManager().DispatchEvent(&events.MessageReactionRemoveAllEvent{ GenericEvent: genericEvent, MessageID: messageReaction.MessageID, ChannelID: messageReaction.ChannelID, @@ -33,13 +33,13 @@ func (h *gatewayHandlerMessageReactionRemoveAll) HandleGatewayEvent(bot *core.Bo }) if messageReaction.GuildID == nil { - bot.EventManager.Dispatch(&events.DMMessageReactionRemoveAllEvent{ + client.EventManager().DispatchEvent(&events.DMMessageReactionRemoveAllEvent{ GenericEvent: genericEvent, MessageID: messageReaction.MessageID, ChannelID: messageReaction.ChannelID, }) } else { - bot.EventManager.Dispatch(&events.GuildMessageReactionRemoveAllEvent{ + client.EventManager().DispatchEvent(&events.GuildMessageReactionRemoveAllEvent{ GenericEvent: genericEvent, MessageID: messageReaction.MessageID, ChannelID: messageReaction.ChannelID, diff --git a/core/handlers/gateway_handler_message_reaction_remove_emoji.go b/gateway/handlers/message_reaction_remove_emoji_handler.go similarity index 69% rename from core/handlers/gateway_handler_message_reaction_remove_emoji.go rename to gateway/handlers/message_reaction_remove_emoji_handler.go index 7fb8a4d3..1f415005 100644 --- a/core/handlers/gateway_handler_message_reaction_remove_emoji.go +++ b/gateway/handlers/message_reaction_remove_emoji_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerMessageUpdate handles discord.GatewayEventTypeMessageReactionRemoveEmoji @@ -15,17 +15,17 @@ func (h *gatewayHandlerMessageReactionRemoveEmoji) EventType() discord.GatewayEv } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerMessageReactionRemoveEmoji) New() interface{} { +func (h *gatewayHandlerMessageReactionRemoveEmoji) New() any { return &discord.GatewayEventMessageReactionRemoveEmoji{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerMessageReactionRemoveEmoji) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { +func (h *gatewayHandlerMessageReactionRemoveEmoji) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { payload := *v.(*discord.GatewayEventMessageReactionRemoveEmoji) - genericEvent := events.NewGenericEvent(bot, sequenceNumber) + genericEvent := events.NewGenericEvent(client, sequenceNumber) - bot.EventManager.Dispatch(&events.MessageReactionRemoveEmojiEvent{ + client.EventManager().DispatchEvent(&events.MessageReactionRemoveEmojiEvent{ GenericEvent: genericEvent, MessageID: payload.MessageID, ChannelID: payload.ChannelID, @@ -34,14 +34,14 @@ func (h *gatewayHandlerMessageReactionRemoveEmoji) HandleGatewayEvent(bot *core. }) if payload.GuildID == nil { - bot.EventManager.Dispatch(&events.DMMessageReactionRemoveEmojiEvent{ + client.EventManager().DispatchEvent(&events.DMMessageReactionRemoveEmojiEvent{ GenericEvent: genericEvent, MessageID: payload.MessageID, ChannelID: payload.ChannelID, Emoji: payload.Emoji, }) } else { - bot.EventManager.Dispatch(&events.GuildMessageReactionRemoveEmojiEvent{ + client.EventManager().DispatchEvent(&events.GuildMessageReactionRemoveEmojiEvent{ GenericEvent: genericEvent, MessageID: payload.MessageID, ChannelID: payload.ChannelID, diff --git a/core/handlers/gateway_handler_message_reaction_remove.go b/gateway/handlers/message_reaction_remove_handler.go similarity index 75% rename from core/handlers/gateway_handler_message_reaction_remove.go rename to gateway/handlers/message_reaction_remove_handler.go index 451180f6..8c27f261 100644 --- a/core/handlers/gateway_handler_message_reaction_remove.go +++ b/gateway/handlers/message_reaction_remove_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerMessageUpdate handles discord.GatewayEventTypeMessageReactionRemove @@ -15,17 +15,17 @@ func (h *gatewayHandlerMessageReactionRemove) EventType() discord.GatewayEventTy } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerMessageReactionRemove) New() interface{} { +func (h *gatewayHandlerMessageReactionRemove) New() any { return &discord.GatewayEventMessageReactionRemove{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerMessageReactionRemove) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { +func (h *gatewayHandlerMessageReactionRemove) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { payload := *v.(*discord.GatewayEventMessageReactionRemove) - genericEvent := events.NewGenericEvent(bot, sequenceNumber) + genericEvent := events.NewGenericEvent(client, sequenceNumber) - bot.EventManager.Dispatch(&events.MessageReactionRemoveEvent{ + client.EventManager().DispatchEvent(&events.MessageReactionRemoveEvent{ GenericReactionEvent: &events.GenericReactionEvent{ GenericEvent: genericEvent, MessageID: payload.MessageID, @@ -37,7 +37,7 @@ func (h *gatewayHandlerMessageReactionRemove) HandleGatewayEvent(bot *core.Bot, }) if payload.GuildID == nil { - bot.EventManager.Dispatch(&events.DMMessageReactionRemoveEvent{ + client.EventManager().DispatchEvent(&events.DMMessageReactionRemoveEvent{ GenericDMMessageReactionEvent: &events.GenericDMMessageReactionEvent{ GenericEvent: genericEvent, MessageID: payload.MessageID, @@ -47,7 +47,7 @@ func (h *gatewayHandlerMessageReactionRemove) HandleGatewayEvent(bot *core.Bot, }, }) } else { - bot.EventManager.Dispatch(&events.GuildMessageReactionRemoveEvent{ + client.EventManager().DispatchEvent(&events.GuildMessageReactionRemoveEvent{ GenericGuildMessageReactionEvent: &events.GenericGuildMessageReactionEvent{ GenericEvent: genericEvent, MessageID: payload.MessageID, diff --git a/gateway/handlers/message_update_handler.go b/gateway/handlers/message_update_handler.go new file mode 100644 index 00000000..be0dde05 --- /dev/null +++ b/gateway/handlers/message_update_handler.go @@ -0,0 +1,63 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerMessageUpdate handles discord.GatewayEventTypeMessageUpdate +type gatewayHandlerMessageUpdate struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerMessageUpdate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeMessageUpdate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerMessageUpdate) New() any { + return &discord.Message{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerMessageUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + message := *v.(*discord.Message) + + oldMessage, _ := client.Caches().Messages().Get(message.ChannelID, message.ID) + client.Caches().Messages().Put(message.ChannelID, message.ID, message) + + genericEvent := events.NewGenericEvent(client, sequenceNumber) + client.EventManager().DispatchEvent(&events.MessageUpdateEvent{ + GenericMessageEvent: &events.GenericMessageEvent{ + GenericEvent: genericEvent, + MessageID: message.ID, + Message: message, + ChannelID: message.ChannelID, + GuildID: message.GuildID, + }, + OldMessage: oldMessage, + }) + + if message.GuildID == nil { + client.EventManager().DispatchEvent(&events.DMMessageUpdateEvent{ + GenericDMMessageEvent: &events.GenericDMMessageEvent{ + GenericEvent: genericEvent, + MessageID: message.ID, + Message: message, + ChannelID: message.ChannelID, + }, + OldMessage: oldMessage, + }) + } else { + client.EventManager().DispatchEvent(&events.GuildMessageUpdateEvent{ + GenericGuildMessageEvent: &events.GenericGuildMessageEvent{ + GenericEvent: genericEvent, + MessageID: message.ID, + Message: message, + ChannelID: message.ChannelID, + GuildID: *message.GuildID, + }, + OldMessage: oldMessage, + }) + } +} diff --git a/core/handlers/gateway_handler_presence_update.go b/gateway/handlers/presence_update_handler.go similarity index 76% rename from core/handlers/gateway_handler_presence_update.go rename to gateway/handlers/presence_update_handler.go index 94148c32..db2a2a6b 100644 --- a/core/handlers/gateway_handler_presence_update.go +++ b/gateway/handlers/presence_update_handler.go @@ -1,10 +1,8 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" - "github.com/google/go-cmp/cmp" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" ) // gatewayHandlerGuildDelete handles discord.GatewayEventTypePresenceUpdate @@ -16,19 +14,19 @@ func (h *gatewayHandlerPresenceUpdate) EventType() discord.GatewayEventType { } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerPresenceUpdate) New() interface{} { +func (h *gatewayHandlerPresenceUpdate) New() any { return &discord.Presence{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerPresenceUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.Presence) +func (h *gatewayHandlerPresenceUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + /*payload := *v.(*discord.Presence) - oldPresence := bot.Caches.Presences().GetCopy(payload.GuildID, payload.PresenceUser.ID) + oldPresence := client.Caches().Presences().GetCopy(payload.GuildID, payload.PresenceUser.ID) _ = bot.EntityBuilder.CreatePresence(payload, core.CacheStrategyYes) - genericEvent := events.NewGenericEvent(bot, sequenceNumber) + genericEvent := events.NewGenericEvent(client, sequenceNumber) var ( oldStatus discord.OnlineStatus @@ -43,7 +41,7 @@ func (h *gatewayHandlerPresenceUpdate) HandleGatewayEvent(bot *core.Bot, sequenc } if oldStatus != payload.Status { - bot.EventManager.Dispatch(&events.UserStatusUpdateEvent{ + client.EventManager().DispatchEvent(&events.UserStatusUpdateEvent{ GenericEvent: genericEvent, UserID: payload.PresenceUser.ID, OldStatus: oldStatus, @@ -52,7 +50,7 @@ func (h *gatewayHandlerPresenceUpdate) HandleGatewayEvent(bot *core.Bot, sequenc } if oldClientStatus == nil || oldClientStatus.Desktop != payload.ClientStatus.Desktop || oldClientStatus.Mobile != payload.ClientStatus.Mobile || oldClientStatus.Web != payload.ClientStatus.Web { - bot.EventManager.Dispatch(&events.UserClientStatusUpdateEvent{ + client.EventManager().DispatchEvent(&events.UserClientStatusUpdateEvent{ GenericEvent: genericEvent, UserID: payload.PresenceUser.ID, OldClientStatus: oldClientStatus, @@ -76,7 +74,7 @@ func (h *gatewayHandlerPresenceUpdate) HandleGatewayEvent(bot *core.Bot, sequenc } if !found { genericUserActivityEvent.Activity = oldActivity - bot.EventManager.Dispatch(&events.UserActivityStopEvent{ + client.EventManager().DispatchEvent(&events.UserActivityStopEvent{ GenericUserActivityEvent: &genericUserActivityEvent, }) } @@ -92,7 +90,7 @@ func (h *gatewayHandlerPresenceUpdate) HandleGatewayEvent(bot *core.Bot, sequenc } if !found { genericUserActivityEvent.Activity = newActivity - bot.EventManager.Dispatch(&events.UserActivityStartEvent{ + client.EventManager().DispatchEvent(&events.UserActivityStartEvent{ GenericUserActivityEvent: &genericUserActivityEvent, }) } @@ -108,10 +106,10 @@ func (h *gatewayHandlerPresenceUpdate) HandleGatewayEvent(bot *core.Bot, sequenc } if oldActivity != nil && !cmp.Equal(*oldActivity, newActivity) { genericUserActivityEvent.Activity = newActivity - bot.EventManager.Dispatch(&events.UserActivityUpdateEvent{ + client.EventManager().DispatchEvent(&events.UserActivityUpdateEvent{ GenericUserActivityEvent: &genericUserActivityEvent, OldActivity: *oldActivity, }) } - } + }*/ } diff --git a/core/handlers/gateway_handler_ready.go b/gateway/handlers/ready_handler.go similarity index 52% rename from core/handlers/gateway_handler_ready.go rename to gateway/handlers/ready_handler.go index 448f98a6..0a6a1c85 100644 --- a/core/handlers/gateway_handler_ready.go +++ b/gateway/handlers/ready_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerReady handles discord.GatewayEventTypeReady @@ -15,30 +15,27 @@ func (h *gatewayHandlerReady) EventType() discord.GatewayEventType { } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerReady) New() interface{} { +func (h *gatewayHandlerReady) New() any { return &discord.GatewayEventReady{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerReady) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { +func (h *gatewayHandlerReady) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { readyEvent := *v.(*discord.GatewayEventReady) - bot.ApplicationID = readyEvent.Application.ID - bot.ClientID = readyEvent.User.ID - - bot.EntityBuilder.CreateSelfUser(readyEvent.User, core.CacheStrategyYes) - var shardID int if readyEvent.Shard != nil { shardID = readyEvent.Shard[0] } + client.HandleReadyEvent(readyEvent) + for _, guild := range readyEvent.Guilds { - bot.Caches.Guilds().SetUnready(shardID, guild.ID) + client.Caches().Guilds().SetUnready(shardID, guild.ID) } - bot.EventManager.Dispatch(&events.ReadyEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), + client.EventManager().DispatchEvent(&events.ReadyEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), GatewayEventReady: readyEvent, }) diff --git a/core/handlers/gateway_handler_resumed.go b/gateway/handlers/resumed_handler.go similarity index 52% rename from core/handlers/gateway_handler_resumed.go rename to gateway/handlers/resumed_handler.go index 1bf83d91..ba8e9c55 100644 --- a/core/handlers/gateway_handler_resumed.go +++ b/gateway/handlers/resumed_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerReady handles discord.GatewayEventTypeResumed @@ -15,14 +15,14 @@ func (h *gatewayHandlerResumed) EventType() discord.GatewayEventType { } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerResumed) New() interface{} { +func (h *gatewayHandlerResumed) New() any { return nil } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerResumed) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, _ interface{}) { - bot.EventManager.Dispatch(&events.ResumedEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), +func (h *gatewayHandlerResumed) HandleGatewayEvent(client bot.Client, sequenceNumber int, _ any) { + client.EventManager().DispatchEvent(&events.ResumedEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), }) } diff --git a/gateway/handlers/stage_instance_create_handler.go b/gateway/handlers/stage_instance_create_handler.go new file mode 100644 index 00000000..8e77e96d --- /dev/null +++ b/gateway/handlers/stage_instance_create_handler.go @@ -0,0 +1,35 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerStageInstanceCreate handles discord.GatewayEventTypeStageInstanceCreate +type gatewayHandlerStageInstanceCreate struct{} + +// EventType returns the discord.GatewayEventTypeStageInstanceCreate +func (h *gatewayHandlerStageInstanceCreate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeStageInstanceCreate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerStageInstanceCreate) New() any { + return &discord.StageInstance{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerStageInstanceCreate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + stageInstance := *v.(*discord.StageInstance) + + client.Caches().StageInstances().Put(stageInstance.GuildID, stageInstance.ID, stageInstance) + + client.EventManager().DispatchEvent(&events.StageInstanceCreateEvent{ + GenericStageInstanceEvent: &events.GenericStageInstanceEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + StageInstanceID: stageInstance.ID, + StageInstance: stageInstance, + }, + }) +} diff --git a/gateway/handlers/stage_instance_delete_handler.go b/gateway/handlers/stage_instance_delete_handler.go new file mode 100644 index 00000000..463b9866 --- /dev/null +++ b/gateway/handlers/stage_instance_delete_handler.go @@ -0,0 +1,35 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerStageInstanceDelete handles discord.GatewayEventTypeStageInstanceDelete +type gatewayHandlerStageInstanceDelete struct{} + +// EventType returns the discord.GatewayEventType +func (h *gatewayHandlerStageInstanceDelete) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeStageInstanceDelete +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerStageInstanceDelete) New() any { + return &discord.StageInstance{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerStageInstanceDelete) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + stageInstance := *v.(*discord.StageInstance) + + client.Caches().StageInstances().Remove(stageInstance.GuildID, stageInstance.ID) + + client.EventManager().DispatchEvent(&events.StageInstanceDeleteEvent{ + GenericStageInstanceEvent: &events.GenericStageInstanceEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + StageInstanceID: stageInstance.ID, + StageInstance: stageInstance, + }, + }) +} diff --git a/core/handlers/gateway_handler_stage_instance_update.go b/gateway/handlers/stage_instance_update_handler.go similarity index 53% rename from core/handlers/gateway_handler_stage_instance_update.go rename to gateway/handlers/stage_instance_update_handler.go index 6e75bdb5..7b58b1be 100644 --- a/core/handlers/gateway_handler_stage_instance_update.go +++ b/gateway/handlers/stage_instance_update_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerStageInstanceUpdate handles discord.GatewayEventTypeStageInstanceUpdate @@ -15,21 +15,22 @@ func (h *gatewayHandlerStageInstanceUpdate) EventType() discord.GatewayEventType } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerStageInstanceUpdate) New() interface{} { +func (h *gatewayHandlerStageInstanceUpdate) New() any { return &discord.StageInstance{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerStageInstanceUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { +func (h *gatewayHandlerStageInstanceUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { stageInstance := *v.(*discord.StageInstance) - oldStageInstance := bot.Caches.StageInstances().GetCopy(stageInstance.ID) + oldStageInstance, _ := client.Caches().StageInstances().Get(stageInstance.GuildID, stageInstance.ID) + client.Caches().StageInstances().Put(stageInstance.GuildID, stageInstance.ID, stageInstance) - bot.EventManager.Dispatch(&events.StageInstanceUpdateEvent{ + client.EventManager().DispatchEvent(&events.StageInstanceUpdateEvent{ GenericStageInstanceEvent: &events.GenericStageInstanceEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), + GenericEvent: events.NewGenericEvent(client, sequenceNumber), StageInstanceID: stageInstance.ID, - StageInstance: bot.EntityBuilder.CreateStageInstance(stageInstance, core.CacheStrategyYes), + StageInstance: stageInstance, }, OldStageInstance: oldStageInstance, }) diff --git a/gateway/handlers/thread_create_handler.go b/gateway/handlers/thread_create_handler.go new file mode 100644 index 00000000..63210323 --- /dev/null +++ b/gateway/handlers/thread_create_handler.go @@ -0,0 +1,34 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +type gatewayHandlerThreadCreate struct{} + +func (h *gatewayHandlerThreadCreate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeThreadCreate +} + +func (h *gatewayHandlerThreadCreate) New() any { + return &discord.GatewayEventThreadCreate{} +} + +func (h *gatewayHandlerThreadCreate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventThreadCreate) + + client.Caches().Channels().Put(payload.ID(), payload.GuildThread) + client.Caches().ThreadMembers().Put(payload.ID(), payload.ThreadMember.UserID, payload.ThreadMember) + + client.EventManager().DispatchEvent(&events.ThreadCreateEvent{ + GenericThreadEvent: &events.GenericThreadEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + ThreadID: payload.ID(), + GuildID: payload.GuildID(), + Thread: payload.GuildThread, + }, + ThreadMember: payload.ThreadMember, + }) +} diff --git a/gateway/handlers/thread_delete_handler.go b/gateway/handlers/thread_delete_handler.go new file mode 100644 index 00000000..a58e66d8 --- /dev/null +++ b/gateway/handlers/thread_delete_handler.go @@ -0,0 +1,34 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +type gatewayHandlerThreadDelete struct{} + +func (h *gatewayHandlerThreadDelete) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeThreadDelete +} + +func (h *gatewayHandlerThreadDelete) New() any { + return &discord.GatewayEventThreadDelete{} +} + +func (h *gatewayHandlerThreadDelete) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventThreadDelete) + + channel, _ := client.Caches().Channels().Remove(payload.ID) + client.Caches().ThreadMembers().RemoveAll(payload.ID) + + client.EventManager().DispatchEvent(&events.ThreadDeleteEvent{ + GenericThreadEvent: &events.GenericThreadEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + ThreadID: payload.ID, + GuildID: payload.GuildID, + ParentID: payload.ParentID, + Thread: channel.(discord.GuildThread), + }, + }) +} diff --git a/gateway/handlers/thread_list_sync_handler.go b/gateway/handlers/thread_list_sync_handler.go new file mode 100644 index 00000000..9aac0ea3 --- /dev/null +++ b/gateway/handlers/thread_list_sync_handler.go @@ -0,0 +1,32 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +type gatewayHandlerThreadListSync struct{} + +func (h *gatewayHandlerThreadListSync) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeThreadListSync +} + +func (h *gatewayHandlerThreadListSync) New() any { + return &discord.GatewayEventThreadListSync{} +} + +func (h *gatewayHandlerThreadListSync) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventThreadListSync) + + for _, thread := range payload.Threads { + client.Caches().Channels().Put(thread.ID(), thread) + client.EventManager().DispatchEvent(&events.ThreadShowEvent{ + GenericThreadEvent: &events.GenericThreadEvent{ + Thread: thread, + ThreadID: thread.ID(), + GuildID: payload.GuildID, + }, + }) + } +} diff --git a/gateway/handlers/thread_member_update_handler.go b/gateway/handlers/thread_member_update_handler.go new file mode 100644 index 00000000..2045485c --- /dev/null +++ b/gateway/handlers/thread_member_update_handler.go @@ -0,0 +1,20 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" +) + +type gatewayHandlerThreadMemberUpdate struct{} + +func (h *gatewayHandlerThreadMemberUpdate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeThreadMemberUpdate +} + +func (h *gatewayHandlerThreadMemberUpdate) New() any { + return &discord.ThreadMember{} +} + +func (h *gatewayHandlerThreadMemberUpdate) HandleGatewayEvent(_ bot.Client, _ int, _ any) { + // ThreadMembersUpdate kinda handles this already? +} diff --git a/gateway/handlers/thread_members_update_handler.go b/gateway/handlers/thread_members_update_handler.go new file mode 100644 index 00000000..239d392b --- /dev/null +++ b/gateway/handlers/thread_members_update_handler.go @@ -0,0 +1,62 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +type gatewayHandlerThreadMembersUpdate struct{} + +func (h *gatewayHandlerThreadMembersUpdate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeThreadMembersUpdate +} + +func (h *gatewayHandlerThreadMembersUpdate) New() any { + return &discord.GatewayEventThreadMembersUpdate{} +} + +func (h *gatewayHandlerThreadMembersUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventThreadMembersUpdate) + + genericEvent := events.NewGenericEvent(client, sequenceNumber) + + if thread, ok := client.Caches().Channels().GetGuildThread(payload.ID); ok { + thread.MemberCount = payload.MemberCount + client.Caches().Channels().Put(thread.ID(), thread) + } + + for _, addedMember := range payload.AddedMembers { + client.Caches().ThreadMembers().Put(payload.ID, addedMember.UserID, addedMember.ThreadMember) + client.Caches().Members().Put(payload.GuildID, addedMember.UserID, addedMember.Member) + + if addedMember.Presence != nil { + client.Caches().Presences().Put(payload.GuildID, addedMember.UserID, *addedMember.Presence) + } + + client.EventManager().DispatchEvent(&events.ThreadMemberAddEvent{ + GenericThreadMemberEvent: &events.GenericThreadMemberEvent{ + GenericEvent: genericEvent, + GuildID: payload.GuildID, + ThreadID: payload.ID, + ThreadMemberID: addedMember.UserID, + ThreadMember: addedMember.ThreadMember, + }, + }) + } + + for _, removedMemberID := range payload.RemovedMemberIDs { + threadMember, _ := client.Caches().ThreadMembers().Remove(payload.ID, removedMemberID) + + client.EventManager().DispatchEvent(&events.ThreadMemberRemoveEvent{ + GenericThreadMemberEvent: &events.GenericThreadMemberEvent{ + GenericEvent: genericEvent, + GuildID: payload.GuildID, + ThreadID: payload.ID, + ThreadMemberID: removedMemberID, + ThreadMember: threadMember, + }, + }) + } + +} diff --git a/gateway/handlers/thread_update_handler.go b/gateway/handlers/thread_update_handler.go new file mode 100644 index 00000000..f0fa754d --- /dev/null +++ b/gateway/handlers/thread_update_handler.go @@ -0,0 +1,35 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +type gatewayHandlerThreadUpdate struct{} + +func (h *gatewayHandlerThreadUpdate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeThreadUpdate +} + +func (h *gatewayHandlerThreadUpdate) New() any { + return &discord.GuildThread{} +} + +func (h *gatewayHandlerThreadUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + guildThread := *v.(*discord.GuildThread) + + oldGuildThread, _ := client.Caches().Channels().GetGuildThread(guildThread.ID()) + client.Caches().Channels().Put(guildThread.ID(), guildThread) + + client.EventManager().DispatchEvent(&events.ThreadUpdateEvent{ + GenericThreadEvent: &events.GenericThreadEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + Thread: guildThread, + ThreadID: guildThread.ID(), + GuildID: guildThread.GuildID(), + ParentID: *guildThread.ParentID(), + }, + OldThread: oldGuildThread, + }) +} diff --git a/core/handlers/gateway_handler_typing_start.go b/gateway/handlers/typing_start_handler.go similarity index 50% rename from core/handlers/gateway_handler_typing_start.go rename to gateway/handlers/typing_start_handler.go index e88fe680..5ecd3213 100644 --- a/core/handlers/gateway_handler_typing_start.go +++ b/gateway/handlers/typing_start_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerTypingStart handles discord.GatewayEventTypeInviteDelete @@ -15,16 +15,16 @@ func (h *gatewayHandlerTypingStart) EventType() discord.GatewayEventType { } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerTypingStart) New() interface{} { - return &discord.TypingStartGatewayEvent{} +func (h *gatewayHandlerTypingStart) New() any { + return &discord.GatewayEventTypingStart{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerTypingStart) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.TypingStartGatewayEvent) +func (h *gatewayHandlerTypingStart) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventTypingStart) - bot.EventManager.Dispatch(&events.UserTypingStartEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), + client.EventManager().DispatchEvent(&events.UserTypingStartEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), ChannelID: payload.ChannelID, GuildID: payload.GuildID, UserID: payload.UserID, @@ -32,20 +32,21 @@ func (h *gatewayHandlerTypingStart) HandleGatewayEvent(bot *core.Bot, sequenceNu }) if payload.GuildID == nil { - bot.EventManager.Dispatch(&events.DMUserTypingStartEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), + client.EventManager().DispatchEvent(&events.DMUserTypingStartEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), ChannelID: payload.ChannelID, UserID: payload.UserID, Timestamp: payload.Timestamp, }) } else { - bot.EventManager.Dispatch(&events.GuildMemberTypingStartEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), + client.Caches().Members().Put(*payload.GuildID, payload.UserID, *payload.Member) + client.EventManager().DispatchEvent(&events.GuildMemberTypingStartEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), ChannelID: payload.ChannelID, UserID: payload.UserID, GuildID: *payload.GuildID, Timestamp: payload.Timestamp, - Member: bot.EntityBuilder.CreateMember(*payload.GuildID, *payload.Member, core.CacheStrategyYes), + Member: *payload.Member, }) } } diff --git a/gateway/handlers/user_update_handler.go b/gateway/handlers/user_update_handler.go new file mode 100644 index 00000000..0419ba53 --- /dev/null +++ b/gateway/handlers/user_update_handler.go @@ -0,0 +1,38 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerVoiceServerUpdate handles discord.GatewayEventTypeUserUpdate +type gatewayHandlerUserUpdate struct{} + +// EventType returns the discord.GatewayEventTypeUserUpdate +func (h *gatewayHandlerUserUpdate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeUserUpdate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerUserUpdate) New() any { + return &discord.OAuth2User{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerUserUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + user := *v.(*discord.OAuth2User) + + var oldUser discord.OAuth2User + if client.SelfUser() != nil { + oldUser = *client.SelfUser() + } + client.SetSelfUser(user) + + client.EventManager().DispatchEvent(&events.SelfUpdateEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + SelfUser: user, + OldSelfUser: oldUser, + }) + +} diff --git a/core/handlers/gateway_handler_voice_server_update.go b/gateway/handlers/voice_server_update_handler.go similarity index 57% rename from core/handlers/gateway_handler_voice_server_update.go rename to gateway/handlers/voice_server_update_handler.go index 1d7ebcc0..aabf813d 100644 --- a/core/handlers/gateway_handler_voice_server_update.go +++ b/gateway/handlers/voice_server_update_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerVoiceServerUpdate handles discord.GatewayEventTypeVoiceServerUpdate @@ -15,16 +15,16 @@ func (h *gatewayHandlerVoiceServerUpdate) EventType() discord.GatewayEventType { } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerVoiceServerUpdate) New() interface{} { +func (h *gatewayHandlerVoiceServerUpdate) New() any { return &discord.VoiceServerUpdate{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerVoiceServerUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { +func (h *gatewayHandlerVoiceServerUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { payload := *v.(*discord.VoiceServerUpdate) - bot.EventManager.Dispatch(&events.VoiceServerUpdateEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), + client.EventManager().DispatchEvent(&events.VoiceServerUpdateEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), VoiceServerUpdate: payload, }) } diff --git a/gateway/handlers/voice_state_update_handler.go b/gateway/handlers/voice_state_update_handler.go new file mode 100644 index 00000000..572f5a3f --- /dev/null +++ b/gateway/handlers/voice_state_update_handler.go @@ -0,0 +1,60 @@ +package handlers + +import ( + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" +) + +// gatewayHandlerVoiceStateUpdate handles core.GatewayEventVoiceStateUpdate +type gatewayHandlerVoiceStateUpdate struct{} + +// EventType returns the gateway.EventType +func (h *gatewayHandlerVoiceStateUpdate) EventType() discord.GatewayEventType { + return discord.GatewayEventTypeVoiceStateUpdate +} + +// New constructs a new payload receiver for the raw gateway event +func (h *gatewayHandlerVoiceStateUpdate) New() any { + return &discord.VoiceState{} +} + +// HandleGatewayEvent handles the specific raw gateway event +func (h *gatewayHandlerVoiceStateUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + voiceState := *v.(*discord.VoiceState) + + oldVoiceState, oldOk := client.Caches().VoiceStates().Get(voiceState.GuildID, voiceState.UserID) + if voiceState.ChannelID == nil { + client.Caches().VoiceStates().Remove(voiceState.GuildID, voiceState.UserID) + } else { + client.Caches().VoiceStates().Put(voiceState.GuildID, voiceState.UserID, voiceState) + } + + genericGuildVoiceEvent := &events.GenericGuildVoiceStateEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), + VoiceState: voiceState, + } + + client.EventManager().DispatchEvent(&events.GuildVoiceStateUpdateEvent{ + GenericGuildVoiceStateEvent: genericGuildVoiceEvent, + OldVoiceState: oldVoiceState, + }) + + if oldOk && oldVoiceState.ChannelID != nil && voiceState.ChannelID != nil { + client.EventManager().DispatchEvent(&events.GuildVoiceMoveEvent{ + GenericGuildVoiceStateEvent: genericGuildVoiceEvent, + OldVoiceState: oldVoiceState, + }) + } else if (oldOk || oldVoiceState.ChannelID == nil) && voiceState.ChannelID != nil { + client.EventManager().DispatchEvent(&events.GuildVoiceJoinEvent{ + GenericGuildVoiceStateEvent: genericGuildVoiceEvent, + }) + } else if voiceState.ChannelID == nil { + client.EventManager().DispatchEvent(&events.GuildVoiceLeaveEvent{ + GenericGuildVoiceStateEvent: genericGuildVoiceEvent, + OldVoiceState: oldVoiceState, + }) + } else { + client.Logger().Warnf("could not decide which GuildVoiceEvent to fire") + } +} diff --git a/core/handlers/gateway_handler_webhooks_update.go b/gateway/handlers/webhooks_update_handler.go similarity index 51% rename from core/handlers/gateway_handler_webhooks_update.go rename to gateway/handlers/webhooks_update_handler.go index a4d19979..d6d4ba27 100644 --- a/core/handlers/gateway_handler_webhooks_update.go +++ b/gateway/handlers/webhooks_update_handler.go @@ -1,9 +1,9 @@ package handlers import ( - "github.com/DisgoOrg/disgo/core" - "github.com/DisgoOrg/disgo/core/events" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/bot" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/events" ) // gatewayHandlerWebhooksUpdate handles discord.GatewayEventTypeWebhooksUpdate @@ -15,16 +15,16 @@ func (h *gatewayHandlerWebhooksUpdate) EventType() discord.GatewayEventType { } // New constructs a new payload receiver for the raw gateway event -func (h *gatewayHandlerWebhooksUpdate) New() interface{} { - return &discord.WebhooksUpdateGatewayEvent{} +func (h *gatewayHandlerWebhooksUpdate) New() any { + return &discord.GatewayEventWebhooksUpdate{} } // HandleGatewayEvent handles the specific raw gateway event -func (h *gatewayHandlerWebhooksUpdate) HandleGatewayEvent(bot *core.Bot, sequenceNumber discord.GatewaySequence, v interface{}) { - payload := *v.(*discord.WebhooksUpdateGatewayEvent) +func (h *gatewayHandlerWebhooksUpdate) HandleGatewayEvent(client bot.Client, sequenceNumber int, v any) { + payload := *v.(*discord.GatewayEventWebhooksUpdate) - bot.EventManager.Dispatch(&events.WebhooksUpdateEvent{ - GenericEvent: events.NewGenericEvent(bot, sequenceNumber), + client.EventManager().DispatchEvent(&events.WebhooksUpdateEvent{ + GenericEvent: events.NewGenericEvent(client, sequenceNumber), GuildId: payload.GuildID, ChannelID: payload.ChannelID, }) diff --git a/gateway/sharding/shard_manager_config.go b/gateway/sharding/shard_manager_config.go deleted file mode 100644 index 86274b68..00000000 --- a/gateway/sharding/shard_manager_config.go +++ /dev/null @@ -1,112 +0,0 @@ -package sharding - -import ( - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/disgo/gateway/sharding/srate" - "github.com/DisgoOrg/log" -) - -//goland:noinspection GoUnusedGlobalVariable -var DefaultConfig = Config{ - CustomShards: false, - GatewayCreateFunc: func(token string, url string, shardID int, shardCount int, eventHandlerFunc gateway.EventHandlerFunc, config *gateway.Config) gateway.Gateway { - return gateway.New(token, url, shardID, shardCount, eventHandlerFunc, config) - }, - GatewayConfig: &gateway.DefaultConfig, - RateLimiter: srate.NewLimiter(&srate.DefaultConfig), -} - -type Config struct { - Logger log.Logger - CustomShards bool - Shards *IntSet - ShardCount int - GatewayCreateFunc func(token string, url string, shardID int, shardCount int, eventHandlerFunc gateway.EventHandlerFunc, config *gateway.Config) gateway.Gateway - GatewayConfig *gateway.Config - RateLimiter srate.Limiter - RateLimiterConfig *srate.Config -} - -type ConfigOpt func(config *Config) - -func (c *Config) Apply(opts []ConfigOpt) { - for _, opt := range opts { - opt(c) - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithLogger(logger log.Logger) ConfigOpt { - return func(config *Config) { - config.Logger = logger - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithShards(shards ...int) ConfigOpt { - return func(config *Config) { - config.CustomShards = true - if config.Shards == nil { - config.Shards = NewIntSet(shards...) - } - for _, shardID := range shards { - config.Shards.Add(shardID) - } - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithShardCount(shardCount int) ConfigOpt { - return func(config *Config) { - config.CustomShards = true - config.ShardCount = shardCount - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithGatewayCreateFunc(gatewayCreateFunc func(token string, url string, shardID int, shardCount int, eventHandlerFunc gateway.EventHandlerFunc, config *gateway.Config) gateway.Gateway) ConfigOpt { - return func(config *Config) { - config.GatewayCreateFunc = gatewayCreateFunc - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithGatewayConfig(gatewayConfig gateway.Config) ConfigOpt { - return func(config *Config) { - config.GatewayConfig = &gatewayConfig - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithGatewayConfigOpts(opts ...gateway.ConfigOpt) ConfigOpt { - return func(config *Config) { - if config.GatewayConfig == nil { - config.GatewayConfig = &gateway.DefaultConfig - } - config.GatewayConfig.Apply(opts) - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithRateLimiter(rateLimiter srate.Limiter) ConfigOpt { - return func(config *Config) { - config.RateLimiter = rateLimiter - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithRateLimiterConfig(rateConfig srate.Config) ConfigOpt { - return func(config *Config) { - config.RateLimiterConfig = &rateConfig - } -} - -//goland:noinspection GoUnusedExportedFunction -func WithRateLimiterConfigOpt(opts ...srate.ConfigOpt) ConfigOpt { - return func(config *Config) { - if config.RateLimiterConfig == nil { - config.RateLimiterConfig = &srate.DefaultConfig - } - config.RateLimiterConfig.Apply(opts) - } -} diff --git a/go.mod b/go.mod index da802643..31bfa0fd 100644 --- a/go.mod +++ b/go.mod @@ -1,15 +1,14 @@ -module github.com/DisgoOrg/disgo +module github.com/disgoorg/disgo -go 1.17 +go 1.18 require ( - github.com/DisgoOrg/log v1.1.3 - github.com/DisgoOrg/snowflake v1.0.4 - github.com/google/go-cmp v0.5.7 + github.com/disgoorg/log v1.2.0 + github.com/disgoorg/snowflake v1.1.0 github.com/gorilla/websocket v1.5.0 - github.com/pkg/errors v0.9.1 github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b github.com/stretchr/testify v1.7.0 + golang.org/x/exp v0.0.0-20220325121720-054d8573a5d8 ) require ( diff --git a/go.sum b/go.sum index 020cecf5..881e05fb 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,11 @@ -github.com/DisgoOrg/log v1.1.3 h1:UN0ZfmPZ7yhCCDQ7iVvIedvZ2zEexNS5Ek76GBuffOE= -github.com/DisgoOrg/log v1.1.3/go.mod h1:tSMofXaNhQNvzLRoL4tAiCG9yGY1ES5DLvduh7e9GRU= -github.com/DisgoOrg/snowflake v1.0.4 h1:hgeXSaXRDVdoNJ0rfHXyVsgxQMzctP346S5WXlBmoOU= -github.com/DisgoOrg/snowflake v1.0.4/go.mod h1:jIQVlVmElm2OGt6v52ITf/71ODaU09chUCflxt8+3yM= github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= +github.com/disgoorg/log v1.2.0 h1:sqlXnu/ZKAlIlHV9IO+dbMto7/hCQ474vlIdMWk8QKo= +github.com/disgoorg/log v1.2.0/go.mod h1:3x1KDG6DI1CE2pDwi3qlwT3wlXpeHW/5rVay+1qDqOo= +github.com/disgoorg/snowflake v1.1.0 h1:uVF9QqI31uqo0kzbZahwvjaYQxn40SUfFK5pCNzfjYQ= +github.com/disgoorg/snowflake v1.1.0/go.mod h1:wUUTKWS1jSV0gIb3TSPsdJORNF8BcjKTjVeyrULEhr8= 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 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b h1:qYTY2tN72LhgDj2rtWG+LI6TXFl2ygFQQ4YezfVaGQE= @@ -17,8 +13,8 @@ github.com/sasha-s/go-csync v0.0.0-20210812194225-61421b77c44b/go.mod h1:/pA7k3z github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/exp v0.0.0-20220325121720-054d8573a5d8 h1:Xt4/LzbTwfocTk9ZLEu4onjeFucl88iW+v4j4PWbQuE= +golang.org/x/exp v0.0.0-20220325121720-054d8573a5d8/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= diff --git a/httpserver/README.md b/httpserver/README.md index 12818eaa..0cc025ac 100644 --- a/httpserver/README.md +++ b/httpserver/README.md @@ -11,7 +11,7 @@ package main import ( "github.com/oasisprotocol/curve25519-voi/primitives/ed25519" - "github.com/DisgoOrg/disgo/httpserver" + "github.com/disgoorg/disgo/httpserver" ) func main() { httpserver.Verify = func(publicKey httpserver.PublicKey, message, sig []byte) bool { diff --git a/httpserver/config.go b/httpserver/config.go index 0d1e78d4..49f2718e 100644 --- a/httpserver/config.go +++ b/httpserver/config.go @@ -3,25 +3,27 @@ package httpserver import ( "net/http" - "github.com/DisgoOrg/log" + "github.com/disgoorg/log" ) -//goland:noinspection GoUnusedGlobalVariable -var DefaultConfig = Config{ - URL: "/interactions/callback", - Port: ":80", +func DefaultConfig() *Config { + return &Config{ + URL: "/interactions/callback", + Address: ":80", + HTTPServer: &http.Server{}, + ServeMux: http.NewServeMux(), + } } type Config struct { - Logger log.Logger - HTTPServer *http.Server - ServeMux *http.ServeMux - EventHandlerFunc EventHandlerFunc - URL string - Port string - PublicKey string - CertFile string - KeyFile string + Logger log.Logger + HTTPServer *http.Server + ServeMux *http.ServeMux + URL string + Address string + PublicKey string + CertFile string + KeyFile string } type ConfigOpt func(config *Config) @@ -32,49 +34,42 @@ func (c *Config) Apply(opts []ConfigOpt) { } } -//goland:noinspection GoUnusedExportedFunction func WithLogger(logger log.Logger) ConfigOpt { return func(config *Config) { config.Logger = logger } } -//goland:noinspection GoUnusedExportedFunction func WithHTTPServer(httpServer *http.Server) ConfigOpt { return func(config *Config) { config.HTTPServer = httpServer } } -//goland:noinspection GoUnusedExportedFunction func WithServeMux(serveMux *http.ServeMux) ConfigOpt { return func(config *Config) { config.ServeMux = serveMux } } -//goland:noinspection GoUnusedExportedFunction func WithURL(url string) ConfigOpt { return func(config *Config) { config.URL = url } } -//goland:noinspection GoUnusedExportedFunction -func WithPort(port string) ConfigOpt { +func WithAddress(address string) ConfigOpt { return func(config *Config) { - config.Port = port + config.Address = address } } -//goland:noinspection GoUnusedExportedFunction func WithPublicKey(publicKey string) ConfigOpt { return func(config *Config) { config.PublicKey = publicKey } } -//goland:noinspection GoUnusedExportedFunction func WithTLS(certFile string, keyFile string) ConfigOpt { return func(config *Config) { config.CertFile = certFile diff --git a/httpserver/ed25519.go b/httpserver/ed25519.go index 5408e479..8a12f7f8 100644 --- a/httpserver/ed25519.go +++ b/httpserver/ed25519.go @@ -2,7 +2,6 @@ package httpserver import "crypto/ed25519" -//goland:noinspection GoUnusedGlobalVariable var ( Verify = func(publicKey PublicKey, message, sig []byte) bool { return ed25519.Verify(publicKey, message, sig) diff --git a/httpserver/server.go b/httpserver/server.go index 276f637f..180958f3 100644 --- a/httpserver/server.go +++ b/httpserver/server.go @@ -8,8 +8,8 @@ import ( "io/ioutil" "net/http" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/log" ) type EventHandlerFunc func(responseChannel chan<- discord.InteractionResponse, payload io.Reader) @@ -18,7 +18,8 @@ type EventHandlerFunc func(responseChannel chan<- discord.InteractionResponse, p type Server interface { Logger() log.Logger PublicKey() PublicKey - Config() Config + EventHandlerFunc() EventHandlerFunc + Start() Close(ctx context.Context) } diff --git a/httpserver/server_impl.go b/httpserver/server_impl.go index 412cc9f7..80980c97 100644 --- a/httpserver/server_impl.go +++ b/httpserver/server_impl.go @@ -7,56 +7,37 @@ import ( "io" "io/ioutil" "net/http" + "time" - "github.com/DisgoOrg/disgo/json" + "github.com/disgoorg/disgo/json" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/log" ) var _ Server = (*serverImpl)(nil) -func New(eventHandlerFunc EventHandlerFunc, config *Config) Server { - if config == nil { - config = &DefaultConfig - } - if config.Logger == nil { - config.Logger = log.Default() - } - config.EventHandlerFunc = eventHandlerFunc +func New(eventHandlerFunc EventHandlerFunc, opts ...ConfigOpt) Server { + config := DefaultConfig() + config.Apply(opts) hexDecodedKey, err := hex.DecodeString(config.PublicKey) if err != nil { config.Logger.Errorf("error while decoding hex string: %s", err) } - server := &serverImpl{ - publicKey: hexDecodedKey, - } - - if config.HTTPServer == nil { - config.HTTPServer = &http.Server{ - Addr: config.Port, - } - } - server.server = config.HTTPServer - - if config.HTTPServer.Handler == nil { - if config.ServeMux == nil { - config.ServeMux = http.NewServeMux() - } - config.ServeMux.Handle(config.URL, &WebhookInteractionHandler{server: server}) - config.HTTPServer.Handler = config.ServeMux + return &serverImpl{ + publicKey: hexDecodedKey, + eventHandlerFunc: eventHandlerFunc, + config: *config, } - server.config = *config - return server } -// serverImpl is used in Bot's webhook server for interactions +// serverImpl is used in Client's webhook server for interactions type serverImpl struct { - config Config - publicKey PublicKey - server *http.Server + config Config + eventHandlerFunc EventHandlerFunc + publicKey PublicKey } func (s *serverImpl) Logger() log.Logger { @@ -68,19 +49,20 @@ func (s *serverImpl) PublicKey() PublicKey { return s.publicKey } -// Config returns the Config -func (s *serverImpl) Config() Config { - return s.config +func (s *serverImpl) EventHandlerFunc() EventHandlerFunc { + return s.eventHandlerFunc } // Start makes the serverImpl listen on the specified port and handle requests func (s *serverImpl) Start() { go func() { + s.config.ServeMux.Handle(s.config.URL, &WebhookInteractionHandler{server: s}) + s.config.HTTPServer.Addr = s.config.Address var err error if s.config.CertFile != "" && s.config.KeyFile != "" { - err = s.server.ListenAndServeTLS(s.config.CertFile, s.config.KeyFile) + err = s.config.HTTPServer.ListenAndServeTLS(s.config.CertFile, s.config.KeyFile) } else { - err = s.server.ListenAndServe() + err = s.config.HTTPServer.ListenAndServe() } if err != nil { s.Logger().Error("error starting http server: ", err) @@ -90,7 +72,7 @@ func (s *serverImpl) Start() { // Close shuts down the serverImpl func (s *serverImpl) Close(ctx context.Context) { - _ = s.server.Shutdown(ctx) + _ = s.config.HTTPServer.Shutdown(ctx) } type WebhookInteractionHandler struct { @@ -114,24 +96,39 @@ func (h *WebhookInteractionHandler) ServeHTTP(w http.ResponseWriter, r *http.Req h.server.Logger().Trace("received http interaction. body: ", string(rqData)) responseChannel := make(chan discord.InteractionResponse, 1) - h.server.Config().EventHandlerFunc(responseChannel, rqBody) + h.server.EventHandlerFunc()(responseChannel, rqBody) + + timer := time.NewTimer(time.Second * 3) + defer timer.Stop() + var ( + body any + err error + ) + select { + case response := <-responseChannel: + body, err = response.ToBody() + case <-timer.C: + h.server.Logger().Warn("interaction timed out") + http.Error(w, "interaction timed out", http.StatusRequestTimeout) + return + } - response, err := (<-responseChannel).ToBody() if err != nil { h.server.Logger().Error("error while converting interaction response to body: ", err) + http.Error(w, "internal server error", http.StatusInternalServerError) return } rsBody := &bytes.Buffer{} multiWriter := io.MultiWriter(w, rsBody) - if multiPart, ok := response.(*discord.MultipartBuffer); ok { + if multiPart, ok := body.(*discord.MultipartBuffer); ok { w.Header().Set("Content-Type", multiPart.ContentType) _, err = io.Copy(multiWriter, multiPart.Buffer) } else { w.Header().Set("Content-Type", "application/json") - err = json.NewEncoder(multiWriter).Encode(response) + err = json.NewEncoder(multiWriter).Encode(body) } if err != nil { h.server.Logger().Error("error writing http interaction response error: ", err) diff --git a/info/info.go b/info/info.go deleted file mode 100644 index 2f2636e3..00000000 --- a/info/info.go +++ /dev/null @@ -1,42 +0,0 @@ -package info - -import ( - "runtime" - "runtime/debug" - "strings" -) - -//goland:noinspection GoUnusedConst -const ( - GitHub = "https://github.com/DisgoOrg/disgo" - Name = "disgo" -) - -//goland:noinspection GoUnusedGlobalVariable -var ( - Version = getVersion() - OS = getOS() -) - -func getVersion() string { - bi, ok := debug.ReadBuildInfo() - if ok { - for _, dep := range bi.Deps { - if strings.Contains(GitHub, dep.Path) { - return dep.Version - } - } - } - return "unknown" -} - -func getOS() string { - os := runtime.GOOS - if strings.HasPrefix(os, "windows") { - return "windows" - } - if strings.HasPrefix(os, "darwin") { - return "darwin" - } - return "linux" -} diff --git a/internal/rwsync/rwsync.go b/internal/rwsync/rwsync.go deleted file mode 100644 index 909781e9..00000000 --- a/internal/rwsync/rwsync.go +++ /dev/null @@ -1,10 +0,0 @@ -package rwsync - -import "sync" - -// RWLocker is a read-write mutex interface -type RWLocker interface { - sync.Locker - RLock() - RUnlock() -} diff --git a/internal/tokenhelper/tokenhelper.go b/internal/tokenhelper/tokenhelper.go index 0936d28a..ce8acf72 100644 --- a/internal/tokenhelper/tokenhelper.go +++ b/internal/tokenhelper/tokenhelper.go @@ -4,12 +4,11 @@ import ( "encoding/base64" "strings" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/snowflake" ) -// IDFromToken returns the applicationID from the BotToken -//goland:noinspection GoUnusedExportedFunction +// IDFromToken returns the applicationID from the token func IDFromToken(token string) (*snowflake.Snowflake, error) { strs := strings.Split(token, ".") if len(strs) == 0 { diff --git a/json/json.go b/json/json.go index 27a4a22a..0a59e732 100644 --- a/json/json.go +++ b/json/json.go @@ -2,7 +2,6 @@ package json import "encoding/json" -//goland:noinspection GoUnusedGlobalVariable var ( Marshal = json.Marshal Unmarshal = json.Unmarshal @@ -13,9 +12,7 @@ var ( ) type ( - RawMessage = json.RawMessage - + RawMessage = json.RawMessage Unmarshaler = json.Unmarshaler - - Marshaler = json.Marshaler + Marshaler = json.Marshaler ) diff --git a/json/null_types.go b/json/null_types.go deleted file mode 100644 index 4fea2193..00000000 --- a/json/null_types.go +++ /dev/null @@ -1,57 +0,0 @@ -package json - -type NullBool *bool - -//goland:noinspection GoUnusedExportedFunction -func NewBool(b bool) *NullBool { - v := NullBool(&b) - return &v -} - -//goland:noinspection GoUnusedExportedFunction -func NewNullBool() *NullBool { - v := NullBool(nil) - return &v -} - -type NullString *string - -//goland:noinspection GoUnusedExportedFunction -func NewString(str string) *NullString { - v := NullString(&str) - return &v -} - -//goland:noinspection GoUnusedExportedFunction -func NewNullString() *NullString { - v := NullString(nil) - return &v -} - -type NullInt *int - -//goland:noinspection GoUnusedExportedFunction -func NewInt(int int) *NullInt { - v := NullInt(&int) - return &v -} - -//goland:noinspection GoUnusedExportedFunction -func NewNullInt() *NullInt { - v := NullInt(nil) - return &v -} - -type NullFloat *float64 - -//goland:noinspection GoUnusedExportedFunction -func NewFloat(float float64) *NullFloat { - v := NullFloat(&float) - return &v -} - -//goland:noinspection GoUnusedExportedFunction -func NewNullFloat() *NullFloat { - v := NullFloat(nil) - return &v -} diff --git a/json/nullable.go b/json/nullable.go new file mode 100644 index 00000000..6fa2ffdc --- /dev/null +++ b/json/nullable.go @@ -0,0 +1,66 @@ +package json + +import ( + "bytes" + "encoding/json" +) + +var nullBytes = []byte("null") + +func NewPtr[T any](t T) *T { + return &t +} + +func Null[T any]() Nullable[T] { + return Nullable[T]{ + isNull: true, + } +} + +func OptionalNull[T any]() *Nullable[T] { + return &Nullable[T]{ + isNull: true, + } +} + +func New[T any](t T) Nullable[T] { + return Nullable[T]{ + value: t, + isNull: false, + } +} + +func NewOptional[T any](t T) *Nullable[T] { + return &Nullable[T]{ + value: t, + isNull: false, + } +} + +type Nullable[T any] struct { + value T + isNull bool +} + +func (n Nullable[T]) MarshalJSON() ([]byte, error) { + if n.isNull { + return nullBytes, nil + } + return json.Marshal(n.value) +} + +func (n *Nullable[T]) UnmarshalJSON(data []byte) error { + if bytes.Equal(data, nullBytes) { + n.isNull = true + return nil + } + return json.Unmarshal(data, &n.value) +} + +func (n Nullable[T]) Value() T { + return n.value +} + +func (n Nullable[T]) IsNull() bool { + return n.isNull +} diff --git a/json/null_types_test.go b/json/nullable_test.go similarity index 59% rename from json/null_types_test.go rename to json/nullable_test.go index 9796c086..3d069b98 100644 --- a/json/null_types_test.go +++ b/json/nullable_test.go @@ -8,15 +8,15 @@ import ( func TestNullBool(t *testing.T) { type v struct { - NullBool NullBool `json:"null_bool"` + NullBool Nullable[bool] `json:"null_bool"` } cases := []struct { - input NullBool + input Nullable[bool] data string }{ - {*NewNullBool(), `{"null_bool":null}`}, - {*NewBool(true), `{"null_bool":true}`}, - {*NewBool(false), `{"null_bool":false}`}, + {Null[bool](), `{"null_bool":null}`}, + {New(true), `{"null_bool":true}`}, + {New(false), `{"null_bool":false}`}, } for _, c := range cases { @@ -30,16 +30,16 @@ func TestNullBool(t *testing.T) { func TestNullBoolPtr(t *testing.T) { type v struct { - NullBool *NullBool `json:"null_bool,omitempty"` + NullBool *Nullable[bool] `json:"null_bool,omitempty"` } cases := []struct { - input *NullBool + input *Nullable[bool] data string }{ {nil, `{}`}, - {NewNullBool(), `{"null_bool":null}`}, - {NewBool(true), `{"null_bool":true}`}, - {NewBool(false), `{"null_bool":false}`}, + {OptionalNull[bool](), `{"null_bool":null}`}, + {NewOptional(true), `{"null_bool":true}`}, + {NewOptional(false), `{"null_bool":false}`}, } for _, c := range cases { diff --git a/oauth2/README.md b/oauth2/README.md index 910c68db..24316f6d 100644 --- a/oauth2/README.md +++ b/oauth2/README.md @@ -1,6 +1,6 @@ # oauth2 -[OAuth2](https://discord.com/developers/docs/topics/oauth2) module of [disgo](https://github.com/DisgoOrg/disgo) +[OAuth2](https://discord.com/developers/docs/topics/oauth2) module of [disgo](https://github.com/disgoorg/disgo) ## Getting Started @@ -10,4 +10,4 @@ Next you need to put in your redirect URL. ### Usage -See [here](https://github.com/DisgoOrg/disgo/blob/development/_examples/oauth2/example.go) for an example. \ No newline at end of file +See [here](https://github.com/disgoorg/disgo/blob/development/_examples/oauth2/example.go) for an example. \ No newline at end of file diff --git a/oauth2/client.go b/oauth2/client.go index 92474660..6944a8d0 100644 --- a/oauth2/client.go +++ b/oauth2/client.go @@ -1,16 +1,13 @@ package oauth2 import ( + "errors" "fmt" - "time" - "github.com/DisgoOrg/snowflake" - "github.com/pkg/errors" + "github.com/disgoorg/snowflake" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest" ) // errors returned by the OAuth2 client @@ -22,122 +19,33 @@ var ( } ) -// New returns a new OAuth2 client -func New(id snowflake.Snowflake, secret string, opts ...ConfigOpt) *Client { - config := &DefaultConfig - config.Apply(opts) - - if config.Logger == nil { - config.Logger = log.Default() - } - - if config.RestClient == nil { - config.RestClient = rest.NewClient(config.RestClientConfig) - } - if config.OAuth2Service == nil { - config.OAuth2Service = rest.NewOAuth2Service(config.RestClient) - } - if config.SessionController == nil { - config.SessionController = NewSessionController() - } - if config.StateController == nil { - config.StateController = NewStateController(config.StateControllerConfig) - } - - return &Client{ID: id, Secret: secret, Config: *config} -} - -// Client is an OAuth2 client -type Client struct { - ID snowflake.Snowflake - Secret string - Config -} - -// GenerateAuthorizationURL generates an authorization URL with the given redirect URI, permissions, guildID, disableGuildSelect & scopes, state is automatically generated -func (c *Client) GenerateAuthorizationURL(redirectURI string, permissions discord.Permissions, guildID snowflake.Snowflake, disableGuildSelect bool, scopes ...discord.ApplicationScope) string { - url, _ := c.GenerateAuthorizationURLState(redirectURI, permissions, guildID, disableGuildSelect, scopes...) - return url -} - -// GenerateAuthorizationURLState generates an authorization URL with the given redirect URI, permissions, guildID, disableGuildSelect & scopes, state is automatically generated & returned -func (c *Client) GenerateAuthorizationURLState(redirectURI string, permissions discord.Permissions, guildID snowflake.Snowflake, disableGuildSelect bool, scopes ...discord.ApplicationScope) (string, string) { - state := c.StateController.GenerateNewState(redirectURI) - values := route.QueryValues{ - "client_id": c.ID, - "redirect_uri": redirectURI, - "response_type": "code", - "scope": discord.JoinScopes(scopes), - "state": state, - } - if permissions != discord.PermissionsNone { - values["permissions"] = permissions - } - if guildID != "" { - values["guild_id"] = guildID - } - if disableGuildSelect { - values["disable_guild_select"] = true - } - compiledRoute, _ := route.Authorize.Compile(values) - return compiledRoute.URL(), state -} - -// StartSession starts a new session with the given authorization code & state -func (c *Client) StartSession(code string, state string, identifier string, opts ...rest.RequestOpt) (Session, error) { - redirectURI := c.StateController.ConsumeState(state) - if redirectURI == "" { - return nil, ErrStateNotFound - } - exchange, err := c.OAuth2Service.GetAccessToken(c.ID, c.Secret, code, redirectURI, opts...) - if err != nil { - return nil, err - } - - return c.SessionController.CreateSessionFromExchange(identifier, *exchange), nil -} - -// RefreshSession refreshes the given session with the refresh token -func (c *Client) RefreshSession(identifier string, session Session, opts ...rest.RequestOpt) (Session, error) { - exchange, err := c.OAuth2Service.RefreshAccessToken(c.ID, c.Secret, session.RefreshToken(), opts...) - if err != nil { - return nil, err - } - return c.SessionController.CreateSessionFromExchange(identifier, *exchange), nil -} - -// GetUser returns the discord.OAuth2User associated with the given session. Fields filled in the struct depend on the Session.Scopes -func (c *Client) GetUser(session Session, opts ...rest.RequestOpt) (*discord.OAuth2User, error) { - if session.Expiration().Before(time.Now()) { - return nil, ErrAccessTokenExpired - } - if !discord.HasScope(discord.ApplicationScopeIdentify, session.Scopes()...) { - return nil, ErrMissingOAuth2Scope(discord.ApplicationScopeIdentify) - } - - return c.OAuth2Service.GetCurrentUser(session.AccessToken(), opts...) -} - -// GetGuilds returns the discord.OAuth2Guild(s) the user is a member of. This requires the discord.ApplicationScopeGuilds scope in the session -func (c *Client) GetGuilds(session Session, opts ...rest.RequestOpt) ([]discord.OAuth2Guild, error) { - if session.Expiration().Before(time.Now()) { - return nil, ErrAccessTokenExpired - } - if !discord.HasScope(discord.ApplicationScopeGuilds, session.Scopes()...) { - return nil, ErrMissingOAuth2Scope(discord.ApplicationScopeGuilds) - } - - return c.OAuth2Service.GetCurrentUserGuilds(session.AccessToken(), "", "", 0, opts...) -} - -// GetConnections returns the discord.Connection(s) the user has connected. This requires the discord.ApplicationScopeConnections scope in the session -func (c *Client) GetConnections(session Session, opts ...rest.RequestOpt) ([]discord.Connection, error) { - if session.Expiration().Before(time.Now()) { - return nil, ErrAccessTokenExpired - } - if !discord.HasScope(discord.ApplicationScopeConnections, session.Scopes()...) { - return nil, ErrMissingOAuth2Scope(discord.ApplicationScopeConnections) - } - - return c.OAuth2Service.GetCurrentUserConnections(session.AccessToken(), opts...) +type Client interface { + // ID returns the configured client ID + ID() snowflake.Snowflake + // Secret returns the configured client secret + Secret() string + // Rest returns the underlying rest.OAuth2 + Rest() rest.OAuth2 + + // SessionController returns the configured SessionController + SessionController() SessionController + // StateController returns the configured StateController + StateController() StateController + + // GenerateAuthorizationURL generates an authorization URL with the given redirect URI, permissions, guildID, disableGuildSelect & scopes. State is automatically generated + GenerateAuthorizationURL(redirectURI string, permissions discord.Permissions, guildID snowflake.Snowflake, disableGuildSelect bool, scopes ...discord.ApplicationScope) string + // GenerateAuthorizationURLState generates an authorization URL with the given redirect URI, permissions, guildID, disableGuildSelect & scopes. State is automatically generated & returned + GenerateAuthorizationURLState(redirectURI string, permissions discord.Permissions, guildID snowflake.Snowflake, disableGuildSelect bool, scopes ...discord.ApplicationScope) (string, string) + + // StartSession starts a new Session with the given authorization code & state + StartSession(code string, state string, identifier string, opts ...rest.RequestOpt) (Session, error) + // RefreshSession refreshes the given Session with the refresh token + RefreshSession(identifier string, session Session, opts ...rest.RequestOpt) (Session, error) + + // GetUser returns the discord.OAuth2User associated with the given Session. Fields filled in the struct depend on the Session.Scopes + GetUser(session Session, opts ...rest.RequestOpt) (*discord.OAuth2User, error) + // GetGuilds returns the discord.OAuth2Guild(s) the user is a member of. This requires the discord.ApplicationScopeGuilds scope in the Session + GetGuilds(session Session, opts ...rest.RequestOpt) ([]discord.OAuth2Guild, error) + // GetConnections returns the discord.Connection(s) the user has connected. This requires the discord.ApplicationScopeConnections scope in the Session + GetConnections(session Session, opts ...rest.RequestOpt) ([]discord.Connection, error) } diff --git a/oauth2/client_impl.go b/oauth2/client_impl.go new file mode 100644 index 00000000..5896eca7 --- /dev/null +++ b/oauth2/client_impl.go @@ -0,0 +1,138 @@ +package oauth2 + +import ( + "time" + + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" +) + +// New returns a new OAuth2 client +func New(id snowflake.Snowflake, secret string, opts ...ConfigOpt) Client { + config := DefaultConfig() + config.Apply(opts) + + return &ClientImpl{id: id, secret: secret, config: *config} +} + +// ClientImpl is an OAuth2 client +type ClientImpl struct { + id snowflake.Snowflake + secret string + config Config +} + +// ID returns the configured client ID +func (c *ClientImpl) ID() snowflake.Snowflake { + return c.id +} + +// Secret returns the configured client secret +func (c *ClientImpl) Secret() string { + return c.secret +} + +// Rest returns the underlying rest.OAuth2 +func (c *ClientImpl) Rest() rest.OAuth2 { + return c.config.OAuth2 +} + +// SessionController returns the configured SessionController +func (c *ClientImpl) SessionController() SessionController { + return c.config.SessionController +} + +// StateController returns the configured StateController +func (c *ClientImpl) StateController() StateController { + return c.config.StateController +} + +// GenerateAuthorizationURL generates an authorization URL with the given redirect URI, permissions, guildID, disableGuildSelect & scopes, state is automatically generated +func (c *ClientImpl) GenerateAuthorizationURL(redirectURI string, permissions discord.Permissions, guildID snowflake.Snowflake, disableGuildSelect bool, scopes ...discord.ApplicationScope) string { + url, _ := c.GenerateAuthorizationURLState(redirectURI, permissions, guildID, disableGuildSelect, scopes...) + return url +} + +// GenerateAuthorizationURLState generates an authorization URL with the given redirect URI, permissions, guildID, disableGuildSelect & scopes, state is automatically generated & returned +func (c *ClientImpl) GenerateAuthorizationURLState(redirectURI string, permissions discord.Permissions, guildID snowflake.Snowflake, disableGuildSelect bool, scopes ...discord.ApplicationScope) (string, string) { + state := c.StateController().GenerateNewState(redirectURI) + values := route.QueryValues{ + "client_id": c.ID, + "redirect_uri": redirectURI, + "response_type": "code", + "scope": discord.JoinScopes(scopes), + "state": state, + } + if permissions != discord.PermissionsNone { + values["permissions"] = permissions + } + if guildID != "" { + values["guild_id"] = guildID + } + if disableGuildSelect { + values["disable_guild_select"] = true + } + compiledRoute, _ := route.Authorize.Compile(values) + return compiledRoute.URL(), state +} + +// StartSession starts a new session with the given authorization code & state +func (c *ClientImpl) StartSession(code string, state string, identifier string, opts ...rest.RequestOpt) (Session, error) { + redirectURI := c.StateController().ConsumeState(state) + if redirectURI == "" { + return nil, ErrStateNotFound + } + exchange, err := c.Rest().GetAccessToken(c.id, c.secret, code, redirectURI, opts...) + if err != nil { + return nil, err + } + + return c.SessionController().CreateSessionFromExchange(identifier, *exchange), nil +} + +// RefreshSession refreshes the given session with the refresh token +func (c *ClientImpl) RefreshSession(identifier string, session Session, opts ...rest.RequestOpt) (Session, error) { + exchange, err := c.Rest().RefreshAccessToken(c.id, c.secret, session.RefreshToken(), opts...) + if err != nil { + return nil, err + } + return c.SessionController().CreateSessionFromExchange(identifier, *exchange), nil +} + +// GetUser returns the discord.OAuth2User associated with the given session. Fields filled in the struct depend on the Session.Scopes +func (c *ClientImpl) GetUser(session Session, opts ...rest.RequestOpt) (*discord.OAuth2User, error) { + if session.Expiration().Before(time.Now()) { + return nil, ErrAccessTokenExpired + } + if !discord.HasScope(discord.ApplicationScopeIdentify, session.Scopes()...) { + return nil, ErrMissingOAuth2Scope(discord.ApplicationScopeIdentify) + } + + return c.Rest().GetCurrentUser(session.AccessToken(), opts...) +} + +// GetGuilds returns the discord.OAuth2Guild(s) the user is a member of. This requires the discord.ApplicationScopeGuilds scope in the session +func (c *ClientImpl) GetGuilds(session Session, opts ...rest.RequestOpt) ([]discord.OAuth2Guild, error) { + if session.Expiration().Before(time.Now()) { + return nil, ErrAccessTokenExpired + } + if !discord.HasScope(discord.ApplicationScopeGuilds, session.Scopes()...) { + return nil, ErrMissingOAuth2Scope(discord.ApplicationScopeGuilds) + } + + return c.Rest().GetCurrentUserGuilds(session.AccessToken(), "", "", 0, opts...) +} + +// GetConnections returns the discord.Connection(s) the user has connected. This requires the discord.ApplicationScopeConnections scope in the session +func (c *ClientImpl) GetConnections(session Session, opts ...rest.RequestOpt) ([]discord.Connection, error) { + if session.Expiration().Before(time.Now()) { + return nil, ErrAccessTokenExpired + } + if !discord.HasScope(discord.ApplicationScopeConnections, session.Scopes()...) { + return nil, ErrMissingOAuth2Scope(discord.ApplicationScopeConnections) + } + + return c.Rest().GetCurrentUserConnections(session.AccessToken(), opts...) +} diff --git a/oauth2/config.go b/oauth2/config.go index 40ab371b..dd989c69 100644 --- a/oauth2/config.go +++ b/oauth2/config.go @@ -1,24 +1,27 @@ package oauth2 import ( - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/rest" + "github.com/disgoorg/log" ) // DefaultConfig is the configuration which is used by default -var DefaultConfig = Config{ - RestClientConfig: &rest.DefaultConfig, +func DefaultConfig() *Config { + return &Config{ + Logger: log.Default(), + SessionController: NewSessionController(), + } } // Config is the configuration for the OAuth2 client type Config struct { - Logger log.Logger - RestClient rest.Client - RestClientConfig *rest.Config - OAuth2Service rest.OAuth2Service - SessionController SessionController - StateControllerConfig *StateControllerConfig - StateController StateController + Logger log.Logger + RestClient rest.Client + RestClientConfigOpts []rest.ConfigOpt + OAuth2 rest.OAuth2 + SessionController SessionController + StateController StateController + StateControllerConfigOpts []StateControllerConfigOpt } // ConfigOpt can be used to supply optional parameters to New @@ -29,10 +32,18 @@ func (c *Config) Apply(opts []ConfigOpt) { for _, opt := range opts { opt(c) } + if c.RestClient == nil { + c.RestClient = rest.NewClient("", c.RestClientConfigOpts...) + } + if c.OAuth2 == nil { + c.OAuth2 = rest.NewOAuth2(c.RestClient) + } + if c.StateController == nil { + c.StateController = NewStateController(c.StateControllerConfigOpts...) + } } // WithLogger applies a custom logger to the OAuth2 client -//goland:noinspection GoUnusedExportedFunction func WithLogger(logger log.Logger) ConfigOpt { return func(config *Config) { config.Logger = logger @@ -40,42 +51,27 @@ func WithLogger(logger log.Logger) ConfigOpt { } // WithRestClient applies a custom rest.Client to the OAuth2 client -//goland:noinspection GoUnusedExportedFunction func WithRestClient(restClient rest.Client) ConfigOpt { return func(config *Config) { config.RestClient = restClient } } -// WithRestClientConfig applies a custom rest.Config to the OAuth2 client -//goland:noinspection GoUnusedExportedFunction -func WithRestClientConfig(restConfig rest.Config) ConfigOpt { - return func(config *Config) { - config.RestClientConfig = &restConfig - } -} - // WithRestClientConfigOpts applies rest.ConfigOpt for the rest.Client to the OAuth2 client -//goland:noinspection GoUnusedExportedFunction func WithRestClientConfigOpts(opts ...rest.ConfigOpt) ConfigOpt { return func(config *Config) { - if config.RestClientConfig == nil { - config.RestClientConfig = &rest.DefaultConfig - } - config.RestClientConfig.Apply(opts) + config.RestClientConfigOpts = append(config.RestClientConfigOpts, opts...) } } -// WithOAuth2Service applies a custom rest.OAuth2Service to the OAuth2 client -//goland:noinspection GoUnusedExportedFunction -func WithOAuth2Service(oauth2service rest.OAuth2Service) ConfigOpt { +// WithOAuth2 applies a custom rest.OAuth2 to the OAuth2 client +func WithOAuth2(oauth2 rest.OAuth2) ConfigOpt { return func(config *Config) { - config.OAuth2Service = oauth2service + config.OAuth2 = oauth2 } } // WithSessionController applies a custom SessionController to the OAuth2 client -//goland:noinspection GoUnusedExportedFunction func WithSessionController(sessionController SessionController) ConfigOpt { return func(config *Config) { config.SessionController = sessionController @@ -83,28 +79,15 @@ func WithSessionController(sessionController SessionController) ConfigOpt { } // WithStateController applies a custom StateController to the OAuth2 client -//goland:noinspection GoUnusedExportedFunction func WithStateController(stateController StateController) ConfigOpt { return func(config *Config) { config.StateController = stateController } } -// WithStateControllerConfig applies a custom StateControllerConfig to the SessionController -//goland:noinspection GoUnusedExportedFunction -func WithStateControllerConfig(stateControllerConfig StateControllerConfig) ConfigOpt { - return func(config *Config) { - config.StateControllerConfig = &stateControllerConfig - } -} - // WithStateControllerOpts applies all StateControllerConfigOpt(s) to the StateController -//goland:noinspection GoUnusedExportedFunction func WithStateControllerOpts(opts ...StateControllerConfigOpt) ConfigOpt { return func(config *Config) { - if config.StateControllerConfig == nil { - config.StateControllerConfig = &DefaultStateControllerConfig - } - config.StateControllerConfig.Apply(opts) + config.StateControllerConfigOpts = append(config.StateControllerConfigOpts, opts...) } } diff --git a/oauth2/session.go b/oauth2/session.go index a3a82bd3..b897f654 100644 --- a/oauth2/session.go +++ b/oauth2/session.go @@ -3,7 +3,7 @@ package oauth2 import ( "time" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/discord" ) var _ Session = (*sessionImpl)(nil) diff --git a/oauth2/session_controller.go b/oauth2/session_controller.go index a692abf6..01a6bc1f 100644 --- a/oauth2/session_controller.go +++ b/oauth2/session_controller.go @@ -3,7 +3,7 @@ package oauth2 import ( "time" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/discord" ) var _ SessionController = (*sessionControllerImpl)(nil) diff --git a/oauth2/state_controller.go b/oauth2/state_controller.go index 5f27af2a..22ec5134 100644 --- a/oauth2/state_controller.go +++ b/oauth2/state_controller.go @@ -14,10 +14,9 @@ type StateController interface { } // NewStateController returns a new empty StateController -func NewStateController(config *StateControllerConfig) StateController { - if config == nil { - config = &DefaultStateControllerConfig - } +func NewStateController(opts ...StateControllerConfigOpt) StateController { + config := DefaultStateControllerConfig() + config.Apply(opts) states := NewTTLMap(config.MaxTTL) for state, url := range config.States { diff --git a/oauth2/state_controller_config.go b/oauth2/state_controller_config.go index e7a085e6..cde0eac1 100644 --- a/oauth2/state_controller_config.go +++ b/oauth2/state_controller_config.go @@ -3,14 +3,16 @@ package oauth2 import ( "time" - "github.com/DisgoOrg/disgo/internal/insecurerandstr" + "github.com/disgoorg/disgo/internal/insecurerandstr" ) // DefaultStateControllerConfig is the default configuration for the StateController -var DefaultStateControllerConfig = StateControllerConfig{ - States: map[string]string{}, - NewStateFunc: func() string { return insecurerandstr.RandStr(32) }, - MaxTTL: time.Hour, +func DefaultStateControllerConfig() *StateControllerConfig { + return &StateControllerConfig{ + States: map[string]string{}, + NewStateFunc: func() string { return insecurerandstr.RandStr(32) }, + MaxTTL: time.Hour, + } } // StateControllerConfig is the configuration for the StateController @@ -31,7 +33,6 @@ func (c *StateControllerConfig) Apply(opts []StateControllerConfigOpt) { } // WithStates loads states from an existing map -//goland:noinspection GoUnusedExportedFunction func WithStates(states map[string]string) StateControllerConfigOpt { return func(config *StateControllerConfig) { config.States = states @@ -39,7 +40,6 @@ func WithStates(states map[string]string) StateControllerConfigOpt { } // WithNewStateFunc sets the function which is used to generate a new random state -//goland:noinspection GoUnusedExportedFunction func WithNewStateFunc(newStateFunc func() string) StateControllerConfigOpt { return func(config *StateControllerConfig) { config.NewStateFunc = newStateFunc @@ -47,7 +47,6 @@ func WithNewStateFunc(newStateFunc func() string) StateControllerConfigOpt { } // WithMaxTTL sets the maximum time to live for a state -//goland:noinspection GoUnusedExportedFunction func WithMaxTTL(maxTTL time.Duration) StateControllerConfigOpt { return func(config *StateControllerConfig) { config.MaxTTL = maxTTL diff --git a/rest/application_service.go b/rest/applications.go similarity index 64% rename from rest/application_service.go rename to rest/applications.go index 4f5def62..569c16ed 100644 --- a/rest/application_service.go +++ b/rest/applications.go @@ -1,30 +1,26 @@ package rest import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) -var ( - _ Service = (*applicationServiceImpl)(nil) - _ ApplicationService = (*applicationServiceImpl)(nil) -) +var _ Applications = (*applicationsImpl)(nil) -func NewApplicationService(restClient Client) ApplicationService { - return &applicationServiceImpl{restClient: restClient} +func NewApplications(restClient Client) Applications { + return &applicationsImpl{restClient: restClient} } -type ApplicationService interface { - Service - GetGlobalCommands(applicationID snowflake.Snowflake, opts ...RequestOpt) ([]discord.ApplicationCommand, error) +type Applications interface { + GetGlobalCommands(applicationID snowflake.Snowflake, withLocalizations bool, opts ...RequestOpt) ([]discord.ApplicationCommand, error) GetGlobalCommand(applicationID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...RequestOpt) (discord.ApplicationCommand, error) CreateGlobalCommand(applicationID snowflake.Snowflake, commandCreate discord.ApplicationCommandCreate, opts ...RequestOpt) (discord.ApplicationCommand, error) SetGlobalCommands(applicationID snowflake.Snowflake, commandCreates []discord.ApplicationCommandCreate, opts ...RequestOpt) ([]discord.ApplicationCommand, error) UpdateGlobalCommand(applicationID snowflake.Snowflake, commandID snowflake.Snowflake, commandUpdate discord.ApplicationCommandUpdate, opts ...RequestOpt) (discord.ApplicationCommand, error) DeleteGlobalCommand(applicationID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...RequestOpt) error - GetGuildCommands(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.ApplicationCommand, error) + GetGuildCommands(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, withLocalizations bool, opts ...RequestOpt) ([]discord.ApplicationCommand, error) GetGuildCommand(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...RequestOpt) (discord.ApplicationCommand, error) CreateGuildCommand(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, command discord.ApplicationCommandCreate, opts ...RequestOpt) (discord.ApplicationCommand, error) SetGuildCommands(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commands []discord.ApplicationCommandCreate, opts ...RequestOpt) ([]discord.ApplicationCommand, error) @@ -37,17 +33,13 @@ type ApplicationService interface { SetGuildCommandPermissions(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandID snowflake.Snowflake, commandPermissions []discord.ApplicationCommandPermission, opts ...RequestOpt) (*discord.ApplicationCommandPermissions, error) } -type applicationServiceImpl struct { +type applicationsImpl struct { restClient Client } -func (s *applicationServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *applicationServiceImpl) GetGlobalCommands(applicationID snowflake.Snowflake, opts ...RequestOpt) (commands []discord.ApplicationCommand, err error) { +func (s *applicationsImpl) GetGlobalCommands(applicationID snowflake.Snowflake, withLocalizations bool, opts ...RequestOpt) (commands []discord.ApplicationCommand, err error) { var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetGlobalCommands.Compile(nil, applicationID) + compiledRoute, err = route.GetGlobalCommands.Compile(route.QueryValues{"with_localizations": withLocalizations}, applicationID) if err != nil { return } @@ -59,7 +51,7 @@ func (s *applicationServiceImpl) GetGlobalCommands(applicationID snowflake.Snowf return } -func (s *applicationServiceImpl) GetGlobalCommand(applicationID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...RequestOpt) (command discord.ApplicationCommand, err error) { +func (s *applicationsImpl) GetGlobalCommand(applicationID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...RequestOpt) (command discord.ApplicationCommand, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetGlobalCommand.Compile(nil, applicationID, commandID) if err != nil { @@ -73,7 +65,7 @@ func (s *applicationServiceImpl) GetGlobalCommand(applicationID snowflake.Snowfl return } -func (s *applicationServiceImpl) CreateGlobalCommand(applicationID snowflake.Snowflake, commandCreate discord.ApplicationCommandCreate, opts ...RequestOpt) (command discord.ApplicationCommand, err error) { +func (s *applicationsImpl) CreateGlobalCommand(applicationID snowflake.Snowflake, commandCreate discord.ApplicationCommandCreate, opts ...RequestOpt) (command discord.ApplicationCommand, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateGlobalCommand.Compile(nil, applicationID) if err != nil { @@ -87,7 +79,7 @@ func (s *applicationServiceImpl) CreateGlobalCommand(applicationID snowflake.Sno return } -func (s *applicationServiceImpl) SetGlobalCommands(applicationID snowflake.Snowflake, commandCreates []discord.ApplicationCommandCreate, opts ...RequestOpt) (commands []discord.ApplicationCommand, err error) { +func (s *applicationsImpl) SetGlobalCommands(applicationID snowflake.Snowflake, commandCreates []discord.ApplicationCommandCreate, opts ...RequestOpt) (commands []discord.ApplicationCommand, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.SetGlobalCommands.Compile(nil, applicationID) if err != nil { @@ -101,7 +93,7 @@ func (s *applicationServiceImpl) SetGlobalCommands(applicationID snowflake.Snowf return } -func (s *applicationServiceImpl) UpdateGlobalCommand(applicationID snowflake.Snowflake, commandID snowflake.Snowflake, commandUpdate discord.ApplicationCommandUpdate, opts ...RequestOpt) (command discord.ApplicationCommand, err error) { +func (s *applicationsImpl) UpdateGlobalCommand(applicationID snowflake.Snowflake, commandID snowflake.Snowflake, commandUpdate discord.ApplicationCommandUpdate, opts ...RequestOpt) (command discord.ApplicationCommand, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateGlobalCommand.Compile(nil, applicationID, commandID) if err != nil { @@ -115,7 +107,7 @@ func (s *applicationServiceImpl) UpdateGlobalCommand(applicationID snowflake.Sno return } -func (s *applicationServiceImpl) DeleteGlobalCommand(applicationID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *applicationsImpl) DeleteGlobalCommand(applicationID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.DeleteGlobalCommand.Compile(nil, applicationID, commandID) if err != nil { return err @@ -123,9 +115,9 @@ func (s *applicationServiceImpl) DeleteGlobalCommand(applicationID snowflake.Sno return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *applicationServiceImpl) GetGuildCommands(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, opts ...RequestOpt) (commands []discord.ApplicationCommand, err error) { +func (s *applicationsImpl) GetGuildCommands(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, withLocalizations bool, opts ...RequestOpt) (commands []discord.ApplicationCommand, err error) { var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetGuildCommands.Compile(nil, applicationID, guildID) + compiledRoute, err = route.GetGuildCommands.Compile(route.QueryValues{"with_localizations": withLocalizations}, applicationID, guildID) if err != nil { return } @@ -137,7 +129,7 @@ func (s *applicationServiceImpl) GetGuildCommands(applicationID snowflake.Snowfl return } -func (s *applicationServiceImpl) GetGuildCommand(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...RequestOpt) (command discord.ApplicationCommand, err error) { +func (s *applicationsImpl) GetGuildCommand(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...RequestOpt) (command discord.ApplicationCommand, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetGuildCommand.Compile(nil, applicationID, guildID, commandID) if err != nil { @@ -151,7 +143,7 @@ func (s *applicationServiceImpl) GetGuildCommand(applicationID snowflake.Snowfla return } -func (s *applicationServiceImpl) CreateGuildCommand(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandCreate discord.ApplicationCommandCreate, opts ...RequestOpt) (command discord.ApplicationCommand, err error) { +func (s *applicationsImpl) CreateGuildCommand(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandCreate discord.ApplicationCommandCreate, opts ...RequestOpt) (command discord.ApplicationCommand, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateGuildCommand.Compile(nil, applicationID, guildID) if err != nil { @@ -165,7 +157,7 @@ func (s *applicationServiceImpl) CreateGuildCommand(applicationID snowflake.Snow return } -func (s *applicationServiceImpl) SetGuildCommands(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandCreates []discord.ApplicationCommandCreate, opts ...RequestOpt) (commands []discord.ApplicationCommand, err error) { +func (s *applicationsImpl) SetGuildCommands(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandCreates []discord.ApplicationCommandCreate, opts ...RequestOpt) (commands []discord.ApplicationCommand, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.SetGuildCommands.Compile(nil, applicationID, guildID) if err != nil { @@ -179,7 +171,7 @@ func (s *applicationServiceImpl) SetGuildCommands(applicationID snowflake.Snowfl return } -func (s *applicationServiceImpl) UpdateGuildCommand(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandID snowflake.Snowflake, commandUpdate discord.ApplicationCommandUpdate, opts ...RequestOpt) (command discord.ApplicationCommand, err error) { +func (s *applicationsImpl) UpdateGuildCommand(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandID snowflake.Snowflake, commandUpdate discord.ApplicationCommandUpdate, opts ...RequestOpt) (command discord.ApplicationCommand, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateGuildCommand.Compile(nil, applicationID, guildID, commandID) if err != nil { @@ -193,7 +185,7 @@ func (s *applicationServiceImpl) UpdateGuildCommand(applicationID snowflake.Snow return } -func (s *applicationServiceImpl) DeleteGuildCommand(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *applicationsImpl) DeleteGuildCommand(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.DeleteGuildCommand.Compile(nil, applicationID, guildID, commandID) if err != nil { return err @@ -201,7 +193,7 @@ func (s *applicationServiceImpl) DeleteGuildCommand(applicationID snowflake.Snow return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *applicationServiceImpl) GetGuildCommandsPermissions(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, opts ...RequestOpt) (commandsPerms []discord.ApplicationCommandPermissions, err error) { +func (s *applicationsImpl) GetGuildCommandsPermissions(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, opts ...RequestOpt) (commandsPerms []discord.ApplicationCommandPermissions, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetGuildCommandsPermissions.Compile(nil, applicationID, guildID) if err != nil { @@ -211,7 +203,7 @@ func (s *applicationServiceImpl) GetGuildCommandsPermissions(applicationID snowf return } -func (s *applicationServiceImpl) GetGuildCommandPermissions(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...RequestOpt) (commandPerms *discord.ApplicationCommandPermissions, err error) { +func (s *applicationsImpl) GetGuildCommandPermissions(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandID snowflake.Snowflake, opts ...RequestOpt) (commandPerms *discord.ApplicationCommandPermissions, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetGuildCommandPermissions.Compile(nil, applicationID, guildID, commandID) if err != nil { @@ -221,7 +213,7 @@ func (s *applicationServiceImpl) GetGuildCommandPermissions(applicationID snowfl return } -func (s *applicationServiceImpl) SetGuildCommandsPermissions(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandPermissions []discord.ApplicationCommandPermissionsSet, opts ...RequestOpt) (commandsPerms []discord.ApplicationCommandPermissions, err error) { +func (s *applicationsImpl) SetGuildCommandsPermissions(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandPermissions []discord.ApplicationCommandPermissionsSet, opts ...RequestOpt) (commandsPerms []discord.ApplicationCommandPermissions, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.SetGuildCommandsPermissions.Compile(nil, applicationID, guildID) if err != nil { @@ -231,7 +223,7 @@ func (s *applicationServiceImpl) SetGuildCommandsPermissions(applicationID snowf return } -func (s *applicationServiceImpl) SetGuildCommandPermissions(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandID snowflake.Snowflake, commandPermissions []discord.ApplicationCommandPermission, opts ...RequestOpt) (commandPerms *discord.ApplicationCommandPermissions, err error) { +func (s *applicationsImpl) SetGuildCommandPermissions(applicationID snowflake.Snowflake, guildID snowflake.Snowflake, commandID snowflake.Snowflake, commandPermissions []discord.ApplicationCommandPermission, opts ...RequestOpt) (commandPerms *discord.ApplicationCommandPermissions, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.SetGuildCommandPermissions.Compile(nil, applicationID, guildID, commandID) if err != nil { diff --git a/rest/audit_log_service.go b/rest/audit_log_service.go deleted file mode 100644 index 28287875..00000000 --- a/rest/audit_log_service.go +++ /dev/null @@ -1,52 +0,0 @@ -package rest - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" -) - -var ( - _ Service = (*AuditLogServiceImpl)(nil) - _ AuditLogService = (*AuditLogServiceImpl)(nil) -) - -func NewAuditLogService(restClient Client) AuditLogService { - return &AuditLogServiceImpl{restClient: restClient} -} - -type AuditLogService interface { - Service - GetAuditLog(guildID snowflake.Snowflake, userID snowflake.Snowflake, actionType discord.AuditLogEvent, before snowflake.Snowflake, limit int, opts ...RequestOpt) (*discord.AuditLog, error) -} - -type AuditLogServiceImpl struct { - restClient Client -} - -func (s *AuditLogServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *AuditLogServiceImpl) GetAuditLog(guildID snowflake.Snowflake, userID snowflake.Snowflake, actionType discord.AuditLogEvent, before snowflake.Snowflake, limit int, opts ...RequestOpt) (auditLog *discord.AuditLog, err error) { - values := route.QueryValues{} - if userID != "" { - values["user_id"] = userID - } - if actionType != 0 { - values["action_type"] = actionType - } - if before != "" { - values["before"] = guildID - } - if limit != 0 { - values["limit"] = limit - } - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetAuditLogs.Compile(values, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &auditLog, opts...) - return -} diff --git a/rest/channel_service.go b/rest/channels.go similarity index 66% rename from rest/channel_service.go rename to rest/channels.go index 60610d99..d468404b 100644 --- a/rest/channel_service.go +++ b/rest/channels.go @@ -1,22 +1,18 @@ package rest import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) -var ( - _ Service = (*channelServiceImpl)(nil) - _ ChannelService = (*channelServiceImpl)(nil) -) +var _ Channels = (*channelImpl)(nil) -func NewChannelService(restClient Client) ChannelService { - return &channelServiceImpl{restClient: restClient} +func NewChannels(restClient Client) Channels { + return &channelImpl{restClient: restClient} } -type ChannelService interface { - Service +type Channels interface { GetChannel(channelID snowflake.Snowflake, opts ...RequestOpt) (discord.Channel, error) UpdateChannel(channelID snowflake.Snowflake, channelUpdate discord.ChannelUpdate, opts ...RequestOpt) (discord.Channel, error) DeleteChannel(channelID snowflake.Snowflake, opts ...RequestOpt) error @@ -52,15 +48,11 @@ type ChannelService interface { // TODO: add missing endpoints } -type channelServiceImpl struct { +type channelImpl struct { restClient Client } -func (s *channelServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *channelServiceImpl) GetChannel(channelID snowflake.Snowflake, opts ...RequestOpt) (channel discord.Channel, err error) { +func (s *channelImpl) GetChannel(channelID snowflake.Snowflake, opts ...RequestOpt) (channel discord.Channel, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetChannel.Compile(nil, channelID) if err != nil { @@ -74,7 +66,7 @@ func (s *channelServiceImpl) GetChannel(channelID snowflake.Snowflake, opts ...R return } -func (s *channelServiceImpl) UpdateChannel(channelID snowflake.Snowflake, channelUpdate discord.ChannelUpdate, opts ...RequestOpt) (channel discord.Channel, err error) { +func (s *channelImpl) UpdateChannel(channelID snowflake.Snowflake, channelUpdate discord.ChannelUpdate, opts ...RequestOpt) (channel discord.Channel, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateChannel.Compile(nil, channelID) if err != nil { @@ -88,7 +80,7 @@ func (s *channelServiceImpl) UpdateChannel(channelID snowflake.Snowflake, channe return } -func (s *channelServiceImpl) DeleteChannel(channelID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *channelImpl) DeleteChannel(channelID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.DeleteChannel.Compile(nil, channelID) if err != nil { return err @@ -96,7 +88,7 @@ func (s *channelServiceImpl) DeleteChannel(channelID snowflake.Snowflake, opts . return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *channelServiceImpl) GetWebhooks(channelID snowflake.Snowflake, opts ...RequestOpt) (webhooks []discord.Webhook, err error) { +func (s *channelImpl) GetWebhooks(channelID snowflake.Snowflake, opts ...RequestOpt) (webhooks []discord.Webhook, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetChannelWebhooks.Compile(nil, channelID) if err != nil { @@ -106,7 +98,7 @@ func (s *channelServiceImpl) GetWebhooks(channelID snowflake.Snowflake, opts ... return } -func (s *channelServiceImpl) CreateWebhook(channelID snowflake.Snowflake, webhookCreate discord.WebhookCreate, opts ...RequestOpt) (webhook discord.Webhook, err error) { +func (s *channelImpl) CreateWebhook(channelID snowflake.Snowflake, webhookCreate discord.WebhookCreate, opts ...RequestOpt) (webhook discord.Webhook, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateWebhook.Compile(nil, channelID) if err != nil { @@ -121,7 +113,7 @@ func (s *channelServiceImpl) CreateWebhook(channelID snowflake.Snowflake, webhoo return } -func (s *channelServiceImpl) GetPermissionOverwrites(channelID snowflake.Snowflake, opts ...RequestOpt) (overwrites []discord.PermissionOverwrite, err error) { +func (s *channelImpl) GetPermissionOverwrites(channelID snowflake.Snowflake, opts ...RequestOpt) (overwrites []discord.PermissionOverwrite, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetPermissionOverwrites.Compile(nil, channelID) if err != nil { @@ -131,7 +123,7 @@ func (s *channelServiceImpl) GetPermissionOverwrites(channelID snowflake.Snowfla return } -func (s *channelServiceImpl) GetPermissionOverwrite(channelID snowflake.Snowflake, overwriteID snowflake.Snowflake, opts ...RequestOpt) (overwrite *discord.PermissionOverwrite, err error) { +func (s *channelImpl) GetPermissionOverwrite(channelID snowflake.Snowflake, overwriteID snowflake.Snowflake, opts ...RequestOpt) (overwrite *discord.PermissionOverwrite, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetPermissionOverwrite.Compile(nil, channelID, overwriteID) if err != nil { @@ -141,7 +133,7 @@ func (s *channelServiceImpl) GetPermissionOverwrite(channelID snowflake.Snowflak return } -func (s *channelServiceImpl) UpdatePermissionOverwrite(channelID snowflake.Snowflake, overwriteID snowflake.Snowflake, permissionOverwrite discord.PermissionOverwriteUpdate, opts ...RequestOpt) error { +func (s *channelImpl) UpdatePermissionOverwrite(channelID snowflake.Snowflake, overwriteID snowflake.Snowflake, permissionOverwrite discord.PermissionOverwriteUpdate, opts ...RequestOpt) error { compiledRoute, err := route.UpdatePermissionOverwrite.Compile(nil, channelID, overwriteID) if err != nil { return err @@ -149,7 +141,7 @@ func (s *channelServiceImpl) UpdatePermissionOverwrite(channelID snowflake.Snowf return s.restClient.Do(compiledRoute, permissionOverwrite, nil, opts...) } -func (s *channelServiceImpl) DeletePermissionOverwrite(channelID snowflake.Snowflake, overwriteID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *channelImpl) DeletePermissionOverwrite(channelID snowflake.Snowflake, overwriteID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.DeletePermissionOverwrite.Compile(nil, channelID, overwriteID) if err != nil { return err @@ -157,7 +149,7 @@ func (s *channelServiceImpl) DeletePermissionOverwrite(channelID snowflake.Snowf return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *channelServiceImpl) SendTyping(channelID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *channelImpl) SendTyping(channelID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.SendTyping.Compile(nil, channelID) if err != nil { return err @@ -165,7 +157,7 @@ func (s *channelServiceImpl) SendTyping(channelID snowflake.Snowflake, opts ...R return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *channelServiceImpl) GetMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...RequestOpt) (message *discord.Message, err error) { +func (s *channelImpl) GetMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...RequestOpt) (message *discord.Message, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetMessage.Compile(nil, channelID, messageID) if err != nil { @@ -175,7 +167,7 @@ func (s *channelServiceImpl) GetMessage(channelID snowflake.Snowflake, messageID return } -func (s *channelServiceImpl) GetMessages(channelID snowflake.Snowflake, around snowflake.Snowflake, before snowflake.Snowflake, after snowflake.Snowflake, limit int, opts ...RequestOpt) (messages []discord.Message, err error) { +func (s *channelImpl) GetMessages(channelID snowflake.Snowflake, around snowflake.Snowflake, before snowflake.Snowflake, after snowflake.Snowflake, limit int, opts ...RequestOpt) (messages []discord.Message, err error) { values := route.QueryValues{} if around != "" { values["around"] = around @@ -198,7 +190,7 @@ func (s *channelServiceImpl) GetMessages(channelID snowflake.Snowflake, around s return } -func (s *channelServiceImpl) CreateMessage(channelID snowflake.Snowflake, messageCreate discord.MessageCreate, opts ...RequestOpt) (message *discord.Message, err error) { +func (s *channelImpl) CreateMessage(channelID snowflake.Snowflake, messageCreate discord.MessageCreate, opts ...RequestOpt) (message *discord.Message, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateMessage.Compile(nil, channelID) if err != nil { @@ -212,7 +204,7 @@ func (s *channelServiceImpl) CreateMessage(channelID snowflake.Snowflake, messag return } -func (s *channelServiceImpl) UpdateMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, messageUpdate discord.MessageUpdate, opts ...RequestOpt) (message *discord.Message, err error) { +func (s *channelImpl) UpdateMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, messageUpdate discord.MessageUpdate, opts ...RequestOpt) (message *discord.Message, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateMessage.Compile(nil, channelID, messageID) if err != nil { @@ -226,7 +218,7 @@ func (s *channelServiceImpl) UpdateMessage(channelID snowflake.Snowflake, messag return } -func (s *channelServiceImpl) DeleteMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *channelImpl) DeleteMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.DeleteMessage.Compile(nil, channelID, messageID) if err != nil { return err @@ -234,7 +226,7 @@ func (s *channelServiceImpl) DeleteMessage(channelID snowflake.Snowflake, messag return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *channelServiceImpl) BulkDeleteMessages(channelID snowflake.Snowflake, messageIDs []snowflake.Snowflake, opts ...RequestOpt) error { +func (s *channelImpl) BulkDeleteMessages(channelID snowflake.Snowflake, messageIDs []snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.BulkDeleteMessages.Compile(nil, channelID) if err != nil { return err @@ -242,7 +234,7 @@ func (s *channelServiceImpl) BulkDeleteMessages(channelID snowflake.Snowflake, m return s.restClient.Do(compiledRoute, discord.MessageBulkDelete{Messages: messageIDs}, nil, opts...) } -func (s *channelServiceImpl) CrosspostMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...RequestOpt) (message *discord.Message, err error) { +func (s *channelImpl) CrosspostMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...RequestOpt) (message *discord.Message, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CrosspostMessage.Compile(nil, channelID, messageID) if err != nil { @@ -252,7 +244,7 @@ func (s *channelServiceImpl) CrosspostMessage(channelID snowflake.Snowflake, mes return } -func (s *channelServiceImpl) GetReactions(channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, opts ...RequestOpt) (users []discord.User, err error) { +func (s *channelImpl) GetReactions(channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, opts ...RequestOpt) (users []discord.User, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetReactions.Compile(nil, channelID, messageID, emoji) if err != nil { @@ -262,7 +254,7 @@ func (s *channelServiceImpl) GetReactions(channelID snowflake.Snowflake, message return } -func (s *channelServiceImpl) AddReaction(channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, opts ...RequestOpt) error { +func (s *channelImpl) AddReaction(channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, opts ...RequestOpt) error { compiledRoute, err := route.AddReaction.Compile(nil, channelID, messageID, emoji) if err != nil { return err @@ -270,7 +262,7 @@ func (s *channelServiceImpl) AddReaction(channelID snowflake.Snowflake, messageI return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *channelServiceImpl) RemoveOwnReaction(channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, opts ...RequestOpt) error { +func (s *channelImpl) RemoveOwnReaction(channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, opts ...RequestOpt) error { compiledRoute, err := route.RemoveOwnReaction.Compile(nil, channelID, messageID, emoji) if err != nil { return err @@ -278,7 +270,7 @@ func (s *channelServiceImpl) RemoveOwnReaction(channelID snowflake.Snowflake, me return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *channelServiceImpl) RemoveUserReaction(channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, userID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *channelImpl) RemoveUserReaction(channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, userID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.RemoveUserReaction.Compile(nil, channelID, messageID, emoji, userID) if err != nil { return err @@ -286,7 +278,7 @@ func (s *channelServiceImpl) RemoveUserReaction(channelID snowflake.Snowflake, m return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *channelServiceImpl) RemoveAllReactions(channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *channelImpl) RemoveAllReactions(channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.RemoveAllReactions.Compile(nil, channelID, messageID) if err != nil { return err @@ -294,7 +286,7 @@ func (s *channelServiceImpl) RemoveAllReactions(channelID snowflake.Snowflake, m return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *channelServiceImpl) RemoveAllReactionsForEmoji(channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, opts ...RequestOpt) error { +func (s *channelImpl) RemoveAllReactionsForEmoji(channelID snowflake.Snowflake, messageID snowflake.Snowflake, emoji string, opts ...RequestOpt) error { compiledRoute, err := route.RemoveAllReactionsForEmoji.Compile(nil, channelID, messageID, emoji) if err != nil { return err @@ -302,7 +294,7 @@ func (s *channelServiceImpl) RemoveAllReactionsForEmoji(channelID snowflake.Snow return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *channelServiceImpl) GetPinnedMessages(channelID snowflake.Snowflake, opts ...RequestOpt) (messages []discord.Message, err error) { +func (s *channelImpl) GetPinnedMessages(channelID snowflake.Snowflake, opts ...RequestOpt) (messages []discord.Message, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetPinnedMessages.Compile(nil, channelID) if err != nil { @@ -312,7 +304,7 @@ func (s *channelServiceImpl) GetPinnedMessages(channelID snowflake.Snowflake, op return } -func (s *channelServiceImpl) PinMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *channelImpl) PinMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.PinMessage.Compile(nil, channelID, messageID) if err != nil { return err @@ -320,7 +312,7 @@ func (s *channelServiceImpl) PinMessage(channelID snowflake.Snowflake, messageID return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *channelServiceImpl) UnpinMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *channelImpl) UnpinMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.UnpinMessage.Compile(nil, channelID, messageID) if err != nil { return err diff --git a/rest/emoji_service.go b/rest/emojis.go similarity index 58% rename from rest/emoji_service.go rename to rest/emojis.go index 4274007a..bb7e8837 100644 --- a/rest/emoji_service.go +++ b/rest/emojis.go @@ -1,22 +1,18 @@ package rest import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) -var ( - _ Service = (*emojiServiceImpl)(nil) - _ EmojiService = (*emojiServiceImpl)(nil) -) +var _ Emojis = (*emojiImpl)(nil) -func NewEmojiService(restClient Client) EmojiService { - return &emojiServiceImpl{restClient: restClient} +func NewEmojis(restClient Client) Emojis { + return &emojiImpl{restClient: restClient} } -type EmojiService interface { - Service +type Emojis interface { GetEmojis(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Emoji, error) GetEmoji(guildID snowflake.Snowflake, emojiID snowflake.Snowflake, opts ...RequestOpt) (*discord.Emoji, error) CreateEmoji(guildID snowflake.Snowflake, emojiCreate discord.EmojiCreate, opts ...RequestOpt) (*discord.Emoji, error) @@ -24,15 +20,11 @@ type EmojiService interface { DeleteEmoji(guildID snowflake.Snowflake, emojiID snowflake.Snowflake, opts ...RequestOpt) error } -type emojiServiceImpl struct { +type emojiImpl struct { restClient Client } -func (s *emojiServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *emojiServiceImpl) GetEmojis(guildID snowflake.Snowflake, opts ...RequestOpt) (emojis []discord.Emoji, err error) { +func (s *emojiImpl) GetEmojis(guildID snowflake.Snowflake, opts ...RequestOpt) (emojis []discord.Emoji, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetEmojis.Compile(nil, guildID) if err != nil { @@ -42,7 +34,7 @@ func (s *emojiServiceImpl) GetEmojis(guildID snowflake.Snowflake, opts ...Reques return } -func (s *emojiServiceImpl) GetEmoji(guildID snowflake.Snowflake, emojiID snowflake.Snowflake, opts ...RequestOpt) (emoji *discord.Emoji, err error) { +func (s *emojiImpl) GetEmoji(guildID snowflake.Snowflake, emojiID snowflake.Snowflake, opts ...RequestOpt) (emoji *discord.Emoji, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetEmoji.Compile(nil, guildID, emojiID) if err != nil { @@ -52,7 +44,7 @@ func (s *emojiServiceImpl) GetEmoji(guildID snowflake.Snowflake, emojiID snowfla return } -func (s *emojiServiceImpl) CreateEmoji(guildID snowflake.Snowflake, emojiCreate discord.EmojiCreate, opts ...RequestOpt) (emoji *discord.Emoji, err error) { +func (s *emojiImpl) CreateEmoji(guildID snowflake.Snowflake, emojiCreate discord.EmojiCreate, opts ...RequestOpt) (emoji *discord.Emoji, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateEmoji.Compile(nil, guildID) if err != nil { @@ -62,7 +54,7 @@ func (s *emojiServiceImpl) CreateEmoji(guildID snowflake.Snowflake, emojiCreate return } -func (s *emojiServiceImpl) UpdateEmoji(guildID snowflake.Snowflake, emojiID snowflake.Snowflake, emojiUpdate discord.EmojiUpdate, opts ...RequestOpt) (emoji *discord.Emoji, err error) { +func (s *emojiImpl) UpdateEmoji(guildID snowflake.Snowflake, emojiID snowflake.Snowflake, emojiUpdate discord.EmojiUpdate, opts ...RequestOpt) (emoji *discord.Emoji, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateEmoji.Compile(nil, guildID, emojiID) if err != nil { @@ -72,7 +64,7 @@ func (s *emojiServiceImpl) UpdateEmoji(guildID snowflake.Snowflake, emojiID snow return } -func (s *emojiServiceImpl) DeleteEmoji(guildID snowflake.Snowflake, emojiID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *emojiImpl) DeleteEmoji(guildID snowflake.Snowflake, emojiID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.DeleteEmoji.Compile(nil, guildID, emojiID) if err != nil { return err diff --git a/rest/gateway.go b/rest/gateway.go new file mode 100644 index 00000000..9308726e --- /dev/null +++ b/rest/gateway.go @@ -0,0 +1,41 @@ +package rest + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" +) + +var _ Gateway = (*gatewayImpl)(nil) + +func NewGateway(restClient Client) Gateway { + return &gatewayImpl{restClient: restClient} +} + +type Gateway interface { + GetGateway(opts ...RequestOpt) (*discord.Gateway, error) + GetGatewayBot(opts ...RequestOpt) (*discord.GatewayBot, error) +} + +type gatewayImpl struct { + restClient Client +} + +func (s *gatewayImpl) GetGateway(opts ...RequestOpt) (gateway *discord.Gateway, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetGateway.Compile(nil) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &gateway, opts...) + return +} + +func (s *gatewayImpl) GetGatewayBot(opts ...RequestOpt) (gatewayBot *discord.GatewayBot, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetGatewayBot.Compile(nil) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &gatewayBot, opts...) + return +} diff --git a/rest/gateway_service.go b/rest/gateway_service.go deleted file mode 100644 index ccf5fb72..00000000 --- a/rest/gateway_service.go +++ /dev/null @@ -1,49 +0,0 @@ -package rest - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" -) - -var ( - _ Service = (*gatewayServiceImpl)(nil) - _ GatewayService = (*gatewayServiceImpl)(nil) -) - -func NewGatewayService(restClient Client) GatewayService { - return &gatewayServiceImpl{restClient: restClient} -} - -type GatewayService interface { - Service - GetGateway(opts ...RequestOpt) (*discord.Gateway, error) - GetGatewayBot(opts ...RequestOpt) (*discord.GatewayBot, error) -} - -type gatewayServiceImpl struct { - restClient Client -} - -func (s *gatewayServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *gatewayServiceImpl) GetGateway(opts ...RequestOpt) (gateway *discord.Gateway, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetGateway.Compile(nil) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &gateway, opts...) - return -} - -func (s *gatewayServiceImpl) GetGatewayBot(opts ...RequestOpt) (gatewayBot *discord.GatewayBot, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetGatewayBot.Compile(nil) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &gatewayBot, opts...) - return -} diff --git a/rest/guild_scheduled_event_service.go b/rest/guild_scheduled_events.go similarity index 60% rename from rest/guild_scheduled_event_service.go rename to rest/guild_scheduled_events.go index 62862479..f96c8fbd 100644 --- a/rest/guild_scheduled_event_service.go +++ b/rest/guild_scheduled_events.go @@ -1,22 +1,18 @@ package rest import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) -var ( - _ Service = (*guildScheduledEventServiceImpl)(nil) - _ GuildScheduledEventService = (*guildScheduledEventServiceImpl)(nil) -) +var _ GuildScheduledEvents = (*guildScheduledEventImpl)(nil) -func NewGuildScheduledEventService(restClient Client) GuildScheduledEventService { - return &guildScheduledEventServiceImpl{restClient: restClient} +func NewGuildScheduledEvents(restClient Client) GuildScheduledEvents { + return &guildScheduledEventImpl{restClient: restClient} } -type GuildScheduledEventService interface { - Service +type GuildScheduledEvents interface { GetGuildScheduledEvents(guildID snowflake.Snowflake, withUserCounts bool, opts ...RequestOpt) ([]discord.GuildScheduledEvent, error) GetGuildScheduledEvent(guildID snowflake.Snowflake, guildScheduledEventID snowflake.Snowflake, withUserCounts bool, opts ...RequestOpt) (*discord.GuildScheduledEvent, error) CreateGuildScheduledEvent(guildID snowflake.Snowflake, guildScheduledEventCreate discord.GuildScheduledEventCreate, opts ...RequestOpt) (*discord.GuildScheduledEvent, error) @@ -26,15 +22,11 @@ type GuildScheduledEventService interface { GetGuildScheduledEventUsers(guildID snowflake.Snowflake, guildScheduledEventID snowflake.Snowflake, limit int, withMember bool, before snowflake.Snowflake, after snowflake.Snowflake, opts ...RequestOpt) ([]discord.GuildScheduledEventUser, error) } -type guildScheduledEventServiceImpl struct { +type guildScheduledEventImpl struct { restClient Client } -func (s *guildScheduledEventServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *guildScheduledEventServiceImpl) GetGuildScheduledEvents(guildID snowflake.Snowflake, withUserCounts bool, opts ...RequestOpt) (guildScheduledEvents []discord.GuildScheduledEvent, err error) { +func (s *guildScheduledEventImpl) GetGuildScheduledEvents(guildID snowflake.Snowflake, withUserCounts bool, opts ...RequestOpt) (guildScheduledEvents []discord.GuildScheduledEvent, err error) { queryValues := route.QueryValues{} if withUserCounts { queryValues["with_user_counts"] = true @@ -48,7 +40,7 @@ func (s *guildScheduledEventServiceImpl) GetGuildScheduledEvents(guildID snowfla return } -func (s *guildScheduledEventServiceImpl) GetGuildScheduledEvent(guildID snowflake.Snowflake, guildScheduledEventID snowflake.Snowflake, withUserCounts bool, opts ...RequestOpt) (guildScheduledEvent *discord.GuildScheduledEvent, err error) { +func (s *guildScheduledEventImpl) GetGuildScheduledEvent(guildID snowflake.Snowflake, guildScheduledEventID snowflake.Snowflake, withUserCounts bool, opts ...RequestOpt) (guildScheduledEvent *discord.GuildScheduledEvent, err error) { queryValues := route.QueryValues{} if withUserCounts { queryValues["with_user_counts"] = true @@ -62,7 +54,7 @@ func (s *guildScheduledEventServiceImpl) GetGuildScheduledEvent(guildID snowflak return } -func (s *guildScheduledEventServiceImpl) CreateGuildScheduledEvent(guildID snowflake.Snowflake, guildScheduledEventCreate discord.GuildScheduledEventCreate, opts ...RequestOpt) (guildScheduledEvent *discord.GuildScheduledEvent, err error) { +func (s *guildScheduledEventImpl) CreateGuildScheduledEvent(guildID snowflake.Snowflake, guildScheduledEventCreate discord.GuildScheduledEventCreate, opts ...RequestOpt) (guildScheduledEvent *discord.GuildScheduledEvent, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateGuildScheduledEvent.Compile(nil, guildID) if err != nil { @@ -72,7 +64,7 @@ func (s *guildScheduledEventServiceImpl) CreateGuildScheduledEvent(guildID snowf return } -func (s *guildScheduledEventServiceImpl) UpdateGuildScheduledEvent(guildID snowflake.Snowflake, guildScheduledEventID snowflake.Snowflake, guildScheduledEventUpdate discord.GuildScheduledEventUpdate, opts ...RequestOpt) (guildScheduledEvent *discord.GuildScheduledEvent, err error) { +func (s *guildScheduledEventImpl) UpdateGuildScheduledEvent(guildID snowflake.Snowflake, guildScheduledEventID snowflake.Snowflake, guildScheduledEventUpdate discord.GuildScheduledEventUpdate, opts ...RequestOpt) (guildScheduledEvent *discord.GuildScheduledEvent, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateGuildScheduledEvent.Compile(nil, guildID, guildScheduledEventID) if err != nil { @@ -82,7 +74,7 @@ func (s *guildScheduledEventServiceImpl) UpdateGuildScheduledEvent(guildID snowf return } -func (s *guildScheduledEventServiceImpl) DeleteGuildScheduledEvent(guildID snowflake.Snowflake, guildScheduledEventID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *guildScheduledEventImpl) DeleteGuildScheduledEvent(guildID snowflake.Snowflake, guildScheduledEventID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.DeleteGuildScheduledEvent.Compile(nil, guildID, guildScheduledEventID) if err != nil { return err @@ -90,7 +82,7 @@ func (s *guildScheduledEventServiceImpl) DeleteGuildScheduledEvent(guildID snowf return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *guildScheduledEventServiceImpl) GetGuildScheduledEventUsers(guildID snowflake.Snowflake, guildScheduledEventID snowflake.Snowflake, limit int, withMember bool, before snowflake.Snowflake, after snowflake.Snowflake, opts ...RequestOpt) (guildScheduledEventUsers []discord.GuildScheduledEventUser, err error) { +func (s *guildScheduledEventImpl) GetGuildScheduledEventUsers(guildID snowflake.Snowflake, guildScheduledEventID snowflake.Snowflake, limit int, withMember bool, before snowflake.Snowflake, after snowflake.Snowflake, opts ...RequestOpt) (guildScheduledEventUsers []discord.GuildScheduledEventUser, err error) { queryValues := route.QueryValues{} if limit > 0 { queryValues["limit"] = limit diff --git a/rest/guild_service.go b/rest/guild_service.go deleted file mode 100644 index 356b41c9..00000000 --- a/rest/guild_service.go +++ /dev/null @@ -1,370 +0,0 @@ -package rest - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" -) - -var ( - _ Service = (*guildServiceImpl)(nil) - _ GuildService = (*guildServiceImpl)(nil) -) - -func NewGuildService(restClient Client) GuildService { - return &guildServiceImpl{restClient: restClient} -} - -type GuildService interface { - Service - GetGuild(guildID snowflake.Snowflake, withCounts bool, opts ...RequestOpt) (*discord.Guild, error) - GetGuildPreview(guildID snowflake.Snowflake, opts ...RequestOpt) (*discord.GuildPreview, error) - CreateGuild(guildCreate discord.GuildCreate, opts ...RequestOpt) (*discord.Guild, error) - UpdateGuild(guildID snowflake.Snowflake, guildUpdate discord.GuildUpdate, opts ...RequestOpt) (*discord.Guild, error) - DeleteGuild(guildID snowflake.Snowflake, opts ...RequestOpt) error - - CreateChannel(guildID snowflake.Snowflake, guildChannelCreate discord.GuildChannelCreate, opts ...RequestOpt) (discord.GuildChannel, error) - - GetRoles(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Role, error) - GetRole(guildID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Role, error) - CreateRole(guildID snowflake.Snowflake, createRole discord.RoleCreate, opts ...RequestOpt) (*discord.Role, error) - UpdateRole(guildID snowflake.Snowflake, roleID snowflake.Snowflake, roleUpdate discord.RoleUpdate, opts ...RequestOpt) (*discord.Role, error) - UpdateRolePositions(guildID snowflake.Snowflake, rolePositionUpdates []discord.RolePositionUpdate, opts ...RequestOpt) ([]discord.Role, error) - DeleteRole(guildID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) error - - GetMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) (*discord.Member, error) - GetMembers(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Member, error) - SearchMembers(guildID snowflake.Snowflake, query string, limit int, opts ...RequestOpt) ([]discord.Member, error) - AddMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, memberAdd discord.MemberAdd, opts ...RequestOpt) (*discord.Member, error) - RemoveMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) error - UpdateMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, memberUpdate discord.MemberUpdate, opts ...RequestOpt) (*discord.Member, error) - AddMemberRole(guildID snowflake.Snowflake, userID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) error - RemoveMemberRole(guildID snowflake.Snowflake, userID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) error - - UpdateSelfNick(guildID snowflake.Snowflake, nick string, opts ...RequestOpt) (*string, error) - - GetBans(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Ban, error) - GetBan(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) (*discord.Ban, error) - AddBan(guildID snowflake.Snowflake, userID snowflake.Snowflake, deleteMessageDays int, opts ...RequestOpt) error - DeleteBan(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) error - - GetIntegrations(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Integration, error) - DeleteIntegration(guildID snowflake.Snowflake, integrationID snowflake.Snowflake, opts ...RequestOpt) error - GetWebhooks(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Webhook, error) - - UpdateCurrentUserVoiceState(guildID snowflake.Snowflake, currentUserVoiceStateUpdate discord.UserVoiceStateUpdate, opts ...RequestOpt) error - UpdateUserVoiceState(guildID snowflake.Snowflake, userID snowflake.Snowflake, userVoiceStateUpdate discord.UserVoiceStateUpdate, opts ...RequestOpt) error -} - -type guildServiceImpl struct { - restClient Client -} - -func (s *guildServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *guildServiceImpl) GetGuild(guildID snowflake.Snowflake, withCounts bool, opts ...RequestOpt) (guild *discord.Guild, err error) { - values := route.QueryValues{} - if withCounts { - values["withCounts"] = true - } - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetGuild.Compile(values, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &guild, opts...) - return -} - -func (s *guildServiceImpl) GetGuildPreview(guildID snowflake.Snowflake, opts ...RequestOpt) (guildPreview *discord.GuildPreview, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetGuildPreview.Compile(nil, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &guildPreview, opts...) - return -} - -func (s *guildServiceImpl) CreateGuild(guildCreate discord.GuildCreate, opts ...RequestOpt) (guild *discord.Guild, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.CreateGuild.Compile(nil) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, guildCreate, &guild, opts...) - return -} - -func (s *guildServiceImpl) UpdateGuild(guildID snowflake.Snowflake, guildUpdate discord.GuildUpdate, opts ...RequestOpt) (guild *discord.Guild, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.UpdateGuild.Compile(nil, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, guildUpdate, &guild, opts...) - return -} - -func (s *guildServiceImpl) DeleteGuild(guildID snowflake.Snowflake, opts ...RequestOpt) error { - compiledRoute, err := route.DeleteGuild.Compile(nil, guildID) - if err != nil { - return err - } - return s.restClient.Do(compiledRoute, nil, nil, opts...) -} - -func (s *guildServiceImpl) CreateChannel(guildID snowflake.Snowflake, guildChannelCreate discord.GuildChannelCreate, opts ...RequestOpt) (guildChannel discord.GuildChannel, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.CreateGuildChannel.Compile(nil, guildID) - if err != nil { - return - } - var ch discord.UnmarshalChannel - err = s.restClient.Do(compiledRoute, guildChannelCreate, &ch, opts...) - if err == nil { - guildChannel = ch.Channel.(discord.GuildChannel) - } - return -} - -func (s *guildServiceImpl) GetRoles(guildID snowflake.Snowflake, opts ...RequestOpt) (roles []discord.Role, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetRoles.Compile(nil, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &roles, opts...) - return -} - -func (s *guildServiceImpl) GetRole(guildID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) (role []discord.Role, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetRole.Compile(nil, guildID, roleID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &role, opts...) - return -} - -func (s *guildServiceImpl) CreateRole(guildID snowflake.Snowflake, createRole discord.RoleCreate, opts ...RequestOpt) (role *discord.Role, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.CreateRole.Compile(nil, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, createRole, &role, opts...) - return -} - -func (s *guildServiceImpl) UpdateRole(guildID snowflake.Snowflake, roleID snowflake.Snowflake, roleUpdate discord.RoleUpdate, opts ...RequestOpt) (role *discord.Role, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.UpdateRole.Compile(nil, guildID, roleID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, roleUpdate, &role, opts...) - return -} - -func (s *guildServiceImpl) UpdateRolePositions(guildID snowflake.Snowflake, rolePositionUpdates []discord.RolePositionUpdate, opts ...RequestOpt) (roles []discord.Role, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.UpdateRolePositions.Compile(nil, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, rolePositionUpdates, &roles, opts...) - return -} - -func (s *guildServiceImpl) DeleteRole(guildID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) error { - compiledRoute, err := route.DeleteRole.Compile(nil, guildID, roleID) - if err != nil { - return err - } - return s.restClient.Do(compiledRoute, nil, nil, opts...) -} - -func (s *guildServiceImpl) GetMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) (member *discord.Member, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetMember.Compile(nil, guildID, userID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &member, opts...) - return -} - -func (s *guildServiceImpl) GetMembers(guildID snowflake.Snowflake, opts ...RequestOpt) (members []discord.Member, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetMembers.Compile(nil, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &members, opts...) - return -} - -func (s *guildServiceImpl) SearchMembers(guildID snowflake.Snowflake, query string, limit int, opts ...RequestOpt) (members []discord.Member, err error) { - values := route.QueryValues{} - if query != "" { - values["query"] = query - } - if limit != 0 { - values["limit"] = limit - } - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.SearchMembers.Compile(values, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &members, opts...) - return -} - -func (s *guildServiceImpl) AddMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, memberAdd discord.MemberAdd, opts ...RequestOpt) (member *discord.Member, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetMembers.Compile(nil, guildID, userID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, memberAdd, &member, opts...) - return -} - -func (s *guildServiceImpl) RemoveMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) error { - compiledRoute, err := route.RemoveMember.Compile(nil, guildID, userID) - if err != nil { - return err - } - return s.restClient.Do(compiledRoute, nil, nil, opts...) -} - -func (s *guildServiceImpl) UpdateMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, memberUpdate discord.MemberUpdate, opts ...RequestOpt) (member *discord.Member, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.UpdateMember.Compile(nil, guildID, userID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, memberUpdate, &member, opts...) - return -} - -func (s *guildServiceImpl) AddMemberRole(guildID snowflake.Snowflake, userID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) error { - compiledRoute, err := route.AddMemberRole.Compile(nil, guildID, userID, roleID) - if err != nil { - return err - } - return s.restClient.Do(compiledRoute, nil, nil, opts...) -} - -func (s *guildServiceImpl) RemoveMemberRole(guildID snowflake.Snowflake, userID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) error { - compiledRoute, err := route.RemoveMemberRole.Compile(nil, guildID, userID, roleID) - if err != nil { - return err - } - return s.restClient.Do(compiledRoute, nil, nil, opts...) -} - -func (s *guildServiceImpl) UpdateSelfNick(guildID snowflake.Snowflake, nick string, opts ...RequestOpt) (nickName *string, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.UpdateSelfNick.Compile(nil, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, discord.SelfNickUpdate{Nick: nick}, nickName, opts...) - return -} - -func (s *guildServiceImpl) GetBans(guildID snowflake.Snowflake, opts ...RequestOpt) (bans []discord.Ban, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetBans.Compile(nil, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &bans, opts...) - return -} - -func (s *guildServiceImpl) GetBan(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) (ban *discord.Ban, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetBan.Compile(nil, guildID, userID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &ban, opts...) - return -} - -func (s *guildServiceImpl) AddBan(guildID snowflake.Snowflake, userID snowflake.Snowflake, deleteMessageDays int, opts ...RequestOpt) error { - compiledRoute, err := route.AddBan.Compile(nil, guildID, userID) - if err != nil { - return err - } - return s.restClient.Do(compiledRoute, discord.AddBan{DeleteMessageDays: deleteMessageDays}, nil, opts...) -} - -func (s *guildServiceImpl) DeleteBan(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) error { - compiledRoute, err := route.DeleteBan.Compile(nil, guildID, userID) - if err != nil { - return err - } - return s.restClient.Do(compiledRoute, nil, nil, opts...) -} - -func (s *guildServiceImpl) GetIntegrations(guildID snowflake.Snowflake, opts ...RequestOpt) (integrations []discord.Integration, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetIntegrations.Compile(nil, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &integrations, opts...) - return -} - -func (s *guildServiceImpl) DeleteIntegration(guildID snowflake.Snowflake, integrationID snowflake.Snowflake, opts ...RequestOpt) error { - compiledRoute, err := route.DeleteIntegration.Compile(nil, guildID, integrationID) - if err != nil { - return err - } - return s.restClient.Do(compiledRoute, nil, nil, opts...) -} - -func (s *guildServiceImpl) GetWebhooks(guildID snowflake.Snowflake, opts ...RequestOpt) (webhooks []discord.Webhook, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetGuildWebhooks.Compile(nil, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &webhooks, opts...) - return -} - -func (s *guildServiceImpl) GetEmojis(guildID snowflake.Snowflake, opts ...RequestOpt) (emojis []discord.Emoji, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetEmojis.Compile(nil, guildID) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, &emojis, opts...) - return -} - -func (s *guildServiceImpl) UpdateCurrentUserVoiceState(guildID snowflake.Snowflake, currentUserVoiceStateUpdate discord.UserVoiceStateUpdate, opts ...RequestOpt) error { - compiledRoute, err := route.UpdateCurrentUserVoiceState.Compile(nil, guildID) - if err != nil { - return err - } - return s.restClient.Do(compiledRoute, currentUserVoiceStateUpdate, nil, opts...) -} - -func (s *guildServiceImpl) UpdateUserVoiceState(guildID snowflake.Snowflake, userID snowflake.Snowflake, userVoiceStateUpdate discord.UserVoiceStateUpdate, opts ...RequestOpt) error { - compiledRoute, err := route.UpdateUserVoiceState.Compile(nil, guildID, userID) - if err != nil { - return err - } - return s.restClient.Do(compiledRoute, userVoiceStateUpdate, nil, opts...) -} diff --git a/rest/guild_template_service.go b/rest/guild_templates.go similarity index 58% rename from rest/guild_template_service.go rename to rest/guild_templates.go index 6cddae8b..e07e591d 100644 --- a/rest/guild_template_service.go +++ b/rest/guild_templates.go @@ -1,22 +1,18 @@ package rest import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) -var ( - _ Service = (*guildTemplateServiceImpl)(nil) - _ GuildTemplateService = (*guildTemplateServiceImpl)(nil) -) +var _ GuildTemplates = (*guildTemplateImpl)(nil) -func NewGuildTemplateService(restClient Client) GuildTemplateService { - return &guildTemplateServiceImpl{restClient: restClient} +func NewGuildTemplates(restClient Client) GuildTemplates { + return &guildTemplateImpl{restClient: restClient} } -type GuildTemplateService interface { - Service +type GuildTemplates interface { GetGuildTemplate(templateCode string, opts ...RequestOpt) (*discord.GuildTemplate, error) GetGuildTemplates(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.GuildTemplate, error) CreateGuildTemplate(guildID snowflake.Snowflake, guildTemplateCreate discord.GuildTemplateCreate, opts ...RequestOpt) (*discord.GuildTemplate, error) @@ -26,15 +22,11 @@ type GuildTemplateService interface { DeleteGuildTemplate(guildID snowflake.Snowflake, templateCode string, opts ...RequestOpt) (*discord.GuildTemplate, error) } -type guildTemplateServiceImpl struct { +type guildTemplateImpl struct { restClient Client } -func (s *guildTemplateServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *guildTemplateServiceImpl) GetGuildTemplate(templateCode string, opts ...RequestOpt) (guildTemplate *discord.GuildTemplate, err error) { +func (s *guildTemplateImpl) GetGuildTemplate(templateCode string, opts ...RequestOpt) (guildTemplate *discord.GuildTemplate, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetGuildTemplate.Compile(nil, templateCode) if err != nil { @@ -44,7 +36,7 @@ func (s *guildTemplateServiceImpl) GetGuildTemplate(templateCode string, opts .. return } -func (s *guildTemplateServiceImpl) GetGuildTemplates(guildID snowflake.Snowflake, opts ...RequestOpt) (guildTemplates []discord.GuildTemplate, err error) { +func (s *guildTemplateImpl) GetGuildTemplates(guildID snowflake.Snowflake, opts ...RequestOpt) (guildTemplates []discord.GuildTemplate, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetGuildTemplates.Compile(nil, guildID) if err != nil { @@ -54,7 +46,7 @@ func (s *guildTemplateServiceImpl) GetGuildTemplates(guildID snowflake.Snowflake return } -func (s *guildTemplateServiceImpl) CreateGuildTemplate(guildID snowflake.Snowflake, guildTemplateCreate discord.GuildTemplateCreate, opts ...RequestOpt) (guildTemplate *discord.GuildTemplate, err error) { +func (s *guildTemplateImpl) CreateGuildTemplate(guildID snowflake.Snowflake, guildTemplateCreate discord.GuildTemplateCreate, opts ...RequestOpt) (guildTemplate *discord.GuildTemplate, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateGuildTemplate.Compile(nil, guildID) if err != nil { @@ -64,7 +56,7 @@ func (s *guildTemplateServiceImpl) CreateGuildTemplate(guildID snowflake.Snowfla return } -func (s *guildTemplateServiceImpl) CreateGuildFromTemplate(templateCode string, createGuildFromTemplate discord.GuildFromTemplateCreate, opts ...RequestOpt) (guild *discord.Guild, err error) { +func (s *guildTemplateImpl) CreateGuildFromTemplate(templateCode string, createGuildFromTemplate discord.GuildFromTemplateCreate, opts ...RequestOpt) (guild *discord.Guild, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateGuildFromTemplate.Compile(nil, templateCode) if err != nil { @@ -74,7 +66,7 @@ func (s *guildTemplateServiceImpl) CreateGuildFromTemplate(templateCode string, return } -func (s *guildTemplateServiceImpl) SyncGuildTemplate(guildID snowflake.Snowflake, templateCode string, opts ...RequestOpt) (guildTemplate *discord.GuildTemplate, err error) { +func (s *guildTemplateImpl) SyncGuildTemplate(guildID snowflake.Snowflake, templateCode string, opts ...RequestOpt) (guildTemplate *discord.GuildTemplate, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.SyncGuildTemplate.Compile(nil, guildID, templateCode) if err != nil { @@ -84,7 +76,7 @@ func (s *guildTemplateServiceImpl) SyncGuildTemplate(guildID snowflake.Snowflake return } -func (s *guildTemplateServiceImpl) UpdateGuildTemplate(guildID snowflake.Snowflake, templateCode string, guildTemplateUpdate discord.GuildTemplateUpdate, opts ...RequestOpt) (guildTemplate *discord.GuildTemplate, err error) { +func (s *guildTemplateImpl) UpdateGuildTemplate(guildID snowflake.Snowflake, templateCode string, guildTemplateUpdate discord.GuildTemplateUpdate, opts ...RequestOpt) (guildTemplate *discord.GuildTemplate, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateGuildTemplate.Compile(nil, guildID, templateCode) if err != nil { @@ -94,7 +86,7 @@ func (s *guildTemplateServiceImpl) UpdateGuildTemplate(guildID snowflake.Snowfla return } -func (s *guildTemplateServiceImpl) DeleteGuildTemplate(guildID snowflake.Snowflake, templateCode string, opts ...RequestOpt) (guildTemplate *discord.GuildTemplate, err error) { +func (s *guildTemplateImpl) DeleteGuildTemplate(guildID snowflake.Snowflake, templateCode string, opts ...RequestOpt) (guildTemplate *discord.GuildTemplate, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.DeleteGuildTemplate.Compile(nil, guildID, templateCode) if err != nil { diff --git a/rest/guilds.go b/rest/guilds.go new file mode 100644 index 00000000..1dd9662b --- /dev/null +++ b/rest/guilds.go @@ -0,0 +1,287 @@ +package rest + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" +) + +var _ Guilds = (*guildImpl)(nil) + +func NewGuilds(restClient Client) Guilds { + return &guildImpl{restClient: restClient} +} + +type Guilds interface { + GetGuild(guildID snowflake.Snowflake, withCounts bool, opts ...RequestOpt) (*discord.Guild, error) + GetGuildPreview(guildID snowflake.Snowflake, opts ...RequestOpt) (*discord.GuildPreview, error) + CreateGuild(guildCreate discord.GuildCreate, opts ...RequestOpt) (*discord.Guild, error) + UpdateGuild(guildID snowflake.Snowflake, guildUpdate discord.GuildUpdate, opts ...RequestOpt) (*discord.Guild, error) + DeleteGuild(guildID snowflake.Snowflake, opts ...RequestOpt) error + + CreateGuildChannel(guildID snowflake.Snowflake, guildChannelCreate discord.GuildChannelCreate, opts ...RequestOpt) (discord.GuildChannel, error) + GetGuildChannels(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.GuildChannel, error) + UpdateChannelPositions(guildID snowflake.Snowflake, guildChannelPositionUpdates []discord.GuildChannelPositionUpdate, opts ...RequestOpt) error + + GetRoles(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Role, error) + GetRole(guildID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Role, error) + CreateRole(guildID snowflake.Snowflake, createRole discord.RoleCreate, opts ...RequestOpt) (*discord.Role, error) + UpdateRole(guildID snowflake.Snowflake, roleID snowflake.Snowflake, roleUpdate discord.RoleUpdate, opts ...RequestOpt) (*discord.Role, error) + UpdateRolePositions(guildID snowflake.Snowflake, rolePositionUpdates []discord.RolePositionUpdate, opts ...RequestOpt) ([]discord.Role, error) + DeleteRole(guildID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) error + + GetBans(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Ban, error) + GetBan(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) (*discord.Ban, error) + AddBan(guildID snowflake.Snowflake, userID snowflake.Snowflake, deleteMessageDays int, opts ...RequestOpt) error + DeleteBan(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) error + + GetIntegrations(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Integration, error) + DeleteIntegration(guildID snowflake.Snowflake, integrationID snowflake.Snowflake, opts ...RequestOpt) error + + GetWebhooks(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Webhook, error) + + GetAuditLog(guildID snowflake.Snowflake, userID snowflake.Snowflake, actionType discord.AuditLogEvent, before snowflake.Snowflake, limit int, opts ...RequestOpt) (*discord.AuditLog, error) +} + +type guildImpl struct { + restClient Client +} + +func (s *guildImpl) GetGuild(guildID snowflake.Snowflake, withCounts bool, opts ...RequestOpt) (guild *discord.Guild, err error) { + values := route.QueryValues{} + if withCounts { + values["withCounts"] = true + } + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetGuild.Compile(values, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &guild, opts...) + return +} + +func (s *guildImpl) GetGuildPreview(guildID snowflake.Snowflake, opts ...RequestOpt) (guildPreview *discord.GuildPreview, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetGuildPreview.Compile(nil, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &guildPreview, opts...) + return +} + +func (s *guildImpl) CreateGuild(guildCreate discord.GuildCreate, opts ...RequestOpt) (guild *discord.Guild, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.CreateGuild.Compile(nil) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, guildCreate, &guild, opts...) + return +} + +func (s *guildImpl) UpdateGuild(guildID snowflake.Snowflake, guildUpdate discord.GuildUpdate, opts ...RequestOpt) (guild *discord.Guild, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.UpdateGuild.Compile(nil, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, guildUpdate, &guild, opts...) + return +} + +func (s *guildImpl) DeleteGuild(guildID snowflake.Snowflake, opts ...RequestOpt) error { + compiledRoute, err := route.DeleteGuild.Compile(nil, guildID) + if err != nil { + return err + } + return s.restClient.Do(compiledRoute, nil, nil, opts...) +} + +func (s *guildImpl) CreateGuildChannel(guildID snowflake.Snowflake, guildChannelCreate discord.GuildChannelCreate, opts ...RequestOpt) (guildChannel discord.GuildChannel, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.CreateGuildChannel.Compile(nil, guildID) + if err != nil { + return + } + var ch discord.UnmarshalChannel + err = s.restClient.Do(compiledRoute, guildChannelCreate, &ch, opts...) + if err == nil { + guildChannel = ch.Channel.(discord.GuildChannel) + } + return +} + +func (s *guildImpl) GetGuildChannels(guildID snowflake.Snowflake, opts ...RequestOpt) (channels []discord.GuildChannel, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetGuildChannels.Compile(nil, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &channels, opts...) + return +} + +func (s *guildImpl) UpdateChannelPositions(guildID snowflake.Snowflake, guildChannelPositionUpdates []discord.GuildChannelPositionUpdate, opts ...RequestOpt) error { + compiledRoute, err := route.UpdateChannelPositions.Compile(nil, guildID) + if err != nil { + return err + } + return s.restClient.Do(compiledRoute, guildChannelPositionUpdates, nil, opts...) +} + +func (s *guildImpl) GetRoles(guildID snowflake.Snowflake, opts ...RequestOpt) (roles []discord.Role, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetRoles.Compile(nil, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &roles, opts...) + return +} + +func (s *guildImpl) GetRole(guildID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) (role []discord.Role, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetRole.Compile(nil, guildID, roleID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &role, opts...) + return +} + +func (s *guildImpl) CreateRole(guildID snowflake.Snowflake, createRole discord.RoleCreate, opts ...RequestOpt) (role *discord.Role, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.CreateRole.Compile(nil, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, createRole, &role, opts...) + return +} + +func (s *guildImpl) UpdateRole(guildID snowflake.Snowflake, roleID snowflake.Snowflake, roleUpdate discord.RoleUpdate, opts ...RequestOpt) (role *discord.Role, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.UpdateRole.Compile(nil, guildID, roleID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, roleUpdate, &role, opts...) + return +} + +func (s *guildImpl) UpdateRolePositions(guildID snowflake.Snowflake, rolePositionUpdates []discord.RolePositionUpdate, opts ...RequestOpt) (roles []discord.Role, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.UpdateRolePositions.Compile(nil, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, rolePositionUpdates, &roles, opts...) + return +} + +func (s *guildImpl) DeleteRole(guildID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) error { + compiledRoute, err := route.DeleteRole.Compile(nil, guildID, roleID) + if err != nil { + return err + } + return s.restClient.Do(compiledRoute, nil, nil, opts...) +} + +func (s *guildImpl) GetBans(guildID snowflake.Snowflake, opts ...RequestOpt) (bans []discord.Ban, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetBans.Compile(nil, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &bans, opts...) + return +} + +func (s *guildImpl) GetBan(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) (ban *discord.Ban, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetBan.Compile(nil, guildID, userID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &ban, opts...) + return +} + +func (s *guildImpl) AddBan(guildID snowflake.Snowflake, userID snowflake.Snowflake, deleteMessageDays int, opts ...RequestOpt) error { + compiledRoute, err := route.AddBan.Compile(nil, guildID, userID) + if err != nil { + return err + } + return s.restClient.Do(compiledRoute, discord.AddBan{DeleteMessageDays: deleteMessageDays}, nil, opts...) +} + +func (s *guildImpl) DeleteBan(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) error { + compiledRoute, err := route.DeleteBan.Compile(nil, guildID, userID) + if err != nil { + return err + } + return s.restClient.Do(compiledRoute, nil, nil, opts...) +} + +func (s *guildImpl) GetIntegrations(guildID snowflake.Snowflake, opts ...RequestOpt) (integrations []discord.Integration, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetIntegrations.Compile(nil, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &integrations, opts...) + return +} + +func (s *guildImpl) DeleteIntegration(guildID snowflake.Snowflake, integrationID snowflake.Snowflake, opts ...RequestOpt) error { + compiledRoute, err := route.DeleteIntegration.Compile(nil, guildID, integrationID) + if err != nil { + return err + } + return s.restClient.Do(compiledRoute, nil, nil, opts...) +} + +func (s *guildImpl) GetWebhooks(guildID snowflake.Snowflake, opts ...RequestOpt) (webhooks []discord.Webhook, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetGuildWebhooks.Compile(nil, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &webhooks, opts...) + return +} + +func (s *guildImpl) GetEmojis(guildID snowflake.Snowflake, opts ...RequestOpt) (emojis []discord.Emoji, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetEmojis.Compile(nil, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &emojis, opts...) + return +} + +func (s *guildImpl) GetAuditLog(guildID snowflake.Snowflake, userID snowflake.Snowflake, actionType discord.AuditLogEvent, before snowflake.Snowflake, limit int, opts ...RequestOpt) (auditLog *discord.AuditLog, err error) { + values := route.QueryValues{} + if userID != "" { + values["user_id"] = userID + } + if actionType != 0 { + values["action_type"] = actionType + } + if before != "" { + values["before"] = guildID + } + if limit != 0 { + values["limit"] = limit + } + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetAuditLogs.Compile(values, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &auditLog, opts...) + return +} diff --git a/rest/interaction_service.go b/rest/interactions.go similarity index 60% rename from rest/interaction_service.go rename to rest/interactions.go index 491d1dc5..2919bc22 100644 --- a/rest/interaction_service.go +++ b/rest/interactions.go @@ -1,23 +1,19 @@ package rest import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) -var ( - _ Service = (*interactionServiceImpl)(nil) - _ InteractionService = (*interactionServiceImpl)(nil) -) +var _ Interactions = (*interactionImpl)(nil) -func NewInteractionService(restClient Client) InteractionService { - return &interactionServiceImpl{restClient: restClient} +func NewInteractions(restClient Client) Interactions { + return &interactionImpl{restClient: restClient} } -type InteractionService interface { - Service - GetInteractionResponse(interactionID snowflake.Snowflake, interactionToken string, opts ...RequestOpt) (*discord.Message, error) +type Interactions interface { + GetInteractionResponse(applicationID snowflake.Snowflake, interactionToken string, opts ...RequestOpt) (*discord.Message, error) CreateInteractionResponse(interactionID snowflake.Snowflake, interactionToken string, interactionResponse discord.InteractionResponse, opts ...RequestOpt) error UpdateInteractionResponse(applicationID snowflake.Snowflake, interactionToken string, messageUpdate discord.MessageUpdate, opts ...RequestOpt) (*discord.Message, error) DeleteInteractionResponse(applicationID snowflake.Snowflake, interactionToken string, opts ...RequestOpt) error @@ -28,15 +24,11 @@ type InteractionService interface { DeleteFollowupMessage(applicationID snowflake.Snowflake, interactionToken string, messageID snowflake.Snowflake, opts ...RequestOpt) error } -type interactionServiceImpl struct { +type interactionImpl struct { restClient Client } -func (s *interactionServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *interactionServiceImpl) GetInteractionResponse(interactionID snowflake.Snowflake, interactionToken string, opts ...RequestOpt) (message *discord.Message, err error) { +func (s *interactionImpl) GetInteractionResponse(interactionID snowflake.Snowflake, interactionToken string, opts ...RequestOpt) (message *discord.Message, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetInteractionResponse.Compile(nil, interactionID, interactionToken) if err != nil { @@ -46,7 +38,7 @@ func (s *interactionServiceImpl) GetInteractionResponse(interactionID snowflake. return } -func (s *interactionServiceImpl) CreateInteractionResponse(interactionID snowflake.Snowflake, interactionToken string, interactionResponse discord.InteractionResponse, opts ...RequestOpt) error { +func (s *interactionImpl) CreateInteractionResponse(interactionID snowflake.Snowflake, interactionToken string, interactionResponse discord.InteractionResponse, opts ...RequestOpt) error { compiledRoute, err := route.CreateInteractionResponse.Compile(nil, interactionID, interactionToken) if err != nil { return err @@ -60,7 +52,7 @@ func (s *interactionServiceImpl) CreateInteractionResponse(interactionID snowfla return s.restClient.Do(compiledRoute, body, nil, opts...) } -func (s *interactionServiceImpl) UpdateInteractionResponse(applicationID snowflake.Snowflake, interactionToken string, messageUpdate discord.MessageUpdate, opts ...RequestOpt) (message *discord.Message, err error) { +func (s *interactionImpl) UpdateInteractionResponse(applicationID snowflake.Snowflake, interactionToken string, messageUpdate discord.MessageUpdate, opts ...RequestOpt) (message *discord.Message, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateInteractionResponse.Compile(nil, applicationID, interactionToken) if err != nil { @@ -76,7 +68,7 @@ func (s *interactionServiceImpl) UpdateInteractionResponse(applicationID snowfla return } -func (s *interactionServiceImpl) DeleteInteractionResponse(applicationID snowflake.Snowflake, interactionToken string, opts ...RequestOpt) error { +func (s *interactionImpl) DeleteInteractionResponse(applicationID snowflake.Snowflake, interactionToken string, opts ...RequestOpt) error { compiledRoute, err := route.DeleteInteractionResponse.Compile(nil, applicationID, interactionToken) if err != nil { return err @@ -84,7 +76,7 @@ func (s *interactionServiceImpl) DeleteInteractionResponse(applicationID snowfla return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *interactionServiceImpl) GetFollowupMessage(applicationID snowflake.Snowflake, interactionToken string, messageID snowflake.Snowflake, opts ...RequestOpt) (message *discord.Message, err error) { +func (s *interactionImpl) GetFollowupMessage(applicationID snowflake.Snowflake, interactionToken string, messageID snowflake.Snowflake, opts ...RequestOpt) (message *discord.Message, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetFollowupMessage.Compile(nil, applicationID, interactionToken, messageID) if err != nil { @@ -95,7 +87,7 @@ func (s *interactionServiceImpl) GetFollowupMessage(applicationID snowflake.Snow return } -func (s *interactionServiceImpl) CreateFollowupMessage(applicationID snowflake.Snowflake, interactionToken string, messageCreate discord.MessageCreate, opts ...RequestOpt) (message *discord.Message, err error) { +func (s *interactionImpl) CreateFollowupMessage(applicationID snowflake.Snowflake, interactionToken string, messageCreate discord.MessageCreate, opts ...RequestOpt) (message *discord.Message, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateFollowupMessage.Compile(nil, applicationID, interactionToken) if err != nil { @@ -111,7 +103,7 @@ func (s *interactionServiceImpl) CreateFollowupMessage(applicationID snowflake.S return } -func (s *interactionServiceImpl) UpdateFollowupMessage(applicationID snowflake.Snowflake, interactionToken string, messageID snowflake.Snowflake, messageUpdate discord.MessageUpdate, opts ...RequestOpt) (message *discord.Message, err error) { +func (s *interactionImpl) UpdateFollowupMessage(applicationID snowflake.Snowflake, interactionToken string, messageID snowflake.Snowflake, messageUpdate discord.MessageUpdate, opts ...RequestOpt) (message *discord.Message, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateFollowupMessage.Compile(nil, applicationID, interactionToken, messageID) if err != nil { @@ -127,7 +119,7 @@ func (s *interactionServiceImpl) UpdateFollowupMessage(applicationID snowflake.S return } -func (s *interactionServiceImpl) DeleteFollowupMessage(applicationID snowflake.Snowflake, interactionToken string, messageID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *interactionImpl) DeleteFollowupMessage(applicationID snowflake.Snowflake, interactionToken string, messageID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.DeleteFollowupMessage.Compile(nil, applicationID, interactionToken, messageID) if err != nil { return err diff --git a/rest/invite_service.go b/rest/invites.go similarity index 58% rename from rest/invite_service.go rename to rest/invites.go index 2839e083..c198f6e4 100644 --- a/rest/invite_service.go +++ b/rest/invites.go @@ -1,22 +1,18 @@ package rest import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) -var ( - _ Service = (*inviteServiceImpl)(nil) - _ InviteService = (*inviteServiceImpl)(nil) -) +var _ Invites = (*inviteImpl)(nil) -func NewInviteService(restClient Client) InviteService { - return &inviteServiceImpl{restClient: restClient} +func NewInvites(restClient Client) Invites { + return &inviteImpl{restClient: restClient} } -type InviteService interface { - Service +type Invites interface { GetInvite(code string, opts ...RequestOpt) (*discord.Invite, error) CreateInvite(channelID snowflake.Snowflake, inviteCreate discord.InviteCreate, opts ...RequestOpt) (*discord.Invite, error) DeleteInvite(code string, opts ...RequestOpt) (*discord.Invite, error) @@ -24,15 +20,11 @@ type InviteService interface { GetChannelInvites(channelID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Invite, error) } -type inviteServiceImpl struct { +type inviteImpl struct { restClient Client } -func (s *inviteServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *inviteServiceImpl) GetInvite(code string, opts ...RequestOpt) (invite *discord.Invite, err error) { +func (s *inviteImpl) GetInvite(code string, opts ...RequestOpt) (invite *discord.Invite, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetInvite.Compile(nil, code) if err != nil { @@ -42,7 +34,7 @@ func (s *inviteServiceImpl) GetInvite(code string, opts ...RequestOpt) (invite * return } -func (s *inviteServiceImpl) CreateInvite(channelID snowflake.Snowflake, inviteCreate discord.InviteCreate, opts ...RequestOpt) (invite *discord.Invite, err error) { +func (s *inviteImpl) CreateInvite(channelID snowflake.Snowflake, inviteCreate discord.InviteCreate, opts ...RequestOpt) (invite *discord.Invite, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateInvite.Compile(nil, channelID) if err != nil { @@ -52,7 +44,7 @@ func (s *inviteServiceImpl) CreateInvite(channelID snowflake.Snowflake, inviteCr return } -func (s *inviteServiceImpl) DeleteInvite(code string, opts ...RequestOpt) (invite *discord.Invite, err error) { +func (s *inviteImpl) DeleteInvite(code string, opts ...RequestOpt) (invite *discord.Invite, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.DeleteInvite.Compile(nil, code) if err != nil { @@ -62,7 +54,7 @@ func (s *inviteServiceImpl) DeleteInvite(code string, opts ...RequestOpt) (invit return } -func (s *inviteServiceImpl) GetGuildInvites(guildID snowflake.Snowflake, opts ...RequestOpt) (invites []discord.Invite, err error) { +func (s *inviteImpl) GetGuildInvites(guildID snowflake.Snowflake, opts ...RequestOpt) (invites []discord.Invite, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetGuildInvites.Compile(nil, guildID) if err != nil { @@ -72,7 +64,7 @@ func (s *inviteServiceImpl) GetGuildInvites(guildID snowflake.Snowflake, opts .. return } -func (s *inviteServiceImpl) GetChannelInvites(channelID snowflake.Snowflake, opts ...RequestOpt) (invites []discord.Invite, err error) { +func (s *inviteImpl) GetChannelInvites(channelID snowflake.Snowflake, opts ...RequestOpt) (invites []discord.Invite, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetChannelInvites.Compile(nil, channelID) if err != nil { diff --git a/rest/members.go b/rest/members.go new file mode 100644 index 00000000..558b1775 --- /dev/null +++ b/rest/members.go @@ -0,0 +1,141 @@ +package rest + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" +) + +var _ Members = (*memberImpl)(nil) + +func NewMembers(restClient Client) Members { + return &memberImpl{restClient: restClient} +} + +type Members interface { + GetMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) (*discord.Member, error) + GetMembers(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Member, error) + SearchMembers(guildID snowflake.Snowflake, query string, limit int, opts ...RequestOpt) ([]discord.Member, error) + AddMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, memberAdd discord.MemberAdd, opts ...RequestOpt) (*discord.Member, error) + RemoveMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) error + UpdateMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, memberUpdate discord.MemberUpdate, opts ...RequestOpt) (*discord.Member, error) + + AddMemberRole(guildID snowflake.Snowflake, userID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) error + RemoveMemberRole(guildID snowflake.Snowflake, userID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) error + + UpdateSelfNick(guildID snowflake.Snowflake, nick string, opts ...RequestOpt) (*string, error) + + UpdateCurrentUserVoiceState(guildID snowflake.Snowflake, currentUserVoiceStateUpdate discord.UserVoiceStateUpdate, opts ...RequestOpt) error + UpdateUserVoiceState(guildID snowflake.Snowflake, userID snowflake.Snowflake, userVoiceStateUpdate discord.UserVoiceStateUpdate, opts ...RequestOpt) error +} + +type memberImpl struct { + restClient Client +} + +func (s *memberImpl) GetMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) (member *discord.Member, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetMember.Compile(nil, guildID, userID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &member, opts...) + return +} + +func (s *memberImpl) GetMembers(guildID snowflake.Snowflake, opts ...RequestOpt) (members []discord.Member, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetMembers.Compile(nil, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &members, opts...) + return +} + +func (s *memberImpl) SearchMembers(guildID snowflake.Snowflake, query string, limit int, opts ...RequestOpt) (members []discord.Member, err error) { + values := route.QueryValues{} + if query != "" { + values["query"] = query + } + if limit != 0 { + values["limit"] = limit + } + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.SearchMembers.Compile(values, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, &members, opts...) + return +} + +func (s *memberImpl) AddMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, memberAdd discord.MemberAdd, opts ...RequestOpt) (member *discord.Member, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.AddMember.Compile(nil, guildID, userID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, memberAdd, &member, opts...) + return +} + +func (s *memberImpl) RemoveMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) error { + compiledRoute, err := route.RemoveMember.Compile(nil, guildID, userID) + if err != nil { + return err + } + return s.restClient.Do(compiledRoute, nil, nil, opts...) +} + +func (s *memberImpl) UpdateMember(guildID snowflake.Snowflake, userID snowflake.Snowflake, memberUpdate discord.MemberUpdate, opts ...RequestOpt) (member *discord.Member, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.UpdateMember.Compile(nil, guildID, userID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, memberUpdate, &member, opts...) + return +} + +func (s *memberImpl) AddMemberRole(guildID snowflake.Snowflake, userID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) error { + compiledRoute, err := route.AddMemberRole.Compile(nil, guildID, userID, roleID) + if err != nil { + return err + } + return s.restClient.Do(compiledRoute, nil, nil, opts...) +} + +func (s *memberImpl) RemoveMemberRole(guildID snowflake.Snowflake, userID snowflake.Snowflake, roleID snowflake.Snowflake, opts ...RequestOpt) error { + compiledRoute, err := route.RemoveMemberRole.Compile(nil, guildID, userID, roleID) + if err != nil { + return err + } + return s.restClient.Do(compiledRoute, nil, nil, opts...) +} + +func (s *memberImpl) UpdateSelfNick(guildID snowflake.Snowflake, nick string, opts ...RequestOpt) (nickName *string, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.UpdateSelfNick.Compile(nil, guildID) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, discord.SelfNickUpdate{Nick: nick}, nickName, opts...) + return +} + +func (s *memberImpl) UpdateCurrentUserVoiceState(guildID snowflake.Snowflake, currentUserVoiceStateUpdate discord.UserVoiceStateUpdate, opts ...RequestOpt) error { + compiledRoute, err := route.UpdateCurrentUserVoiceState.Compile(nil, guildID) + if err != nil { + return err + } + return s.restClient.Do(compiledRoute, currentUserVoiceStateUpdate, nil, opts...) +} + +func (s *memberImpl) UpdateUserVoiceState(guildID snowflake.Snowflake, userID snowflake.Snowflake, userVoiceStateUpdate discord.UserVoiceStateUpdate, opts ...RequestOpt) error { + compiledRoute, err := route.UpdateUserVoiceState.Compile(nil, guildID, userID) + if err != nil { + return err + } + return s.restClient.Do(compiledRoute, userVoiceStateUpdate, nil, opts...) +} diff --git a/rest/oauth2_service.go b/rest/oauth2.go similarity index 53% rename from rest/oauth2_service.go rename to rest/oauth2.go index bb786419..55fe1428 100644 --- a/rest/oauth2_service.go +++ b/rest/oauth2.go @@ -3,22 +3,18 @@ package rest import ( "net/url" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) -var ( - _ Service = (*oAuth2ServiceImpl)(nil) - _ OAuth2Service = (*oAuth2ServiceImpl)(nil) -) +var _ OAuth2 = (*oAuth2Impl)(nil) -func NewOAuth2Service(restClient Client) OAuth2Service { - return &oAuth2ServiceImpl{restClient: restClient} +func NewOAuth2(restClient Client) OAuth2 { + return &oAuth2Impl{restClient: restClient} } -type OAuth2Service interface { - Service +type OAuth2 interface { GetBotApplicationInfo(opts ...RequestOpt) (*discord.Application, error) GetCurrentAuthorizationInfo(bearerToken string, opts ...RequestOpt) (*discord.AuthorizationInformation, error) @@ -30,22 +26,18 @@ type OAuth2Service interface { RefreshAccessToken(clientID snowflake.Snowflake, clientSecret string, refreshToken string, opts ...RequestOpt) (*discord.AccessTokenExchange, error) } -type oAuth2ServiceImpl struct { +type oAuth2Impl struct { restClient Client } -func (s *oAuth2ServiceImpl) botOrBearerToken(bearerToken string, opts []RequestOpt) []RequestOpt { - if bearerToken == "" { - return applyBotToken(s.RestClient().Config().BotTokenFunc(), opts) +func withBearerToken(bearerToken string, opts []RequestOpt) []RequestOpt { + if bearerToken != "" { + return append(opts, WithToken(discord.TokenTypeBearer, bearerToken)) } - return applyBearerToken(bearerToken, opts) -} - -func (s *oAuth2ServiceImpl) RestClient() Client { - return s.restClient + return opts } -func (s *oAuth2ServiceImpl) GetBotApplicationInfo(opts ...RequestOpt) (application *discord.Application, err error) { +func (s *oAuth2Impl) GetBotApplicationInfo(opts ...RequestOpt) (application *discord.Application, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetBotApplicationInfo.Compile(nil) if err != nil { @@ -55,28 +47,28 @@ func (s *oAuth2ServiceImpl) GetBotApplicationInfo(opts ...RequestOpt) (applicati return } -func (s *oAuth2ServiceImpl) GetCurrentAuthorizationInfo(bearerToken string, opts ...RequestOpt) (info *discord.AuthorizationInformation, err error) { +func (s *oAuth2Impl) GetCurrentAuthorizationInfo(bearerToken string, opts ...RequestOpt) (info *discord.AuthorizationInformation, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetAuthorizationInfo.Compile(nil) if err != nil { return } - err = s.restClient.Do(compiledRoute, nil, &info, applyBearerToken(bearerToken, opts)...) + err = s.restClient.Do(compiledRoute, nil, &info, withBearerToken(bearerToken, opts)...) return } -func (s *oAuth2ServiceImpl) GetCurrentUser(bearerToken string, opts ...RequestOpt) (user *discord.OAuth2User, err error) { +func (s *oAuth2Impl) GetCurrentUser(bearerToken string, opts ...RequestOpt) (user *discord.OAuth2User, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetCurrentUser.Compile(nil) if err != nil { return } - err = s.restClient.Do(compiledRoute, nil, &user, s.botOrBearerToken(bearerToken, opts)...) + err = s.restClient.Do(compiledRoute, nil, &user, withBearerToken(bearerToken, opts)...) return } -func (s *oAuth2ServiceImpl) GetCurrentUserGuilds(bearerToken string, before snowflake.Snowflake, after snowflake.Snowflake, limit int, opts ...RequestOpt) (guilds []discord.OAuth2Guild, err error) { +func (s *oAuth2Impl) GetCurrentUserGuilds(bearerToken string, before snowflake.Snowflake, after snowflake.Snowflake, limit int, opts ...RequestOpt) (guilds []discord.OAuth2Guild, err error) { queryParams := route.QueryValues{} if before != "" { queryParams["before"] = before @@ -94,22 +86,22 @@ func (s *oAuth2ServiceImpl) GetCurrentUserGuilds(bearerToken string, before snow return } - err = s.restClient.Do(compiledRoute, nil, &guilds, s.botOrBearerToken(bearerToken, opts)...) + err = s.restClient.Do(compiledRoute, nil, &guilds, withBearerToken(bearerToken, opts)...) return } -func (s *oAuth2ServiceImpl) GetCurrentUserConnections(bearerToken string, opts ...RequestOpt) (connections []discord.Connection, err error) { +func (s *oAuth2Impl) GetCurrentUserConnections(bearerToken string, opts ...RequestOpt) (connections []discord.Connection, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetCurrentUserConnections.Compile(nil) if err != nil { return } - err = s.restClient.Do(compiledRoute, nil, &connections, s.botOrBearerToken(bearerToken, opts)...) + err = s.restClient.Do(compiledRoute, nil, &connections, withBearerToken(bearerToken, opts)...) return } -func (s *oAuth2ServiceImpl) exchangeAccessToken(clientID snowflake.Snowflake, clientSecret string, grantType discord.GrantType, codeOrRefreshToken string, redirectURI string, opts ...RequestOpt) (exchange *discord.AccessTokenExchange, err error) { +func (s *oAuth2Impl) exchangeAccessToken(clientID snowflake.Snowflake, clientSecret string, grantType discord.GrantType, codeOrRefreshToken string, redirectURI string, opts ...RequestOpt) (exchange *discord.AccessTokenExchange, err error) { values := url.Values{ "client_id": []string{clientID.String()}, "client_secret": []string{clientSecret}, @@ -133,10 +125,10 @@ func (s *oAuth2ServiceImpl) exchangeAccessToken(clientID snowflake.Snowflake, cl return } -func (s *oAuth2ServiceImpl) GetAccessToken(clientID snowflake.Snowflake, clientSecret string, code string, redirectURI string, opts ...RequestOpt) (exchange *discord.AccessTokenExchange, err error) { +func (s *oAuth2Impl) GetAccessToken(clientID snowflake.Snowflake, clientSecret string, code string, redirectURI string, opts ...RequestOpt) (exchange *discord.AccessTokenExchange, err error) { return s.exchangeAccessToken(clientID, clientSecret, discord.GrantTypeAuthorizationCode, code, redirectURI, opts...) } -func (s *oAuth2ServiceImpl) RefreshAccessToken(clientID snowflake.Snowflake, clientSecret string, refreshToken string, opts ...RequestOpt) (exchange *discord.AccessTokenExchange, err error) { +func (s *oAuth2Impl) RefreshAccessToken(clientID snowflake.Snowflake, clientSecret string, refreshToken string, opts ...RequestOpt) (exchange *discord.AccessTokenExchange, err error) { return s.exchangeAccessToken(clientID, clientSecret, discord.GrantTypeRefreshToken, refreshToken, "", opts...) } diff --git a/rest/request_opt.go b/rest/request_config.go similarity index 64% rename from rest/request_opt.go rename to rest/request_config.go index 7f81dade..8219046d 100644 --- a/rest/request_opt.go +++ b/rest/request_config.go @@ -5,14 +5,27 @@ import ( "fmt" "net/http" "time" + + "github.com/disgoorg/disgo/discord" ) +func DefaultRequestConfig(rq *http.Request, tokenType discord.TokenType, token string) *RequestConfig { + return &RequestConfig{ + Request: rq, + Ctx: context.TODO(), + TokenType: tokenType, + Token: token, + } +} + // RequestConfig are additional options for the request type RequestConfig struct { - Request *http.Request - Ctx context.Context - Checks []Check - Delay time.Duration + Request *http.Request + Ctx context.Context + Checks []Check + Delay time.Duration + TokenType discord.TokenType + Token string } // Check is a function which gets executed right before a request is made @@ -23,6 +36,9 @@ type RequestOpt func(config *RequestConfig) // Apply applies the given RequestOpt(s) to the RequestConfig & sets the context if none is set func (c *RequestConfig) Apply(opts []RequestOpt) { + if c.TokenType != "" && c.Token != "" { + c.Request.Header.Set("Authorization", c.TokenType.Apply(c.Token)) + } for _, opt := range opts { opt(c) } @@ -32,7 +48,6 @@ func (c *RequestConfig) Apply(opts []RequestOpt) { } // WithCtx applies a custom context to the request -//goland:noinspection GoUnusedExportedFunction func WithCtx(ctx context.Context) RequestOpt { return func(config *RequestConfig) { config.Ctx = ctx @@ -40,7 +55,6 @@ func WithCtx(ctx context.Context) RequestOpt { } // WithCheck adds a new check to the request -//goland:noinspection GoUnusedExportedFunction func WithCheck(check Check) RequestOpt { return func(config *RequestConfig) { config.Checks = append(config.Checks, check) @@ -48,7 +62,6 @@ func WithCheck(check Check) RequestOpt { } // WithDelay applies a delay to the request -//goland:noinspection GoUnusedExportedFunction func WithDelay(delay time.Duration) RequestOpt { return func(config *RequestConfig) { config.Delay = delay @@ -56,7 +69,6 @@ func WithDelay(delay time.Duration) RequestOpt { } // WithReason adds a reason header to the request. Not all discord endpoints support this -//goland:noinspection GoUnusedExportedFunction func WithReason(reason string) RequestOpt { return func(config *RequestConfig) { config.Request.Header.Set("X-Audit-Log-Reason", reason) @@ -64,19 +76,29 @@ func WithReason(reason string) RequestOpt { } // WithHeader adds a custom header to the request -//goland:noinspection GoUnusedExportedFunction func WithHeader(key string, value string) RequestOpt { return func(config *RequestConfig) { config.Request.Header.Set(key, value) } } +// WithDiscordLocale adds the X-Discord-Locale header with the passed locale to the request +func WithDiscordLocale(locale discord.Locale) RequestOpt { + return WithHeader("X-Discord-Locale", locale.Code()) +} + // WithQueryParam applies a custom query parameter to the request -//goland:noinspection GoUnusedExportedFunction -func WithQueryParam(param string, value interface{}) RequestOpt { +func WithQueryParam(param string, value any) RequestOpt { return func(config *RequestConfig) { values := config.Request.URL.Query() values.Add(param, fmt.Sprint(value)) config.Request.URL.RawQuery = values.Encode() } } + +func WithToken(tokenType discord.TokenType, token string) RequestOpt { + return func(config *RequestConfig) { + config.TokenType = tokenType + config.Token = token + } +} diff --git a/rest/rest.go b/rest/rest.go new file mode 100644 index 00000000..185f8767 --- /dev/null +++ b/rest/rest.go @@ -0,0 +1,153 @@ +package rest + +import ( + "context" +) + +var _ Rest = (*servicesImpl)(nil) + +// NewRest returns a new default Rest +func NewRest(restClient Client) Rest { + return &servicesImpl{ + restClient: restClient, + applications: NewApplications(restClient), + oauth2: NewOAuth2(restClient), + gateway: NewGateway(restClient), + guilds: NewGuilds(restClient), + members: NewMembers(restClient), + channels: NewChannels(restClient), + threads: NewThreads(restClient), + interactions: NewInteractions(restClient), + invites: NewInvites(restClient), + guildTemplates: NewGuildTemplates(restClient), + users: NewUsers(restClient), + voice: NewVoice(restClient), + webhooks: NewWebhooks(restClient), + stageInstances: NewStageInstances(restClient), + emojis: NewEmojis(restClient), + stickers: NewStickers(restClient), + guildScheduledEvents: NewGuildScheduledEvents(restClient), + } +} + +// Rest is a manager for all of disgo's HTTP requests +type Rest interface { + RestClient() Client + Close(ctx context.Context) + + Applications() Applications + OAuth2() OAuth2 + Gateway() Gateway + Guilds() Guilds + Members() Members + Channels() Channels + Threads() Threads + Interactions() Interactions + Invites() Invites + GuildTemplates() GuildTemplates + Users() Users + Voice() Voice + Webhooks() Webhooks + StageInstances() StageInstances + Emojis() Emojis + Stickers() Stickers + GuildScheduledEvents() GuildScheduledEvents +} + +type servicesImpl struct { + restClient Client + + applications Applications + oauth2 OAuth2 + gateway Gateway + guilds Guilds + members Members + channels Channels + threads Threads + interactions Interactions + invites Invites + guildTemplates GuildTemplates + users Users + voice Voice + webhooks Webhooks + stageInstances StageInstances + emojis Emojis + stickers Stickers + guildScheduledEvents GuildScheduledEvents +} + +func (s *servicesImpl) RestClient() Client { + return s.restClient +} + +func (s *servicesImpl) Close(ctx context.Context) { + s.restClient.Close(ctx) +} + +func (s *servicesImpl) Applications() Applications { + return s.applications +} + +func (s *servicesImpl) OAuth2() OAuth2 { + return s.oauth2 +} + +func (s *servicesImpl) Gateway() Gateway { + return s.gateway +} + +func (s *servicesImpl) Guilds() Guilds { + return s.guilds +} + +func (s *servicesImpl) Members() Members { + return s.members +} + +func (s *servicesImpl) Channels() Channels { + return s.channels +} + +func (s *servicesImpl) Threads() Threads { + return s.threads +} + +func (s *servicesImpl) Interactions() Interactions { + return s.interactions +} + +func (s *servicesImpl) Invites() Invites { + return s.invites +} + +func (s *servicesImpl) GuildTemplates() GuildTemplates { + return s.guildTemplates +} + +func (s *servicesImpl) Users() Users { + return s.users +} + +func (s *servicesImpl) Voice() Voice { + return s.voice +} + +func (s *servicesImpl) Webhooks() Webhooks { + return s.webhooks +} + +func (s *servicesImpl) StageInstances() StageInstances { + return s.stageInstances +} + +func (s *servicesImpl) Emojis() Emojis { + return s.emojis +} + +func (s *servicesImpl) Stickers() Stickers { + return s.stickers +} + +func (s *servicesImpl) GuildScheduledEvents() GuildScheduledEvents { + return s.guildScheduledEvents +} diff --git a/rest/rest_client.go b/rest/rest_client.go index 6f327b5b..765ed2ab 100644 --- a/rest/rest_client.go +++ b/rest/rest_client.go @@ -3,42 +3,26 @@ package rest import ( "bytes" "context" + "fmt" "io/ioutil" "net/http" "net/url" "time" - "github.com/DisgoOrg/disgo/json" - "github.com/pkg/errors" + "github.com/disgoorg/disgo/json" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/disgo/rest/rrate" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/disgo/rest/rrate" + "github.com/disgoorg/log" ) // NewClient constructs a new Client with the given Config struct -//goland:noinspection GoUnusedExportedFunction -func NewClient(config *Config) Client { - if config == nil { - config = &DefaultConfig - } - if config.Logger == nil { - config.Logger = log.Default() - } - if config.HTTPClient == nil { - config.HTTPClient = http.DefaultClient - } - if config.RateLimiterConfig == nil { - config.RateLimiterConfig = &rrate.DefaultConfig - } - if config.RateLimiterConfig.Logger == nil { - config.RateLimiterConfig.Logger = config.Logger - } - if config.RateLimiter == nil { - config.RateLimiter = rrate.NewLimiter(config.RateLimiterConfig) - } - return &clientImpl{config: *config} +func NewClient(botToken string, opts ...ConfigOpt) Client { + config := DefaultConfig() + config.Apply(opts) + + return &clientImpl{botToken: botToken, config: *config} } // Client allows doing requests to different endpoints @@ -51,18 +35,17 @@ type Client interface { // RateLimiter returns the rrate.Limiter the rest client uses RateLimiter() rrate.Limiter - // Config returns the Config the rest client uses - Config() Config // Close closes the rest client and awaits all pending requests to finish. You can use a cancelling context to abort the waiting Close(ctx context.Context) - // Do makes a request to the given route.CompiledAPIRoute and marshals the given interface{} as json and unmarshalls the response into the given interface - Do(route *route.CompiledAPIRoute, rqBody interface{}, rsBody interface{}, opts ...RequestOpt) error + // Do makes a request to the given route.CompiledAPIRoute and marshals the given any as json and unmarshalls the response into the given interface + Do(route *route.CompiledAPIRoute, rqBody any, rsBody any, opts ...RequestOpt) error } type clientImpl struct { - config Config + botToken string + config Config } func (c *clientImpl) Close(ctx context.Context) { @@ -82,11 +65,7 @@ func (c *clientImpl) RateLimiter() rrate.Limiter { return c.config.RateLimiter } -func (c *clientImpl) Config() Config { - return c.config -} - -func (c *clientImpl) retry(cRoute *route.CompiledAPIRoute, rqBody interface{}, rsBody interface{}, tries int, opts []RequestOpt) error { +func (c *clientImpl) retry(cRoute *route.CompiledAPIRoute, rqBody any, rsBody any, tries int, opts []RequestOpt) error { rqURL := cRoute.URL() var rawRqBody []byte var err error @@ -105,7 +84,7 @@ func (c *clientImpl) retry(cRoute *route.CompiledAPIRoute, rqBody interface{}, r default: contentType = "application/json" if rawRqBody, err = json.Marshal(rqBody); err != nil { - return errors.Wrap(err, "failed to marshal request body") + return fmt.Errorf("failed to marshal request body: %w", err) } } c.Logger().Tracef("request to %s, body: %s", rqURL, string(rawRqBody)) @@ -116,30 +95,38 @@ func (c *clientImpl) retry(cRoute *route.CompiledAPIRoute, rqBody interface{}, r return err } - rq.Header.Set("User-Agent", c.Config().UserAgent) + rq.Header.Set("User-Agent", c.config.UserAgent) if contentType != "" { rq.Header.Set("Content-Type", contentType) } - if cRoute.APIRoute.NeedsAuth() { - opts = applyBotToken(c.Config().BotTokenFunc(), opts) + var ( + tokenType discord.TokenType + token string + ) + + if cRoute.APIRoute.NeedsBotAuth() { + tokenType = discord.TokenTypeBot + token = c.botToken } - config := &RequestConfig{Request: rq} + config := DefaultRequestConfig(rq, tokenType, token) config.Apply(opts) if config.Delay > 0 { + timer := time.NewTimer(config.Delay) + defer timer.Stop() select { case <-config.Ctx.Done(): return config.Ctx.Err() - case <-time.After(config.Delay): + case <-timer.C: } } // wait for rate limits err = c.RateLimiter().WaitBucket(config.Ctx, cRoute) if err != nil { - return errors.Wrap(err, "error locking bucket in rest client") + return fmt.Errorf("error locking bucket in rest client: %w", err) } rq = rq.WithContext(config.Ctx) @@ -152,18 +139,18 @@ func (c *clientImpl) retry(cRoute *route.CompiledAPIRoute, rqBody interface{}, r rs, err := c.HTTPClient().Do(config.Request) if err != nil { - return errors.Wrap(err, "error doing request in rest client") + return fmt.Errorf("error doing request in rest client: %w", err) } if err = c.RateLimiter().UnlockBucket(cRoute, rs.Header); err != nil { // TODO: should we maybe retry here? - return errors.Wrap(err, "error unlocking bucket in rest client") + return fmt.Errorf("error unlocking bucket in rest client: %w", err) } var rawRsBody []byte if rs.Body != nil { if rawRsBody, err = ioutil.ReadAll(rs.Body); err != nil { - return errors.Wrap(err, "error reading response body in rest client") + return fmt.Errorf("error reading response body in rest client: %w", err) } c.Logger().Tracef("response from %s, code %d, body: %s", rqURL, rs.StatusCode, string(rawRsBody)) } @@ -172,7 +159,7 @@ func (c *clientImpl) retry(cRoute *route.CompiledAPIRoute, rqBody interface{}, r case http.StatusOK, http.StatusCreated, http.StatusNoContent: if rsBody != nil && rs.Body != nil { if err = json.Unmarshal(rawRsBody, rsBody); err != nil { - wErr := errors.Wrap(err, "error unmarshalling response body") + wErr := fmt.Errorf("error unmarshalling response body: %w", err) c.Logger().Error(wErr) return NewErrorErr(rq, rawRqBody, rs, rawRsBody, wErr) } @@ -183,7 +170,7 @@ func (c *clientImpl) retry(cRoute *route.CompiledAPIRoute, rqBody interface{}, r return NewError(rq, rawRqBody, rs, rawRsBody) case http.StatusTooManyRequests: - if tries >= c.RateLimiter().Config().MaxRetries { + if tries >= c.RateLimiter().MaxRetries() { return NewError(rq, rawRqBody, rs, rawRsBody) } return c.retry(cRoute, rqBody, rsBody, tries+1, opts) @@ -191,24 +178,16 @@ func (c *clientImpl) retry(cRoute *route.CompiledAPIRoute, rqBody interface{}, r default: var v discord.APIError if err = json.Unmarshal(rawRsBody, &v); err != nil { - return errors.Wrap(err, "error unmarshalling error response body") + return fmt.Errorf("error unmarshalling error response body: %w", err) } return NewErrorAPIErr(rq, rawRqBody, rs, rawRsBody, v) } } -func (c *clientImpl) Do(cRoute *route.CompiledAPIRoute, rqBody interface{}, rsBody interface{}, opts ...RequestOpt) error { +func (c *clientImpl) Do(cRoute *route.CompiledAPIRoute, rqBody any, rsBody any, opts ...RequestOpt) error { return c.retry(cRoute, rqBody, rsBody, 1, opts) } -func applyToken(tokenType discord.TokenType, token string, opts []RequestOpt) []RequestOpt { +func applyAuthHeader(tokenType discord.TokenType, token string, opts []RequestOpt) []RequestOpt { return append(opts, WithHeader("authorization", tokenType.Apply(token))) } - -func applyBotToken(botToken string, opts []RequestOpt) []RequestOpt { - return applyToken(discord.TokenTypeBot, botToken, opts) -} - -func applyBearerToken(bearerToken string, opts []RequestOpt) []RequestOpt { - return applyToken(discord.TokenTypeBearer, bearerToken, opts) -} diff --git a/rest/rest_config.go b/rest/rest_config.go index 8b0e83d3..7b603b7e 100644 --- a/rest/rest_config.go +++ b/rest/rest_config.go @@ -1,30 +1,28 @@ package rest import ( - "fmt" "net/http" "time" - "github.com/DisgoOrg/disgo/info" - "github.com/DisgoOrg/disgo/rest/rrate" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/rest/rrate" + "github.com/disgoorg/log" ) // DefaultConfig is the configuration which is used by default -var DefaultConfig = Config{ - HTTPClient: &http.Client{Timeout: 20 * time.Second}, - RateLimiterConfig: &rrate.DefaultConfig, - UserAgent: fmt.Sprintf("DiscordBot (%s, %s)", info.GitHub, info.Version), +func DefaultConfig() *Config { + return &Config{ + Logger: log.Default(), + HTTPClient: &http.Client{Timeout: 20 * time.Second}, + } } // Config is the configuration for the rest client type Config struct { - Logger log.Logger - HTTPClient *http.Client - RateLimiter rrate.Limiter - RateLimiterConfig *rrate.Config - BotTokenFunc func() string - UserAgent string + Logger log.Logger + HTTPClient *http.Client + RateLimiter rrate.Limiter + RateLimiterConfigOpts []rrate.ConfigOpt + UserAgent string } // ConfigOpt can be used to supply optional parameters to NewClient @@ -35,10 +33,12 @@ func (c *Config) Apply(opts []ConfigOpt) { for _, opt := range opts { opt(c) } + if c.RateLimiter == nil { + c.RateLimiter = rrate.NewLimiter(c.RateLimiterConfigOpts...) + } } // WithLogger applies a custom logger to the rest rate limiter -//goland:noinspection GoUnusedExportedFunction func WithLogger(logger log.Logger) ConfigOpt { return func(config *Config) { config.Logger = logger @@ -46,7 +46,6 @@ func WithLogger(logger log.Logger) ConfigOpt { } // WithHTTPClient applies a custom http.Client to the rest rate limiter -//goland:noinspection GoUnusedExportedFunction func WithHTTPClient(httpClient *http.Client) ConfigOpt { return func(config *Config) { config.HTTPClient = httpClient @@ -54,42 +53,20 @@ func WithHTTPClient(httpClient *http.Client) ConfigOpt { } // WithRateLimiter applies a custom rrate.Limiter to the rest client -//goland:noinspection GoUnusedExportedFunction func WithRateLimiter(rateLimiter rrate.Limiter) ConfigOpt { return func(config *Config) { config.RateLimiter = rateLimiter } } -// WithRateLimiterConfig applies a custom logger to the rest rate limiter -//goland:noinspection GoUnusedExportedFunction -func WithRateLimiterConfig(rateLimiterConfig rrate.Config) ConfigOpt { - return func(config *Config) { - config.RateLimiterConfig = &rateLimiterConfig - } -} - // WithRateLimiterConfigOpts applies rrate.ConfigOpt for the rrate.Limiter to the rest rate limiter -//goland:noinspection GoUnusedExportedFunction func WithRateLimiterConfigOpts(opts ...rrate.ConfigOpt) ConfigOpt { return func(config *Config) { - if config.RateLimiterConfig == nil { - config.RateLimiterConfig = &rrate.DefaultConfig - } - config.RateLimiterConfig.Apply(opts) - } -} - -// WithBotTokenFunc sets the function to get the bot token -//goland:noinspection GoUnusedExportedFunction -func WithBotTokenFunc(botTokenFunc func() string) ConfigOpt { - return func(config *Config) { - config.BotTokenFunc = botTokenFunc + config.RateLimiterConfigOpts = append(config.RateLimiterConfigOpts, opts...) } } // WithUserAgent sets the user agent for all requests -//goland:noinspection GoUnusedExportedFunction func WithUserAgent(userAgent string) ConfigOpt { return func(config *Config) { config.UserAgent = userAgent diff --git a/rest/rest_error.go b/rest/rest_error.go index 4ff142e0..d6a6a00f 100644 --- a/rest/rest_error.go +++ b/rest/rest_error.go @@ -1,9 +1,10 @@ package rest import ( + "fmt" "net/http" - "github.com/DisgoOrg/disgo/discord" + "github.com/disgoorg/disgo/discord" ) var _ error = (*Error)(nil) @@ -65,7 +66,7 @@ func (e Error) Error() string { return e.Err.Error() } if e.Response != nil { - return e.Response.Status + return fmt.Sprintf("Status: %s, Body: %s", e.Response.Status, string(e.RsBody)) } return "unknown error" } diff --git a/rest/rest_services.go b/rest/rest_services.go deleted file mode 100644 index 92cae1aa..00000000 --- a/rest/rest_services.go +++ /dev/null @@ -1,165 +0,0 @@ -package rest - -import ( - "context" - "net/http" -) - -var _ Services = (*servicesImpl)(nil) - -// NewServices returns a new default Services -func NewServices(restClient Client) Services { - if restClient == nil { - restClient = NewClient(&DefaultConfig) - } - return &servicesImpl{ - restClient: restClient, - applicationService: NewApplicationService(restClient), - oauth2Service: NewOAuth2Service(restClient), - auditLogService: NewAuditLogService(restClient), - gatewayService: NewGatewayService(restClient), - guildService: NewGuildService(restClient), - channelService: NewChannelService(restClient), - threadService: NewThreadService(restClient), - interactionService: NewInteractionService(restClient), - inviteService: NewInviteService(restClient), - guildTemplateService: NewGuildTemplateService(restClient), - userService: NewUserService(restClient), - voiceService: NewVoiceService(restClient), - webhookService: NewWebhookService(restClient), - stageInstanceService: NewStageInstanceService(restClient), - emojiService: NewEmojiService(restClient), - stickerService: NewStickerService(restClient), - guildScheduledEventService: NewGuildScheduledEventService(restClient), - } -} - -// Services is a manager for all of disgo's HTTP requests -type Services interface { - RestClient() Client - HTTPClient() *http.Client - Close(ctx context.Context) - ApplicationService() ApplicationService - OAuth2Service() OAuth2Service - AuditLogService() AuditLogService - GatewayService() GatewayService - GuildService() GuildService - ChannelService() ChannelService - ThreadService() ThreadService - InteractionService() InteractionService - InviteService() InviteService - GuildTemplateService() GuildTemplateService - UserService() UserService - VoiceService() VoiceService - WebhookService() WebhookService - StageInstanceService() StageInstanceService - EmojiService() EmojiService - StickerService() StickerService - GuildScheduledEventService() GuildScheduledEventService -} - -type servicesImpl struct { - restClient Client - - applicationService ApplicationService - oauth2Service OAuth2Service - auditLogService AuditLogService - gatewayService GatewayService - guildService GuildService - channelService ChannelService - threadService ThreadService - interactionService InteractionService - inviteService InviteService - guildTemplateService GuildTemplateService - userService UserService - voiceService VoiceService - webhookService WebhookService - stageInstanceService StageInstanceService - emojiService EmojiService - stickerService StickerService - guildScheduledEventService GuildScheduledEventService -} - -func (s *servicesImpl) RestClient() Client { - return s.restClient -} - -func (s *servicesImpl) HTTPClient() *http.Client { - return s.RestClient().HTTPClient() -} - -func (s *servicesImpl) Close(ctx context.Context) { - s.restClient.Close(ctx) -} - -func (s *servicesImpl) ApplicationService() ApplicationService { - return s.applicationService -} - -func (s *servicesImpl) OAuth2Service() OAuth2Service { - return s.oauth2Service -} - -func (s *servicesImpl) AuditLogService() AuditLogService { - return s.auditLogService -} - -func (s *servicesImpl) GatewayService() GatewayService { - return s.gatewayService -} - -func (s *servicesImpl) GuildService() GuildService { - return s.guildService -} - -func (s *servicesImpl) ChannelService() ChannelService { - return s.channelService -} - -func (s *servicesImpl) ThreadService() ThreadService { - return s.threadService -} - -func (s *servicesImpl) InteractionService() InteractionService { - return s.interactionService -} - -func (s *servicesImpl) InviteService() InviteService { - return s.inviteService -} - -func (s *servicesImpl) GuildTemplateService() GuildTemplateService { - return s.guildTemplateService -} - -func (s *servicesImpl) UserService() UserService { - return s.userService -} - -func (s *servicesImpl) VoiceService() VoiceService { - return s.voiceService -} - -func (s *servicesImpl) WebhookService() WebhookService { - return s.webhookService -} - -func (s *servicesImpl) StageInstanceService() StageInstanceService { - return s.stageInstanceService -} - -func (s *servicesImpl) EmojiService() EmojiService { - return s.emojiService -} - -func (s *servicesImpl) StickerService() StickerService { - return s.stickerService -} - -func (s *servicesImpl) GuildScheduledEventService() GuildScheduledEventService { - return s.guildScheduledEventService -} - -type Service interface { - RestClient() Client -} diff --git a/rest/route/api_route.go b/rest/route/api_route.go index 47402a26..23d64d2e 100644 --- a/rest/route/api_route.go +++ b/rest/route/api_route.go @@ -15,7 +15,7 @@ func NewAPIRouteNoAuth(method Method, path string, queryParams ...string) *APIRo return newAPIRoute(method, path, queryParams, false) } -func newAPIRoute(method Method, path string, queryParams []string, needsAuth bool) *APIRoute { +func newAPIRoute(method Method, path string, queryParams []string, needsBotAuth bool) *APIRoute { params := map[string]struct{}{} for _, param := range queryParams { params[param] = struct{}{} @@ -27,12 +27,11 @@ func newAPIRoute(method Method, path string, queryParams []string, needsAuth boo queryParams: params, urlParamCount: countURLParams(path), method: method, - needsAuth: needsAuth, + needsBotAuth: needsBotAuth, } } // NewCustomAPIRoute generates a new custom path struct -//goland:noinspection GoUnusedExportedFunction func NewCustomAPIRoute(method Method, basePath string, path string, queryParams ...string) *APIRoute { route := NewAPIRoute(method, path, queryParams...) route.basePath = basePath @@ -46,11 +45,11 @@ type APIRoute struct { queryParams map[string]struct{} urlParamCount int method Method - needsAuth bool + needsBotAuth bool } // Compile returns a CompiledAPIRoute -func (r *APIRoute) Compile(queryValues QueryValues, params ...interface{}) (*CompiledAPIRoute, error) { +func (r *APIRoute) Compile(queryValues QueryValues, params ...any) (*CompiledAPIRoute, error) { if len(params) != r.urlParamCount { return nil, ErrInvalidArgCount(r.urlParamCount, len(params)) } @@ -99,9 +98,9 @@ func (r *APIRoute) Path() string { return r.path } -// NeedsAuth returns whether the route requires authentication -func (r *APIRoute) NeedsAuth() bool { - return r.needsAuth +// NeedsBotAuth returns whether the route requires authentication +func (r *APIRoute) NeedsBotAuth() bool { + return r.needsBotAuth } // CompiledAPIRoute is APIRoute compiled with all URL args diff --git a/rest/route/cdn_route.go b/rest/route/cdn_route.go index d2c20f0f..251e7da5 100644 --- a/rest/route/cdn_route.go +++ b/rest/route/cdn_route.go @@ -25,7 +25,6 @@ func NewCDNRoute(path string, supportedImageFormats ...ImageFormat) *CDNRoute { } // NewCustomCDNRoute generates a new custom cdn path struct -//goland:noinspection GoUnusedExportedFunction func NewCustomCDNRoute(basePath string, path string, supportedImageFormats ...ImageFormat) *CDNRoute { route := NewCDNRoute(path, supportedImageFormats...) route.basePath = basePath @@ -42,7 +41,7 @@ type CDNRoute struct { } // Compile builds a full request URL based on provided arguments -func (r *CDNRoute) Compile(queryValues QueryValues, imageFormat ImageFormat, size int, params ...interface{}) (*CompiledCDNRoute, error) { +func (r *CDNRoute) Compile(queryValues QueryValues, imageFormat ImageFormat, size int, params ...any) (*CompiledCDNRoute, error) { supported := false for _, supportedFileExtension := range r.supportedImageFormats { if supportedFileExtension == imageFormat { @@ -55,7 +54,9 @@ func (r *CDNRoute) Compile(queryValues QueryValues, imageFormat ImageFormat, siz if queryValues == nil { queryValues = QueryValues{} } - queryValues["size"] = size + if size > 0 { + queryValues["size"] = size + } path := r.path for _, param := range params { diff --git a/rest/route/route.go b/rest/route/route.go index 33658ce0..3738fc6e 100644 --- a/rest/route/route.go +++ b/rest/route/route.go @@ -22,7 +22,6 @@ func NewRoute(path string, queryParams ...string) *Route { } // NewCustomRoute generates a new custom path struct -//goland:noinspection GoUnusedExportedFunction func NewCustomRoute(basePath string, path string, queryParams ...string) *Route { route := NewRoute(path, queryParams...) route.basePath = basePath @@ -38,7 +37,7 @@ type Route struct { } // Compile returns a CompiledRoute -func (r *Route) Compile(queryValues QueryValues, params ...interface{}) (*CompiledRoute, error) { +func (r *Route) Compile(queryValues QueryValues, params ...any) (*CompiledRoute, error) { if len(params) != r.urlParamCount { return nil, ErrInvalidArgCount(r.urlParamCount, len(params)) } diff --git a/rest/route/route_const.go b/rest/route/route_const.go index b629418b..f3f32063 100644 --- a/rest/route/route_const.go +++ b/rest/route/route_const.go @@ -27,7 +27,7 @@ func (m Method) String() string { } // QueryValues is used to supply query param value pairs to Route.Compile -type QueryValues map[string]interface{} +type QueryValues map[string]any // ImageFormat is the type of image on Discord's CDN (https://discord.com/developers/docs/reference#image-formatting-image-formats) type ImageFormat string @@ -45,3 +45,12 @@ const ( func (f ImageFormat) String() string { return string(f) } + +func (f ImageFormat) CanBeAnimated() bool { + switch f { + case WebP, GIF: + return true + default: + return false + } +} diff --git a/rest/route/route_endpoints.go b/rest/route/route_endpoints.go index 5dc43c23..a3d47bd3 100644 --- a/rest/route/route_endpoints.go +++ b/rest/route/route_endpoints.go @@ -220,7 +220,7 @@ var ( // Invites var ( - GetInvite = NewAPIRoute(GET, "/invites/{code}") + GetInvite = NewAPIRoute(GET, "/invites/{code}", "with_counts", "with_expiration", "guild_scheduled_event_id") CreateInvite = NewAPIRoute(POST, "/channels/{channel.id}/invites") DeleteInvite = NewAPIRoute(DELETE, "/invites/{code}") @@ -230,14 +230,14 @@ var ( // Interactions var ( - GetGlobalCommands = NewAPIRoute(GET, "/applications/{application.id}/commands") + GetGlobalCommands = NewAPIRoute(GET, "/applications/{application.id}/commands", "with_localizations") GetGlobalCommand = NewAPIRoute(GET, "/applications/{application.id}/command/{command.id}") CreateGlobalCommand = NewAPIRoute(POST, "/applications/{application.id}/commands") SetGlobalCommands = NewAPIRoute(PUT, "/applications/{application.id}/commands") UpdateGlobalCommand = NewAPIRoute(PATCH, "/applications/{application.id}/commands/{command.id}") DeleteGlobalCommand = NewAPIRoute(DELETE, "/applications/{application.id}/commands") - GetGuildCommands = NewAPIRoute(GET, "/applications/{application.id}/guilds/{guild.id}/commands") + GetGuildCommands = NewAPIRoute(GET, "/applications/{application.id}/guilds/{guild.id}/commands", "with_localizations") GetGuildCommand = NewAPIRoute(GET, "/applications/{application.id}/guilds/{guild.id}/command/{command.id}") CreateGuildCommand = NewAPIRoute(POST, "/applications/{application.id}/guilds/{guild.id}/commands") SetGuildCommands = NewAPIRoute(PUT, "/applications/{application.id}/guilds/{guild.id}/commands") diff --git a/rest/route/route_test.go b/rest/route/route_test.go index e52f7d17..a7864f23 100644 --- a/rest/route/route_test.go +++ b/rest/route/route_test.go @@ -12,7 +12,7 @@ var ( ) func TestAPIRoute_Compile(t *testing.T) { - queryParams := map[string]interface{}{ + queryParams := map[string]any{ "wait": true, } compiledRoute, err := APITestRoute.Compile(queryParams, "test1", "test2", "test3") diff --git a/rest/rrate/rest_rate_limiter.go b/rest/rrate/rest_rate_limiter.go index 26a5602c..9097d4fb 100644 --- a/rest/rrate/rest_rate_limiter.go +++ b/rest/rrate/rest_rate_limiter.go @@ -4,8 +4,8 @@ import ( "context" "net/http" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/log" ) // Limiter can be used to supply your own rate limit implementation @@ -13,8 +13,8 @@ type Limiter interface { // Logger returns the logger the rate limiter uses Logger() log.Logger - // Config returns the Config the rate limiter uses - Config() Config + // MaxRetries returns the maximum number of retries the client should do + MaxRetries() int // Close closes the rate limiter and awaits all pending requests to finish. You can use a cancelling context to abort the waiting Close(ctx context.Context) diff --git a/rest/rrate/rest_rate_limiter_config.go b/rest/rrate/rest_rate_limiter_config.go index 6ba4501d..82b305d5 100644 --- a/rest/rrate/rest_rate_limiter_config.go +++ b/rest/rrate/rest_rate_limiter_config.go @@ -1,12 +1,15 @@ package rrate import ( - "github.com/DisgoOrg/log" + "github.com/disgoorg/log" ) // DefaultConfig is the configuration which is used by default -var DefaultConfig = Config{ - MaxRetries: 10, +func DefaultConfig() *Config { + return &Config{ + Logger: log.Default(), + MaxRetries: 10, + } } // Config is the configuration for the rate limiter @@ -26,7 +29,6 @@ func (c *Config) Apply(opts []ConfigOpt) { } // WithLogger applies a custom logger to the rest rate limiter -//goland:noinspection GoUnusedExportedFunction func WithLogger(logger log.Logger) ConfigOpt { return func(config *Config) { config.Logger = logger @@ -34,7 +36,6 @@ func WithLogger(logger log.Logger) ConfigOpt { } // WithMaxRetries tells the rest rate limiter to retry the request up to the specified number of times if it encounters a 429 response -//goland:noinspection GoUnusedExportedFunction func WithMaxRetries(maxRetries int) ConfigOpt { return func(config *Config) { config.MaxRetries = maxRetries diff --git a/rest/rrate/rest_rate_limiter_impl.go b/rest/rrate/rest_rate_limiter_impl.go index 0eaeeb14..ed2f6ce3 100644 --- a/rest/rrate/rest_rate_limiter_impl.go +++ b/rest/rrate/rest_rate_limiter_impl.go @@ -8,21 +8,18 @@ import ( "sync" "time" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/log" "github.com/sasha-s/go-csync" ) // TODO: do we need some cleanup task? // NewLimiter return a new default implementation of a rest rate limiter -func NewLimiter(config *Config) Limiter { - if config == nil { - config = &DefaultConfig - } - if config.Logger == nil { - config.Logger = log.Default() - } +func NewLimiter(opts ...ConfigOpt) Limiter { + config := DefaultConfig() + config.Apply(opts) + return &limiterImpl{ config: *config, hashes: map[*route.APIRoute]routeHash{}, @@ -53,8 +50,8 @@ func (l *limiterImpl) Logger() log.Logger { return l.config.Logger } -func (l *limiterImpl) Config() Config { - return l.config +func (l *limiterImpl) MaxRetries() int { + return l.config.MaxRetries } func (l *limiterImpl) Close(ctx context.Context) { diff --git a/rest/stage_instance_service.go b/rest/stage_instances.go similarity index 53% rename from rest/stage_instance_service.go rename to rest/stage_instances.go index 3f3e2168..a704816b 100644 --- a/rest/stage_instance_service.go +++ b/rest/stage_instances.go @@ -1,37 +1,29 @@ package rest import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) -var ( - _ Service = (*stageInstanceServiceImpl)(nil) - _ StageInstanceService = (*stageInstanceServiceImpl)(nil) -) +var _ StageInstances = (*stageInstanceImpl)(nil) -func NewStageInstanceService(restClient Client) StageInstanceService { - return &stageInstanceServiceImpl{restClient: restClient} +func NewStageInstances(restClient Client) StageInstances { + return &stageInstanceImpl{restClient: restClient} } -type StageInstanceService interface { - Service +type StageInstances interface { GetStageInstance(guildID snowflake.Snowflake, opts ...RequestOpt) (*discord.StageInstance, error) CreateStageInstance(stageInstanceCreate discord.StageInstanceCreate, opts ...RequestOpt) (*discord.StageInstance, error) UpdateStageInstance(guildID snowflake.Snowflake, stageInstanceUpdate discord.StageInstanceUpdate, opts ...RequestOpt) (*discord.StageInstance, error) DeleteStageInstance(guildID snowflake.Snowflake, opts ...RequestOpt) error } -type stageInstanceServiceImpl struct { +type stageInstanceImpl struct { restClient Client } -func (s *stageInstanceServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *stageInstanceServiceImpl) GetStageInstance(guildID snowflake.Snowflake, opts ...RequestOpt) (stageInstance *discord.StageInstance, err error) { +func (s *stageInstanceImpl) GetStageInstance(guildID snowflake.Snowflake, opts ...RequestOpt) (stageInstance *discord.StageInstance, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetStageInstance.Compile(nil, guildID) if err != nil { @@ -41,7 +33,7 @@ func (s *stageInstanceServiceImpl) GetStageInstance(guildID snowflake.Snowflake, return } -func (s *stageInstanceServiceImpl) CreateStageInstance(stageInstanceCreate discord.StageInstanceCreate, opts ...RequestOpt) (stageInstance *discord.StageInstance, err error) { +func (s *stageInstanceImpl) CreateStageInstance(stageInstanceCreate discord.StageInstanceCreate, opts ...RequestOpt) (stageInstance *discord.StageInstance, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateStageInstance.Compile(nil) if err != nil { @@ -51,7 +43,7 @@ func (s *stageInstanceServiceImpl) CreateStageInstance(stageInstanceCreate disco return } -func (s *stageInstanceServiceImpl) UpdateStageInstance(guildID snowflake.Snowflake, stageInstanceUpdate discord.StageInstanceUpdate, opts ...RequestOpt) (stageInstance *discord.StageInstance, err error) { +func (s *stageInstanceImpl) UpdateStageInstance(guildID snowflake.Snowflake, stageInstanceUpdate discord.StageInstanceUpdate, opts ...RequestOpt) (stageInstance *discord.StageInstance, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateStageInstance.Compile(nil, guildID) if err != nil { @@ -61,7 +53,7 @@ func (s *stageInstanceServiceImpl) UpdateStageInstance(guildID snowflake.Snowfla return } -func (s *stageInstanceServiceImpl) DeleteStageInstance(guildID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *stageInstanceImpl) DeleteStageInstance(guildID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.DeleteStageInstance.Compile(nil, guildID) if err != nil { return err diff --git a/rest/sticker_service.go b/rest/stickers.go similarity index 61% rename from rest/sticker_service.go rename to rest/stickers.go index 4b9b3a53..27e933c9 100644 --- a/rest/sticker_service.go +++ b/rest/stickers.go @@ -1,21 +1,18 @@ package rest import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) -var ( - _ Service = (*stickerServiceImpl)(nil) - _ StickerService = (*stickerServiceImpl)(nil) -) +var _ Stickers = (*stickerImpl)(nil) -func NewStickerService(restClient Client) StickerService { - return &stickerServiceImpl{restClient: restClient} +func NewStickers(restClient Client) Stickers { + return &stickerImpl{restClient: restClient} } -type StickerService interface { +type Stickers interface { GetNitroStickerPacks(opts ...RequestOpt) ([]discord.StickerPack, error) GetSticker(stickerID snowflake.Snowflake, opts ...RequestOpt) (*discord.Sticker, error) GetStickers(guildID snowflake.Snowflake, opts ...RequestOpt) ([]discord.Sticker, error) @@ -24,15 +21,11 @@ type StickerService interface { DeleteSticker(guildID snowflake.Snowflake, stickerID snowflake.Snowflake, opts ...RequestOpt) error } -type stickerServiceImpl struct { +type stickerImpl struct { restClient Client } -func (s *stickerServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *stickerServiceImpl) GetNitroStickerPacks(opts ...RequestOpt) (stickerPacks []discord.StickerPack, err error) { +func (s *stickerImpl) GetNitroStickerPacks(opts ...RequestOpt) (stickerPacks []discord.StickerPack, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetNitroStickerPacks.Compile(nil) if err != nil { @@ -46,7 +39,7 @@ func (s *stickerServiceImpl) GetNitroStickerPacks(opts ...RequestOpt) (stickerPa return } -func (s *stickerServiceImpl) GetSticker(stickerID snowflake.Snowflake, opts ...RequestOpt) (sticker *discord.Sticker, err error) { +func (s *stickerImpl) GetSticker(stickerID snowflake.Snowflake, opts ...RequestOpt) (sticker *discord.Sticker, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetSticker.Compile(nil, stickerID) if err != nil { @@ -56,7 +49,7 @@ func (s *stickerServiceImpl) GetSticker(stickerID snowflake.Snowflake, opts ...R return } -func (s *stickerServiceImpl) GetStickers(guildID snowflake.Snowflake, opts ...RequestOpt) (stickers []discord.Sticker, err error) { +func (s *stickerImpl) GetStickers(guildID snowflake.Snowflake, opts ...RequestOpt) (stickers []discord.Sticker, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetGuildStickers.Compile(nil, guildID) if err != nil { @@ -66,7 +59,7 @@ func (s *stickerServiceImpl) GetStickers(guildID snowflake.Snowflake, opts ...Re return } -func (s *stickerServiceImpl) CreateSticker(guildID snowflake.Snowflake, createSticker discord.StickerCreate, opts ...RequestOpt) (sticker *discord.Sticker, err error) { +func (s *stickerImpl) CreateSticker(guildID snowflake.Snowflake, createSticker discord.StickerCreate, opts ...RequestOpt) (sticker *discord.Sticker, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateGuildSticker.Compile(nil, guildID) if err != nil { @@ -80,7 +73,7 @@ func (s *stickerServiceImpl) CreateSticker(guildID snowflake.Snowflake, createSt return } -func (s *stickerServiceImpl) UpdateSticker(guildID snowflake.Snowflake, stickerID snowflake.Snowflake, stickerUpdate discord.StickerUpdate, opts ...RequestOpt) (sticker *discord.Sticker, err error) { +func (s *stickerImpl) UpdateSticker(guildID snowflake.Snowflake, stickerID snowflake.Snowflake, stickerUpdate discord.StickerUpdate, opts ...RequestOpt) (sticker *discord.Sticker, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateGuildSticker.Compile(nil, guildID, stickerID) if err != nil { @@ -90,7 +83,7 @@ func (s *stickerServiceImpl) UpdateSticker(guildID snowflake.Snowflake, stickerI return } -func (s *stickerServiceImpl) DeleteSticker(guildID snowflake.Snowflake, stickerID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *stickerImpl) DeleteSticker(guildID snowflake.Snowflake, stickerID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.DeleteGuildSticker.Compile(nil, guildID, stickerID) if err != nil { return err diff --git a/rest/thread_service.go b/rest/threads.go similarity index 68% rename from rest/thread_service.go rename to rest/threads.go index 98491591..d3799b7d 100644 --- a/rest/thread_service.go +++ b/rest/threads.go @@ -1,22 +1,18 @@ package rest import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) -var ( - _ Service = (*threadServiceImpl)(nil) - _ ThreadService = (*threadServiceImpl)(nil) -) +var _ Threads = (*threadImpl)(nil) -func NewThreadService(restClient Client) ThreadService { - return &threadServiceImpl{restClient: restClient} +func NewThreads(restClient Client) Threads { + return &threadImpl{restClient: restClient} } -type ThreadService interface { - Service +type Threads interface { CreateThreadWithMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, threadCreateWithMessage discord.ThreadCreateWithMessage, opts ...RequestOpt) (thread discord.GuildThread, err error) CreateThread(channelID snowflake.Snowflake, threadCreate discord.ThreadCreate, opts ...RequestOpt) (thread discord.GuildThread, err error) JoinThread(threadID snowflake.Snowflake, opts ...RequestOpt) error @@ -31,15 +27,11 @@ type ThreadService interface { GetJoinedPrivateArchivedThreads(channelID snowflake.Snowflake, before discord.Time, limit int, opts ...RequestOpt) (threads *discord.GetThreads, err error) } -type threadServiceImpl struct { +type threadImpl struct { restClient Client } -func (s *threadServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *threadServiceImpl) CreateThreadWithMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, threadCreateWithMessage discord.ThreadCreateWithMessage, opts ...RequestOpt) (thread discord.GuildThread, err error) { +func (s *threadImpl) CreateThreadWithMessage(channelID snowflake.Snowflake, messageID snowflake.Snowflake, threadCreateWithMessage discord.ThreadCreateWithMessage, opts ...RequestOpt) (thread discord.GuildThread, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateThreadWithMessage.Compile(nil, channelID, messageID) if err != nil { @@ -53,7 +45,7 @@ func (s *threadServiceImpl) CreateThreadWithMessage(channelID snowflake.Snowflak return } -func (s *threadServiceImpl) CreateThread(channelID snowflake.Snowflake, threadCreate discord.ThreadCreate, opts ...RequestOpt) (thread discord.GuildThread, err error) { +func (s *threadImpl) CreateThread(channelID snowflake.Snowflake, threadCreate discord.ThreadCreate, opts ...RequestOpt) (thread discord.GuildThread, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateThread.Compile(nil, channelID) if err != nil { @@ -67,7 +59,7 @@ func (s *threadServiceImpl) CreateThread(channelID snowflake.Snowflake, threadCr return } -func (s *threadServiceImpl) JoinThread(threadID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *threadImpl) JoinThread(threadID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.JoinThread.Compile(nil, threadID) if err != nil { return err @@ -75,7 +67,7 @@ func (s *threadServiceImpl) JoinThread(threadID snowflake.Snowflake, opts ...Req return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *threadServiceImpl) LeaveThread(threadID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *threadImpl) LeaveThread(threadID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.LeaveThread.Compile(nil, threadID) if err != nil { return err @@ -83,7 +75,7 @@ func (s *threadServiceImpl) LeaveThread(threadID snowflake.Snowflake, opts ...Re return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *threadServiceImpl) AddThreadMember(threadID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *threadImpl) AddThreadMember(threadID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.AddThreadMember.Compile(nil, threadID, userID) if err != nil { return err @@ -91,7 +83,7 @@ func (s *threadServiceImpl) AddThreadMember(threadID snowflake.Snowflake, userID return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *threadServiceImpl) RemoveThreadMember(threadID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *threadImpl) RemoveThreadMember(threadID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.RemoveThreadMember.Compile(nil, threadID, userID) if err != nil { return err @@ -99,7 +91,7 @@ func (s *threadServiceImpl) RemoveThreadMember(threadID snowflake.Snowflake, use return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *threadServiceImpl) GetThreadMember(threadID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) (threadMember *discord.ThreadMember, err error) { +func (s *threadImpl) GetThreadMember(threadID snowflake.Snowflake, userID snowflake.Snowflake, opts ...RequestOpt) (threadMember *discord.ThreadMember, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetThreadMember.Compile(nil, threadID, userID) if err != nil { @@ -109,7 +101,7 @@ func (s *threadServiceImpl) GetThreadMember(threadID snowflake.Snowflake, userID return } -func (s *threadServiceImpl) GetThreadMembers(threadID snowflake.Snowflake, opts ...RequestOpt) (threadMembers []discord.ThreadMember, err error) { +func (s *threadImpl) GetThreadMembers(threadID snowflake.Snowflake, opts ...RequestOpt) (threadMembers []discord.ThreadMember, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetThreadMembers.Compile(nil, threadID) if err != nil { @@ -119,7 +111,7 @@ func (s *threadServiceImpl) GetThreadMembers(threadID snowflake.Snowflake, opts return } -func (s *threadServiceImpl) GetPublicArchivedThreads(channelID snowflake.Snowflake, before discord.Time, limit int, opts ...RequestOpt) (threads *discord.GetThreads, err error) { +func (s *threadImpl) GetPublicArchivedThreads(channelID snowflake.Snowflake, before discord.Time, limit int, opts ...RequestOpt) (threads *discord.GetThreads, err error) { queryValues := route.QueryValues{} if !before.IsZero() { queryValues["before"] = before @@ -136,7 +128,7 @@ func (s *threadServiceImpl) GetPublicArchivedThreads(channelID snowflake.Snowfla return } -func (s *threadServiceImpl) GetPrivateArchivedThreads(channelID snowflake.Snowflake, before discord.Time, limit int, opts ...RequestOpt) (threads *discord.GetThreads, err error) { +func (s *threadImpl) GetPrivateArchivedThreads(channelID snowflake.Snowflake, before discord.Time, limit int, opts ...RequestOpt) (threads *discord.GetThreads, err error) { queryValues := route.QueryValues{} if !before.IsZero() { queryValues["before"] = before @@ -153,7 +145,7 @@ func (s *threadServiceImpl) GetPrivateArchivedThreads(channelID snowflake.Snowfl return } -func (s *threadServiceImpl) GetJoinedPrivateArchivedThreads(channelID snowflake.Snowflake, before discord.Time, limit int, opts ...RequestOpt) (threads *discord.GetThreads, err error) { +func (s *threadImpl) GetJoinedPrivateArchivedThreads(channelID snowflake.Snowflake, before discord.Time, limit int, opts ...RequestOpt) (threads *discord.GetThreads, err error) { queryValues := route.QueryValues{} if !before.IsZero() { queryValues["before"] = before diff --git a/rest/user_service.go b/rest/users.go similarity index 62% rename from rest/user_service.go rename to rest/users.go index 5d3a38b0..676b3f34 100644 --- a/rest/user_service.go +++ b/rest/users.go @@ -1,39 +1,31 @@ package rest import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) -var ( - _ Service = (*userServiceImpl)(nil) - _ UserService = (*userServiceImpl)(nil) -) +var _ Users = (*userImpl)(nil) -func NewUserService(restClient Client) UserService { - return &userServiceImpl{restClient: restClient} +func NewUsers(restClient Client) Users { + return &userImpl{restClient: restClient} } -type UserService interface { - Service +type Users interface { GetUser(userID snowflake.Snowflake, opts ...RequestOpt) (*discord.User, error) UpdateSelfUser(selfUserUpdate discord.SelfUserUpdate, opts ...RequestOpt) (*discord.OAuth2User, error) GetGuilds(before int, after int, limit int, opts ...RequestOpt) ([]discord.OAuth2Guild, error) LeaveGuild(guildID snowflake.Snowflake, opts ...RequestOpt) error GetDMChannels(opts ...RequestOpt) ([]discord.Channel, error) - CreateDMChannel(userID snowflake.Snowflake, opts ...RequestOpt) (*discord.Channel, error) + CreateDMChannel(userID snowflake.Snowflake, opts ...RequestOpt) (*discord.DMChannel, error) } -type userServiceImpl struct { +type userImpl struct { restClient Client } -func (s *userServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *userServiceImpl) GetUser(userID snowflake.Snowflake, opts ...RequestOpt) (user *discord.User, err error) { +func (s *userImpl) GetUser(userID snowflake.Snowflake, opts ...RequestOpt) (user *discord.User, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetUser.Compile(nil, userID) if err != nil { @@ -43,7 +35,7 @@ func (s *userServiceImpl) GetUser(userID snowflake.Snowflake, opts ...RequestOpt return } -func (s *userServiceImpl) UpdateSelfUser(updateSelfUser discord.SelfUserUpdate, opts ...RequestOpt) (selfUser *discord.OAuth2User, err error) { +func (s *userImpl) UpdateSelfUser(updateSelfUser discord.SelfUserUpdate, opts ...RequestOpt) (selfUser *discord.OAuth2User, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateSelfUser.Compile(nil) if err != nil { @@ -54,7 +46,7 @@ func (s *userServiceImpl) UpdateSelfUser(updateSelfUser discord.SelfUserUpdate, return } -func (s *userServiceImpl) GetGuilds(before int, after int, limit int, opts ...RequestOpt) (guilds []discord.OAuth2Guild, err error) { +func (s *userImpl) GetGuilds(before int, after int, limit int, opts ...RequestOpt) (guilds []discord.OAuth2Guild, err error) { queryParams := route.QueryValues{} if before > 0 { queryParams["before"] = before @@ -75,7 +67,7 @@ func (s *userServiceImpl) GetGuilds(before int, after int, limit int, opts ...Re return } -func (s *userServiceImpl) LeaveGuild(guildID snowflake.Snowflake, opts ...RequestOpt) error { +func (s *userImpl) LeaveGuild(guildID snowflake.Snowflake, opts ...RequestOpt) error { compiledRoute, err := route.LeaveGuild.Compile(nil, guildID) if err != nil { return err @@ -83,7 +75,7 @@ func (s *userServiceImpl) LeaveGuild(guildID snowflake.Snowflake, opts ...Reques return s.restClient.Do(compiledRoute, nil, nil, opts...) } -func (s *userServiceImpl) GetDMChannels(opts ...RequestOpt) (channels []discord.Channel, err error) { +func (s *userImpl) GetDMChannels(opts ...RequestOpt) (channels []discord.Channel, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetDMChannels.Compile(nil) if err != nil { @@ -94,7 +86,7 @@ func (s *userServiceImpl) GetDMChannels(opts ...RequestOpt) (channels []discord. return } -func (s *userServiceImpl) CreateDMChannel(userID snowflake.Snowflake, opts ...RequestOpt) (channel *discord.Channel, err error) { +func (s *userImpl) CreateDMChannel(userID snowflake.Snowflake, opts ...RequestOpt) (channel *discord.DMChannel, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.CreateDMChannel.Compile(nil) if err != nil { diff --git a/rest/voice.go b/rest/voice.go new file mode 100644 index 00000000..b00c7509 --- /dev/null +++ b/rest/voice.go @@ -0,0 +1,30 @@ +package rest + +import ( + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" +) + +var _ Voice = (*voiceImpl)(nil) + +func NewVoice(restClient Client) Voice { + return &voiceImpl{restClient: restClient} +} + +type Voice interface { + GetVoiceRegions(opts ...RequestOpt) ([]discord.VoiceRegion, error) +} + +type voiceImpl struct { + restClient Client +} + +func (s *voiceImpl) GetVoiceRegions(opts ...RequestOpt) (regions []discord.VoiceRegion, err error) { + var compiledRoute *route.CompiledAPIRoute + compiledRoute, err = route.GetVoiceRegions.Compile(nil) + if err != nil { + return + } + err = s.restClient.Do(compiledRoute, nil, ®ions, opts...) + return +} diff --git a/rest/voice_service.go b/rest/voice_service.go deleted file mode 100644 index 9e5dd3a3..00000000 --- a/rest/voice_service.go +++ /dev/null @@ -1,38 +0,0 @@ -package rest - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" -) - -var ( - _ Service = (*voiceServiceImpl)(nil) - _ VoiceService = (*voiceServiceImpl)(nil) -) - -func NewVoiceService(restClient Client) VoiceService { - return &voiceServiceImpl{restClient: restClient} -} - -type VoiceService interface { - Service - GetVoiceRegions(opts ...RequestOpt) ([]discord.VoiceRegion, error) -} - -type voiceServiceImpl struct { - restClient Client -} - -func (s *voiceServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *voiceServiceImpl) GetVoiceRegions(opts ...RequestOpt) (regions []discord.VoiceRegion, err error) { - var compiledRoute *route.CompiledAPIRoute - compiledRoute, err = route.GetVoiceRegions.Compile(nil) - if err != nil { - return - } - err = s.restClient.Do(compiledRoute, nil, ®ions, opts...) - return -} diff --git a/rest/webhook_service.go b/rest/webhooks.go similarity index 65% rename from rest/webhook_service.go rename to rest/webhooks.go index 2d7793e6..6da7066c 100644 --- a/rest/webhook_service.go +++ b/rest/webhooks.go @@ -1,22 +1,18 @@ package rest import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" ) -var ( - _ Service = (*webhookServiceImpl)(nil) - _ WebhookService = (*webhookServiceImpl)(nil) -) +var _ Webhooks = (*webhookImpl)(nil) -func NewWebhookService(restClient Client) WebhookService { - return &webhookServiceImpl{restClient: restClient} +func NewWebhooks(restClient Client) Webhooks { + return &webhookImpl{restClient: restClient} } -type WebhookService interface { - Service +type Webhooks interface { GetWebhook(webhookID snowflake.Snowflake, opts ...RequestOpt) (discord.Webhook, error) UpdateWebhook(webhookID snowflake.Snowflake, webhookUpdate discord.WebhookUpdate, opts ...RequestOpt) (discord.Webhook, error) DeleteWebhook(webhookID snowflake.Snowflake, opts ...RequestOpt) error @@ -32,15 +28,11 @@ type WebhookService interface { DeleteMessage(webhookID snowflake.Snowflake, webhookToken string, messageID snowflake.Snowflake, threadID snowflake.Snowflake, opts ...RequestOpt) error } -type webhookServiceImpl struct { +type webhookImpl struct { restClient Client } -func (s *webhookServiceImpl) RestClient() Client { - return s.restClient -} - -func (s *webhookServiceImpl) GetWebhook(webhookID snowflake.Snowflake, opts ...RequestOpt) (webhook discord.Webhook, err error) { +func (s *webhookImpl) GetWebhook(webhookID snowflake.Snowflake, opts ...RequestOpt) (webhook discord.Webhook, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetWebhook.Compile(nil, webhookID) if err != nil { @@ -55,7 +47,7 @@ func (s *webhookServiceImpl) GetWebhook(webhookID snowflake.Snowflake, opts ...R return } -func (s *webhookServiceImpl) UpdateWebhook(webhookID snowflake.Snowflake, webhookUpdate discord.WebhookUpdate, opts ...RequestOpt) (webhook discord.Webhook, err error) { +func (s *webhookImpl) UpdateWebhook(webhookID snowflake.Snowflake, webhookUpdate discord.WebhookUpdate, opts ...RequestOpt) (webhook discord.Webhook, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateWebhook.Compile(nil, webhookID) if err != nil { @@ -70,7 +62,7 @@ func (s *webhookServiceImpl) UpdateWebhook(webhookID snowflake.Snowflake, webhoo return } -func (s *webhookServiceImpl) DeleteWebhook(webhookID snowflake.Snowflake, opts ...RequestOpt) (err error) { +func (s *webhookImpl) DeleteWebhook(webhookID snowflake.Snowflake, opts ...RequestOpt) (err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.DeleteWebhook.Compile(nil, webhookID) if err != nil { @@ -80,7 +72,7 @@ func (s *webhookServiceImpl) DeleteWebhook(webhookID snowflake.Snowflake, opts . return } -func (s *webhookServiceImpl) GetWebhookWithToken(webhookID snowflake.Snowflake, webhookToken string, opts ...RequestOpt) (webhook discord.Webhook, err error) { +func (s *webhookImpl) GetWebhookWithToken(webhookID snowflake.Snowflake, webhookToken string, opts ...RequestOpt) (webhook discord.Webhook, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.GetWebhookWithToken.Compile(nil, webhookID, webhookToken) if err != nil { @@ -95,7 +87,7 @@ func (s *webhookServiceImpl) GetWebhookWithToken(webhookID snowflake.Snowflake, return } -func (s *webhookServiceImpl) UpdateWebhookWithToken(webhookID snowflake.Snowflake, webhookToken string, webhookUpdate discord.WebhookUpdateWithToken, opts ...RequestOpt) (webhook discord.Webhook, err error) { +func (s *webhookImpl) UpdateWebhookWithToken(webhookID snowflake.Snowflake, webhookToken string, webhookUpdate discord.WebhookUpdateWithToken, opts ...RequestOpt) (webhook discord.Webhook, err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.UpdateWebhookWithToken.Compile(nil, webhookID, webhookToken) if err != nil { @@ -110,7 +102,7 @@ func (s *webhookServiceImpl) UpdateWebhookWithToken(webhookID snowflake.Snowflak return } -func (s *webhookServiceImpl) DeleteWebhookWithToken(webhookID snowflake.Snowflake, webhookToken string, opts ...RequestOpt) (err error) { +func (s *webhookImpl) DeleteWebhookWithToken(webhookID snowflake.Snowflake, webhookToken string, opts ...RequestOpt) (err error) { var compiledRoute *route.CompiledAPIRoute compiledRoute, err = route.DeleteWebhookWithToken.Compile(nil, webhookID, webhookToken) if err != nil { @@ -120,7 +112,7 @@ func (s *webhookServiceImpl) DeleteWebhookWithToken(webhookID snowflake.Snowflak return } -func (s *webhookServiceImpl) createMessage(webhookID snowflake.Snowflake, webhookToken string, messageCreate discord.Payload, wait bool, threadID snowflake.Snowflake, apiRoute *route.APIRoute, opts []RequestOpt) (message *discord.Message, err error) { +func (s *webhookImpl) createMessage(webhookID snowflake.Snowflake, webhookToken string, messageCreate discord.Payload, wait bool, threadID snowflake.Snowflake, apiRoute *route.APIRoute, opts []RequestOpt) (message *discord.Message, err error) { params := route.QueryValues{} if wait { params["wait"] = true @@ -147,19 +139,19 @@ func (s *webhookServiceImpl) createMessage(webhookID snowflake.Snowflake, webhoo return } -func (s *webhookServiceImpl) CreateMessage(webhookID snowflake.Snowflake, webhookToken string, messageCreate discord.WebhookMessageCreate, wait bool, threadID snowflake.Snowflake, opts ...RequestOpt) (*discord.Message, error) { +func (s *webhookImpl) CreateMessage(webhookID snowflake.Snowflake, webhookToken string, messageCreate discord.WebhookMessageCreate, wait bool, threadID snowflake.Snowflake, opts ...RequestOpt) (*discord.Message, error) { return s.createMessage(webhookID, webhookToken, messageCreate, wait, threadID, route.CreateWebhookMessage, opts) } -func (s *webhookServiceImpl) CreateMessageSlack(webhookID snowflake.Snowflake, webhookToken string, messageCreate discord.Payload, wait bool, threadID snowflake.Snowflake, opts ...RequestOpt) (*discord.Message, error) { +func (s *webhookImpl) CreateMessageSlack(webhookID snowflake.Snowflake, webhookToken string, messageCreate discord.Payload, wait bool, threadID snowflake.Snowflake, opts ...RequestOpt) (*discord.Message, error) { return s.createMessage(webhookID, webhookToken, messageCreate, wait, threadID, route.CreateWebhookMessageSlack, opts) } -func (s *webhookServiceImpl) CreateMessageGitHub(webhookID snowflake.Snowflake, webhookToken string, messageCreate discord.Payload, wait bool, threadID snowflake.Snowflake, opts ...RequestOpt) (*discord.Message, error) { +func (s *webhookImpl) CreateMessageGitHub(webhookID snowflake.Snowflake, webhookToken string, messageCreate discord.Payload, wait bool, threadID snowflake.Snowflake, opts ...RequestOpt) (*discord.Message, error) { return s.createMessage(webhookID, webhookToken, messageCreate, wait, threadID, route.CreateWebhookMessageGitHub, opts) } -func (s *webhookServiceImpl) UpdateMessage(webhookID snowflake.Snowflake, webhookToken string, messageID snowflake.Snowflake, messageUpdate discord.WebhookMessageUpdate, threadID snowflake.Snowflake, opts ...RequestOpt) (message *discord.Message, err error) { +func (s *webhookImpl) UpdateMessage(webhookID snowflake.Snowflake, webhookToken string, messageID snowflake.Snowflake, messageUpdate discord.WebhookMessageUpdate, threadID snowflake.Snowflake, opts ...RequestOpt) (message *discord.Message, err error) { params := route.QueryValues{} if threadID != "" { params["thread_id"] = threadID @@ -180,7 +172,7 @@ func (s *webhookServiceImpl) UpdateMessage(webhookID snowflake.Snowflake, webhoo return } -func (s *webhookServiceImpl) DeleteMessage(webhookID snowflake.Snowflake, webhookToken string, messageID snowflake.Snowflake, threadID snowflake.Snowflake, opts ...RequestOpt) (err error) { +func (s *webhookImpl) DeleteMessage(webhookID snowflake.Snowflake, webhookToken string, messageID snowflake.Snowflake, threadID snowflake.Snowflake, opts ...RequestOpt) (err error) { params := route.QueryValues{} if threadID != "" { params["thread_id"] = threadID diff --git a/gateway/sharding/int_set.go b/sharding/int_set.go similarity index 100% rename from gateway/sharding/int_set.go rename to sharding/int_set.go diff --git a/gateway/sharding/shard_manager.go b/sharding/shard_manager.go similarity index 78% rename from gateway/sharding/shard_manager.go rename to sharding/shard_manager.go index 06761109..c98f1656 100644 --- a/gateway/sharding/shard_manager.go +++ b/sharding/shard_manager.go @@ -3,15 +3,14 @@ package sharding import ( "context" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/disgo/gateway/sharding/srate" - "github.com/DisgoOrg/log" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/disgo/sharding/srate" + "github.com/disgoorg/log" + "github.com/disgoorg/snowflake" ) type ShardManager interface { Logger() log.Logger - Config() Config RateLimiter() srate.Limiter Open(ctx context.Context) diff --git a/sharding/shard_manager_config.go b/sharding/shard_manager_config.go new file mode 100644 index 00000000..1e8e0842 --- /dev/null +++ b/sharding/shard_manager_config.go @@ -0,0 +1,82 @@ +package sharding + +import ( + "github.com/disgoorg/disgo/gateway" + "github.com/disgoorg/disgo/sharding/srate" + "github.com/disgoorg/log" +) + +func DefaultConfig() *Config { + return &Config{ + Logger: log.Default(), + GatewayCreateFunc: gateway.New, + } +} + +type Config struct { + Logger log.Logger + Shards *IntSet + ShardCount int + GatewayCreateFunc gateway.CreateFunc + GatewayConfigOpts []gateway.ConfigOpt + RateLimiter srate.Limiter + RateLimiterConfigOpts []srate.ConfigOpt +} + +type ConfigOpt func(config *Config) + +func (c *Config) Apply(opts []ConfigOpt) { + for _, opt := range opts { + opt(c) + } + if c.RateLimiter == nil { + c.RateLimiter = srate.NewLimiter(c.RateLimiterConfigOpts...) + } +} + +func WithLogger(logger log.Logger) ConfigOpt { + return func(config *Config) { + config.Logger = logger + } +} + +func WithShards(shards ...int) ConfigOpt { + return func(config *Config) { + if config.Shards == nil { + config.Shards = NewIntSet(shards...) + } + for _, shardID := range shards { + config.Shards.Add(shardID) + } + } +} + +func WithShardCount(shardCount int) ConfigOpt { + return func(config *Config) { + config.ShardCount = shardCount + } +} + +func WithGatewayCreateFunc(gatewayCreateFunc gateway.CreateFunc) ConfigOpt { + return func(config *Config) { + config.GatewayCreateFunc = gatewayCreateFunc + } +} + +func WithGatewayConfigOpts(opts ...gateway.ConfigOpt) ConfigOpt { + return func(config *Config) { + config.GatewayConfigOpts = append(config.GatewayConfigOpts, opts...) + } +} + +func WithRateLimiter(rateLimiter srate.Limiter) ConfigOpt { + return func(config *Config) { + config.RateLimiter = rateLimiter + } +} + +func WithRateLimiterConfigOpt(opts ...srate.ConfigOpt) ConfigOpt { + return func(config *Config) { + config.RateLimiterConfigOpts = append(config.RateLimiterConfigOpts, opts...) + } +} diff --git a/gateway/sharding/shard_manager_impl.go b/sharding/shard_manager_impl.go similarity index 68% rename from gateway/sharding/shard_manager_impl.go rename to sharding/shard_manager_impl.go index 916bc6b5..246796b3 100644 --- a/gateway/sharding/shard_manager_impl.go +++ b/sharding/shard_manager_impl.go @@ -5,39 +5,21 @@ import ( "sync" "time" - "github.com/DisgoOrg/disgo/gateway" - "github.com/DisgoOrg/disgo/gateway/sharding/srate" - "github.com/DisgoOrg/log" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/gateway" + srate2 "github.com/disgoorg/disgo/sharding/srate" + "github.com/disgoorg/log" + "github.com/disgoorg/snowflake" ) var _ ShardManager = (*shardManagerImpl)(nil) -func New(token string, gatewayURL string, eventHandlerFunc gateway.EventHandlerFunc, config *Config) ShardManager { - if config.Logger == nil { - config.Logger = log.Default() - } - if config.Shards == nil || config.Shards.Len() == 0 { - config.Shards = NewIntSet(0) - } - if config.ShardCount == 0 { - config.ShardCount = config.Shards.Len() - } - if config.GatewayConfig == nil { - config.GatewayConfig = &gateway.DefaultConfig - } - if config.GatewayCreateFunc == nil { - config.GatewayCreateFunc = func(token string, url string, shardID int, shardCount int, eventHandlerFunc gateway.EventHandlerFunc, config *gateway.Config) gateway.Gateway { - return gateway.New(token, url, shardID, shardCount, eventHandlerFunc, config) - } - } - if config.RateLimiter == nil { - config.RateLimiter = srate.NewLimiter(&srate.DefaultConfig) - } +func New(token string, eventHandlerFunc gateway.EventHandlerFunc, opts ...ConfigOpt) ShardManager { + config := DefaultConfig() + config.Apply(opts) + return &shardManagerImpl{ shards: NewShardsMap(), token: token, - gatewayURL: gatewayURL, eventHandlerFunc: eventHandlerFunc, config: *config, } @@ -47,7 +29,6 @@ type shardManagerImpl struct { shards *ShardsMap token string - gatewayURL string eventHandlerFunc gateway.EventHandlerFunc config Config } @@ -56,11 +37,7 @@ func (m *shardManagerImpl) Logger() log.Logger { return m.config.Logger } -func (m *shardManagerImpl) Config() Config { - return m.config -} - -func (m *shardManagerImpl) RateLimiter() srate.Limiter { +func (m *shardManagerImpl) RateLimiter() srate2.Limiter { return m.config.RateLimiter } @@ -83,7 +60,7 @@ func (m *shardManagerImpl) Open(ctx context.Context) { return } - shard := m.config.GatewayCreateFunc(m.token, m.gatewayURL, shardID, m.config.ShardCount, m.eventHandlerFunc, m.config.GatewayConfig) + shard := m.config.GatewayCreateFunc(m.token, m.eventHandlerFunc, append(m.config.GatewayConfigOpts, gateway.WithShardID(shardID), gateway.WithShardCount(m.config.ShardCount))...) m.shards.Set(shardID, shard) if err := shard.Open(ctx); err != nil { m.Logger().Errorf("failed to open shard %d: %s", shardID, err) @@ -131,7 +108,7 @@ func (m *shardManagerImpl) Close(ctx context.Context) { func (m *shardManagerImpl) OpenShard(ctx context.Context, shardID int) error { m.Logger().Infof("opening shard %d...", shardID) - shard := m.config.GatewayCreateFunc(m.token, m.gatewayURL, shardID, m.config.ShardCount, m.eventHandlerFunc, m.config.GatewayConfig) + shard := m.config.GatewayCreateFunc(m.token, m.eventHandlerFunc, append(m.config.GatewayConfigOpts, gateway.WithShardID(shardID), gateway.WithShardCount(m.config.ShardCount))...) m.config.Shards.Add(shardID) m.shards.Set(shardID, shard) return shard.Open(ctx) diff --git a/gateway/sharding/shards_map.go b/sharding/shards_map.go similarity index 96% rename from gateway/sharding/shards_map.go rename to sharding/shards_map.go index 14352f53..edb110b1 100644 --- a/gateway/sharding/shards_map.go +++ b/sharding/shards_map.go @@ -3,7 +3,7 @@ package sharding import ( "sync" - "github.com/DisgoOrg/disgo/gateway" + "github.com/disgoorg/disgo/gateway" ) func NewShardsMap() *ShardsMap { diff --git a/gateway/sharding/srate/shard_rate_limiter.go b/sharding/srate/shard_rate_limiter.go similarity index 87% rename from gateway/sharding/srate/shard_rate_limiter.go rename to sharding/srate/shard_rate_limiter.go index 16c79c66..7fa79c41 100644 --- a/gateway/sharding/srate/shard_rate_limiter.go +++ b/sharding/srate/shard_rate_limiter.go @@ -3,13 +3,13 @@ package srate import ( "context" - "github.com/DisgoOrg/log" + "github.com/disgoorg/log" ) type Limiter interface { Logger() log.Logger Close(ctx context.Context) - Config() Config + WaitBucket(ctx context.Context, shardID int) error UnlockBucket(shardID int) } diff --git a/gateway/sharding/srate/shard_rate_limiter_config.go b/sharding/srate/shard_rate_limiter_config.go similarity index 72% rename from gateway/sharding/srate/shard_rate_limiter_config.go rename to sharding/srate/shard_rate_limiter_config.go index 76b9fbef..4c3f1848 100644 --- a/gateway/sharding/srate/shard_rate_limiter_config.go +++ b/sharding/srate/shard_rate_limiter_config.go @@ -1,12 +1,15 @@ package srate import ( - "github.com/DisgoOrg/log" + "github.com/disgoorg/log" ) -var DefaultConfig = Config{ - MaxConcurrency: 1, - StartupDelay: 5, +func DefaultConfig() *Config { + return &Config{ + Logger: log.Default(), + MaxConcurrency: 1, + StartupDelay: 5, + } } type Config struct { @@ -23,21 +26,18 @@ func (c *Config) Apply(opts []ConfigOpt) { } } -//goland:noinspection GoUnusedExportedFunction func WithLogger(logger log.Logger) ConfigOpt { return func(config *Config) { config.Logger = logger } } -//goland:noinspection GoUnusedExportedFunction func WithMaxConcurrency(maxConcurrency int) ConfigOpt { return func(config *Config) { config.MaxConcurrency = maxConcurrency } } -//goland:noinspection GoUnusedExportedFunction func WithStartupDelay(startupDelay int) ConfigOpt { return func(config *Config) { config.StartupDelay = startupDelay diff --git a/gateway/sharding/srate/shard_rate_limiter_impl.go b/sharding/srate/shard_rate_limiter_impl.go similarity index 86% rename from gateway/sharding/srate/shard_rate_limiter_impl.go rename to sharding/srate/shard_rate_limiter_impl.go index c863a779..2c59a9cf 100644 --- a/gateway/sharding/srate/shard_rate_limiter_impl.go +++ b/sharding/srate/shard_rate_limiter_impl.go @@ -5,22 +5,16 @@ import ( "sync" "time" - "github.com/DisgoOrg/log" + "github.com/disgoorg/log" "github.com/sasha-s/go-csync" ) var _ Limiter = (*limiterImpl)(nil) -func NewLimiter(config *Config) Limiter { - if config == nil { - config = &DefaultConfig - } - if config.Logger == nil { - config.Logger = log.Default() - } - if config.StartupDelay == 0 { - config.StartupDelay = 5 - } +func NewLimiter(opts ...ConfigOpt) Limiter { + config := DefaultConfig() + config.Apply(opts) + return &limiterImpl{ buckets: map[int]*bucket{}, config: *config, @@ -55,10 +49,6 @@ func (r *limiterImpl) Close(ctx context.Context) { } } -func (r *limiterImpl) Config() Config { - return r.config -} - func (r *limiterImpl) getBucket(shardID int, create bool) *bucket { r.Logger().Debug("locking shard srate limiter") r.Lock() diff --git a/webhook/README.md b/webhook/README.md index 4cfd9374..30266191 100644 --- a/webhook/README.md +++ b/webhook/README.md @@ -1,13 +1,13 @@ # webhook -[Webhook](https://discord.com/developers/docs/resources/webhook) module of [disgo](https://github.com/DisgoOrg/disgo) +[Webhook](https://discord.com/developers/docs/resources/webhook) module of [disgo](https://github.com/disgoorg/disgo) ### Usage Import the package into your project. ```go -import "github.com/DisgoOrg/disgo/webhook" +import "github.com/disgoorg/disgo/webhook" ``` Create a new Webhook by `webhook_id` and `webhook_token`. (*This WebhookClient should be created once as it holds important state*) @@ -81,4 +81,4 @@ err := client.DeleteMessage("message_id") ### Full Example -a full example can be found [here](https://github.com/DisgoOrg/disgo/tree/development/_examples/webhook/example.go) \ No newline at end of file +a full example can be found [here](https://github.com/disgoorg/disgo/tree/development/_examples/webhook/example.go) \ No newline at end of file diff --git a/webhook/webhook.go b/webhook/webhook.go deleted file mode 100644 index 7decceee..00000000 --- a/webhook/webhook.go +++ /dev/null @@ -1,22 +0,0 @@ -package webhook - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" -) - -// Webhook can be used to update or delete the Webhook -type Webhook struct { - discord.IncomingWebhook - WebhookClient *Client -} - -// Update is used to update the Webhook -func (h *Webhook) Update(webhookUpdate discord.WebhookUpdateWithToken, opts ...rest.RequestOpt) (*Webhook, error) { - return h.WebhookClient.UpdateWebhook(webhookUpdate, opts...) -} - -// Delete is used to delete the Webhook -func (h *Webhook) Delete(opts ...rest.RequestOpt) error { - return h.WebhookClient.DeleteWebhook(opts...) -} diff --git a/webhook/webhook_client.go b/webhook/webhook_client.go index dbc3db7b..465bdd94 100644 --- a/webhook/webhook_client.go +++ b/webhook/webhook_client.go @@ -3,141 +3,50 @@ package webhook import ( "context" - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/disgo/rest/route" - "github.com/DisgoOrg/log" - "github.com/DisgoOrg/snowflake" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest" + "github.com/disgoorg/snowflake" ) -// NewClient returns a new Client -//goland:noinspection GoUnusedExportedFunction -func NewClient(id snowflake.Snowflake, token string, opts ...ConfigOpt) *Client { - config := &DefaultConfig - config.Apply(opts) - - if config.Logger == nil { - config.Logger = log.Default() - } - - if config.WebhookService == nil { - if config.RestClient == nil { - config.RestClient = rest.NewClient(config.RestClientConfig) - } - config.WebhookService = rest.NewWebhookService(config.RestClient) - } - if config.DefaultAllowedMentions == nil { - config.DefaultAllowedMentions = &discord.DefaultAllowedMentions - } - - webhookClient := &Client{ - ID: id, - Token: token, - } - - if config.EntityBuilder == nil { - config.EntityBuilder = NewEntityBuilder(webhookClient) - } - - webhookClient.Config = *config - return webhookClient -} - -// Client is used to interact with the discord webhook api -type Client struct { - ID snowflake.Snowflake - Token string - Config -} - -// GetWebhook fetches the current webhook from discord -func (h *Client) GetWebhook(opts ...rest.RequestOpt) (*Webhook, error) { - webhook, err := h.WebhookService.GetWebhookWithToken(h.ID, h.Token, opts...) - if err != nil { - return nil, err - } - return h.EntityBuilder.CreateWebhook(webhook), nil -} - -// UpdateWebhook updates the current webhook -func (h *Client) UpdateWebhook(webhookUpdate discord.WebhookUpdateWithToken, opts ...rest.RequestOpt) (*Webhook, error) { - webhook, err := h.WebhookService.UpdateWebhookWithToken(h.ID, h.Token, webhookUpdate, opts...) - if err != nil { - return nil, err - } - return h.EntityBuilder.CreateWebhook(webhook), nil -} - -// DeleteWebhook deletes the current webhook -func (h *Client) DeleteWebhook(opts ...rest.RequestOpt) error { - return h.WebhookService.DeleteWebhookWithToken(h.ID, h.Token, opts...) -} - -// CreateMessageInThread creates a new Message in the provided thread -func (h *Client) CreateMessageInThread(messageCreate discord.WebhookMessageCreate, threadID snowflake.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - message, err := h.WebhookService.CreateMessage(h.ID, h.Token, messageCreate, true, threadID, opts...) - if err != nil { - return nil, err - } - return h.EntityBuilder.CreateMessage(*message), nil -} - -// CreateMessage creates a new message from the discord.WebhookMessageCreate -func (h *Client) CreateMessage(messageCreate discord.WebhookMessageCreate, opts ...rest.RequestOpt) (*Message, error) { - return h.CreateMessageInThread(messageCreate, "", opts...) -} - -// CreateContent creates a new message from the provided content -func (h *Client) CreateContent(content string, opts ...rest.RequestOpt) (*Message, error) { - return h.CreateMessage(discord.WebhookMessageCreate{Content: content}, opts...) -} - -// CreateEmbeds creates a new message from the provided embeds -func (h *Client) CreateEmbeds(embeds []discord.Embed, opts ...rest.RequestOpt) (*Message, error) { - return h.CreateMessage(discord.WebhookMessageCreate{Embeds: embeds}, opts...) -} - -// UpdateMessage updates an already sent webhook message with the discord.WebhookMessageUpdate -func (h *Client) UpdateMessage(messageID snowflake.Snowflake, messageUpdate discord.WebhookMessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return h.UpdateMessageInThread(messageID, messageUpdate, "", opts...) -} - -// UpdateMessageInThread updates an already sent webhook message with the discord.WebhookMessageUpdate in a thread -func (h *Client) UpdateMessageInThread(messageID snowflake.Snowflake, messageUpdate discord.WebhookMessageUpdate, threadID snowflake.Snowflake, opts ...rest.RequestOpt) (*Message, error) { - message, err := h.WebhookService.UpdateMessage(h.ID, h.Token, messageID, messageUpdate, threadID, opts...) - if err != nil { - return nil, err - } - return h.EntityBuilder.CreateMessage(*message), nil -} - -// UpdateContent updates an already sent webhook message with the content -func (h *Client) UpdateContent(messageID snowflake.Snowflake, content string, opts ...rest.RequestOpt) (*Message, error) { - return h.UpdateMessage(messageID, discord.WebhookMessageUpdate{Content: &content}, opts...) -} - -// UpdateEmbeds updates an already sent webhook message with the embeds -func (h *Client) UpdateEmbeds(messageID snowflake.Snowflake, embeds []discord.Embed, opts ...rest.RequestOpt) (*Message, error) { - return h.UpdateMessage(messageID, discord.WebhookMessageUpdate{Embeds: &embeds}, opts...) -} - -// DeleteMessage deletes an already sent webhook message -func (h *Client) DeleteMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return h.DeleteMessageInThread(messageID, "", opts...) -} - -// DeleteMessageInThread deletes an already sent webhook message in a thread -func (h *Client) DeleteMessageInThread(messageID snowflake.Snowflake, threadID snowflake.Snowflake, opts ...rest.RequestOpt) error { - return h.WebhookService.DeleteMessage(h.ID, h.Token, messageID, threadID, opts...) -} - -// URL returns the full webhook URL -func (h *Client) URL() string { - compiledRoute, _ := route.GetWebhook.Compile(nil, h.ID, h.Token) - return compiledRoute.URL() -} - -// Close closes all connections the webhook client has open -func (h *Client) Close(ctx context.Context) { - h.RestClient.Close(ctx) +type Client interface { + // ID returns the configured Webhook id + ID() snowflake.Snowflake + // Token returns the configured Webhook token + Token() string + // URL returns the full Webhook URL + URL() string + // Close closes all connections the Webhook Client has open + Close(ctx context.Context) + // Rest returns the underlying rest.Webhooks + Rest() rest.Webhooks + + // GetWebhook fetches the current Webhook from discord + GetWebhook(opts ...rest.RequestOpt) (*discord.IncomingWebhook, error) + // UpdateWebhook updates the current Webhook + UpdateWebhook(webhookUpdate discord.WebhookUpdateWithToken, opts ...rest.RequestOpt) (*discord.IncomingWebhook, error) + // DeleteWebhook deletes the current Webhook + DeleteWebhook(opts ...rest.RequestOpt) error + + // CreateMessage creates a new Message from the discord.WebhookMessageCreate + CreateMessage(messageCreate discord.WebhookMessageCreate, opts ...rest.RequestOpt) (*discord.Message, error) + // CreateMessageInThread creates a new Message from the discord.WebhookMessageCreate in the provided thread + CreateMessageInThread(messageCreate discord.WebhookMessageCreate, threadID snowflake.Snowflake, opts ...rest.RequestOpt) (*discord.Message, error) + // CreateContent creates a new Message from the provided content + CreateContent(content string, opts ...rest.RequestOpt) (*discord.Message, error) + // CreateEmbeds creates a new Message from the provided discord.Embed(s) + CreateEmbeds(embeds []discord.Embed, opts ...rest.RequestOpt) (*discord.Message, error) + + // UpdateMessage updates an already sent Webhook Message with the discord.WebhookMessageUpdate + UpdateMessage(messageID snowflake.Snowflake, messageUpdate discord.WebhookMessageUpdate, opts ...rest.RequestOpt) (*discord.Message, error) + // UpdateMessageInThread updates an already sent Webhook Message with the discord.WebhookMessageUpdate in the provided thread + UpdateMessageInThread(messageID snowflake.Snowflake, messageUpdate discord.WebhookMessageUpdate, threadID snowflake.Snowflake, opts ...rest.RequestOpt) (*discord.Message, error) + // UpdateContent updates an already sent Webhook Message with the content + UpdateContent(messageID snowflake.Snowflake, content string, opts ...rest.RequestOpt) (*discord.Message, error) + // UpdateEmbeds updates an already sent Webhook Message with the discord.Embed(s) + UpdateEmbeds(messageID snowflake.Snowflake, embeds []discord.Embed, opts ...rest.RequestOpt) (*discord.Message, error) + + // DeleteMessage deletes an already sent Webhook Message + DeleteMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error + // DeleteMessageInThread deletes an already sent Webhook Message in the provided thread + DeleteMessageInThread(messageID snowflake.Snowflake, threadID snowflake.Snowflake, opts ...rest.RequestOpt) error } diff --git a/webhook/webhook_client_impl.go b/webhook/webhook_client_impl.go new file mode 100644 index 00000000..42dd36f4 --- /dev/null +++ b/webhook/webhook_client_impl.go @@ -0,0 +1,125 @@ +package webhook + +import ( + "context" + + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest" + "github.com/disgoorg/disgo/rest/route" + "github.com/disgoorg/snowflake" +) + +// NewClient returns a new Client +func NewClient(id snowflake.Snowflake, token string, opts ...ConfigOpt) Client { + config := DefaultConfig() + config.Apply(opts) + + return &ClientImpl{ + id: id, + token: token, + config: *config, + } +} + +// ClientImpl is used to interact with the discord webhook api +type ClientImpl struct { + id snowflake.Snowflake + token string + config Config +} + +func (c *ClientImpl) ID() snowflake.Snowflake { + return c.id +} + +func (c *ClientImpl) Token() string { + return c.token +} + +// URL returns the full webhook URL +func (c *ClientImpl) URL() string { + compiledRoute, _ := route.GetWebhook.Compile(nil, c.ID, c.Token) + return compiledRoute.URL() +} + +// Close closes all connections the webhook client has open +func (c *ClientImpl) Close(ctx context.Context) { + c.config.RestClient.Close(ctx) +} + +func (c *ClientImpl) Rest() rest.Webhooks { + return c.config.Webhooks +} + +// GetWebhook fetches the current webhook from discord +func (c *ClientImpl) GetWebhook(opts ...rest.RequestOpt) (*discord.IncomingWebhook, error) { + webhook, err := c.Rest().GetWebhookWithToken(c.id, c.token, opts...) + if incomingWebhook, ok := webhook.(discord.IncomingWebhook); ok && err == nil { + return &incomingWebhook, nil + } + return nil, err +} + +// UpdateWebhook updates the current webhook +func (c *ClientImpl) UpdateWebhook(webhookUpdate discord.WebhookUpdateWithToken, opts ...rest.RequestOpt) (*discord.IncomingWebhook, error) { + webhook, err := c.Rest().UpdateWebhookWithToken(c.id, c.token, webhookUpdate, opts...) + if incomingWebhook, ok := webhook.(discord.IncomingWebhook); ok && err == nil { + return &incomingWebhook, nil + } + return nil, err +} + +// DeleteWebhook deletes the current webhook +func (c *ClientImpl) DeleteWebhook(opts ...rest.RequestOpt) error { + return c.Rest().DeleteWebhookWithToken(c.id, c.token, opts...) +} + +// CreateMessageInThread creates a new Message in the provided thread +func (c *ClientImpl) CreateMessageInThread(messageCreate discord.WebhookMessageCreate, threadID snowflake.Snowflake, opts ...rest.RequestOpt) (*discord.Message, error) { + return c.Rest().CreateMessage(c.id, c.token, messageCreate, true, threadID, opts...) +} + +// CreateMessage creates a new message from the discord.WebhookMessageCreate +func (c *ClientImpl) CreateMessage(messageCreate discord.WebhookMessageCreate, opts ...rest.RequestOpt) (*discord.Message, error) { + return c.CreateMessageInThread(messageCreate, "", opts...) +} + +// CreateContent creates a new message from the provided content +func (c *ClientImpl) CreateContent(content string, opts ...rest.RequestOpt) (*discord.Message, error) { + return c.CreateMessage(discord.WebhookMessageCreate{Content: content}, opts...) +} + +// CreateEmbeds creates a new message from the provided embeds +func (c *ClientImpl) CreateEmbeds(embeds []discord.Embed, opts ...rest.RequestOpt) (*discord.Message, error) { + return c.CreateMessage(discord.WebhookMessageCreate{Embeds: embeds}, opts...) +} + +// UpdateMessage updates an already sent webhook message with the discord.WebhookMessageUpdate +func (c *ClientImpl) UpdateMessage(messageID snowflake.Snowflake, messageUpdate discord.WebhookMessageUpdate, opts ...rest.RequestOpt) (*discord.Message, error) { + return c.UpdateMessageInThread(messageID, messageUpdate, "", opts...) +} + +// UpdateMessageInThread updates an already sent webhook message with the discord.WebhookMessageUpdate in a thread +func (c *ClientImpl) UpdateMessageInThread(messageID snowflake.Snowflake, messageUpdate discord.WebhookMessageUpdate, threadID snowflake.Snowflake, opts ...rest.RequestOpt) (*discord.Message, error) { + return c.Rest().UpdateMessage(c.id, c.token, messageID, messageUpdate, threadID, opts...) +} + +// UpdateContent updates an already sent webhook message with the content +func (c *ClientImpl) UpdateContent(messageID snowflake.Snowflake, content string, opts ...rest.RequestOpt) (*discord.Message, error) { + return c.UpdateMessage(messageID, discord.WebhookMessageUpdate{Content: &content}, opts...) +} + +// UpdateEmbeds updates an already sent webhook message with the embeds +func (c *ClientImpl) UpdateEmbeds(messageID snowflake.Snowflake, embeds []discord.Embed, opts ...rest.RequestOpt) (*discord.Message, error) { + return c.UpdateMessage(messageID, discord.WebhookMessageUpdate{Embeds: &embeds}, opts...) +} + +// DeleteMessage deletes an already sent webhook message +func (c *ClientImpl) DeleteMessage(messageID snowflake.Snowflake, opts ...rest.RequestOpt) error { + return c.DeleteMessageInThread(messageID, "", opts...) +} + +// DeleteMessageInThread deletes an already sent webhook message in a thread +func (c *ClientImpl) DeleteMessageInThread(messageID snowflake.Snowflake, threadID snowflake.Snowflake, opts ...rest.RequestOpt) error { + return c.Rest().DeleteMessage(c.id, c.token, messageID, threadID, opts...) +} diff --git a/webhook/webhook_config.go b/webhook/webhook_config.go index a3eb9879..58c2ec0b 100644 --- a/webhook/webhook_config.go +++ b/webhook/webhook_config.go @@ -1,25 +1,25 @@ package webhook import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" - "github.com/DisgoOrg/log" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/rest" + "github.com/disgoorg/log" ) // DefaultConfig is the default configuration for the webhook client -//goland:noinspection GoUnusedGlobalVariable -var DefaultConfig = Config{ - RestClientConfig: &rest.DefaultConfig, - DefaultAllowedMentions: &discord.DefaultAllowedMentions, +func DefaultConfig() *Config { + return &Config{ + Logger: log.Default(), + DefaultAllowedMentions: &discord.DefaultAllowedMentions, + } } // Config is the configuration for the webhook client type Config struct { Logger log.Logger RestClient rest.Client - RestClientConfig *rest.Config - WebhookService rest.WebhookService - EntityBuilder EntityBuilder + RestClientConfigOpts []rest.ConfigOpt + Webhooks rest.Webhooks DefaultAllowedMentions *discord.AllowedMentions } @@ -31,10 +31,15 @@ func (c *Config) Apply(opts []ConfigOpt) { for _, opt := range opts { opt(c) } + if c.RestClient == nil { + c.RestClient = rest.NewClient("", c.RestClientConfigOpts...) + } + if c.Webhooks == nil { + c.Webhooks = rest.NewWebhooks(c.RestClient) + } } // WithLogger sets the logger for the webhook client -//goland:noinspection GoUnusedExportedFunction func WithLogger(logger log.Logger) ConfigOpt { return func(config *Config) { config.Logger = logger @@ -42,50 +47,27 @@ func WithLogger(logger log.Logger) ConfigOpt { } // WithRestClient sets the rest client for the webhook client -//goland:noinspection GoUnusedExportedFunction func WithRestClient(restClient rest.Client) ConfigOpt { return func(config *Config) { config.RestClient = restClient } } -// WithRestClientConfig sets the rest client configuration for the webhook client -//goland:noinspection GoUnusedExportedFunction -func WithRestClientConfig(restConfig rest.Config) ConfigOpt { - return func(config *Config) { - config.RestClientConfig = &restConfig - } -} - // WithRestClientConfigOpts sets the rest client configuration for the webhook client -//goland:noinspection GoUnusedExportedFunction func WithRestClientConfigOpts(opts ...rest.ConfigOpt) ConfigOpt { return func(config *Config) { - if config.RestClientConfig == nil { - config.RestClientConfig = &rest.DefaultConfig - } - config.RestClientConfig.Apply(opts) - } -} - -// WithWebhookService sets the webhook service for the webhook client -//goland:noinspection GoUnusedExportedFunction -func WithWebhookService(webhookService rest.WebhookService) ConfigOpt { - return func(config *Config) { - config.WebhookService = webhookService + config.RestClientConfigOpts = append(config.RestClientConfigOpts, opts...) } } -// WithEntityBuilder sets the entity builder for the webhook client -//goland:noinspection GoUnusedExportedFunction -func WithEntityBuilder(entityBuilder EntityBuilder) ConfigOpt { +// WithWebhooks sets the webhook service for the webhook client +func WithWebhooks(webhooks rest.Webhooks) ConfigOpt { return func(config *Config) { - config.EntityBuilder = entityBuilder + config.Webhooks = webhooks } } // WithDefaultAllowedMentions sets the default allowed mentions for the webhook client -//goland:noinspection GoUnusedExportedFunction func WithDefaultAllowedMentions(allowedMentions discord.AllowedMentions) ConfigOpt { return func(config *Config) { config.DefaultAllowedMentions = &allowedMentions diff --git a/webhook/webhook_entity_builder.go b/webhook/webhook_entity_builder.go deleted file mode 100644 index 8be17667..00000000 --- a/webhook/webhook_entity_builder.go +++ /dev/null @@ -1,52 +0,0 @@ -package webhook - -import ( - "fmt" - - "github.com/DisgoOrg/disgo/discord" -) - -// EntityBuilder is used to transform discord package entities into webhook package entities which hold a reference to the webhook client -type EntityBuilder interface { - // WebhookClient returns the underlying webhook client used by this EntityBuilder - WebhookClient() *Client - - // CreateMessage returns a new webhook.Message from the discord.Message - - CreateMessage(message discord.Message) *Message - - // CreateWebhook returns a new webhook.Webhook from the discord.Webhook - CreateWebhook(webhook discord.Webhook) *Webhook -} - -// NewEntityBuilder returns a new default EntityBuilder -func NewEntityBuilder(webhookClient *Client) EntityBuilder { - return &entityBuilderImpl{ - webhookClient: webhookClient, - } -} - -type entityBuilderImpl struct { - webhookClient *Client -} - -func (b *entityBuilderImpl) WebhookClient() *Client { - return b.webhookClient -} - -func (b *entityBuilderImpl) CreateMessage(message discord.Message) *Message { - return &Message{ - Message: message, - WebhookClient: b.WebhookClient(), - } -} - -func (b *entityBuilderImpl) CreateWebhook(webhook discord.Webhook) *Webhook { - if w, ok := webhook.(discord.IncomingWebhook); ok { - return &Webhook{ - IncomingWebhook: w, - WebhookClient: b.WebhookClient(), - } - } - panic(fmt.Sprintf("invalid webhook type %d received", webhook.Type())) -} diff --git a/webhook/webhook_message.go b/webhook/webhook_message.go deleted file mode 100644 index 650d9104..00000000 --- a/webhook/webhook_message.go +++ /dev/null @@ -1,106 +0,0 @@ -package webhook - -import ( - "github.com/DisgoOrg/disgo/discord" - "github.com/DisgoOrg/disgo/rest" -) - -// Message represents a discord.Message which can be directly edited by the Client -type Message struct { - discord.Message - WebhookClient *Client -} - -// Update allows you to edit an existing Message sent by you -func (m *Message) Update(messageUpdate discord.WebhookMessageUpdate, opts ...rest.RequestOpt) (*Message, error) { - return m.WebhookClient.UpdateMessage(m.ID, messageUpdate, opts...) -} - -// Delete allows you to edit an existing Message sent by you -func (m *Message) Delete(opts ...rest.RequestOpt) error { - return m.WebhookClient.DeleteMessage(m.ID, opts...) -} - -// ActionRows returns all discord.ActionRowComponent(s) from this Message -func (m *Message) ActionRows() []discord.ActionRowComponent { - var actionRows []discord.ActionRowComponent - for i := range m.Components { - if actionRow, ok := m.Components[i].(discord.ActionRowComponent); ok { - actionRows = append(actionRows, actionRow) - } - } - return actionRows -} - -// InteractiveComponents returns the discord.InteractiveComponent(s) from this Message -func (m *Message) InteractiveComponents() []discord.InteractiveComponent { - var interactiveComponents []discord.InteractiveComponent - for i := range m.Components { - for ii := range m.Components[i].Components() { - interactiveComponents = append(interactiveComponents, m.Components[i].Components()[ii]) - } - } - return interactiveComponents -} - -// ComponentByID returns the discord.Component with the specific discord.CustomID -func (m *Message) ComponentByID(customID discord.CustomID) discord.InteractiveComponent { - for i := range m.Components { - for ii := range m.Components[i].Components() { - if m.Components[i].Components()[ii].ID() == customID { - return m.Components[i].Components()[ii] - } - } - } - return nil -} - -// Buttons returns all ButtonComponent(s) from this Message -func (m *Message) Buttons() []discord.ButtonComponent { - var buttons []discord.ButtonComponent - for i := range m.Components { - for ii := range m.Components[i].Components() { - if button, ok := m.Components[i].Components()[ii].(discord.ButtonComponent); ok { - buttons = append(buttons, button) - } - } - } - return buttons -} - -// ButtonByID returns a ButtonComponent with the specific customID from this Message -func (m *Message) ButtonByID(customID discord.CustomID) *discord.ButtonComponent { - for i := range m.Components { - for ii := range m.Components[i].Components() { - if button, ok := m.Components[i].Components()[ii].(*discord.ButtonComponent); ok && button.ID() == customID { - return button - } - } - } - return nil -} - -// SelectMenus returns all SelectMenuComponent(s) from this Message -func (m *Message) SelectMenus() []discord.SelectMenuComponent { - var selectMenus []discord.SelectMenuComponent - for i := range m.Components { - for ii := range m.Components[i].Components() { - if button, ok := m.Components[i].Components()[ii].(discord.SelectMenuComponent); ok { - selectMenus = append(selectMenus, button) - } - } - } - return selectMenus -} - -// SelectMenuByID returns a SelectMenuComponent with the specific customID from this Message -func (m *Message) SelectMenuByID(customID discord.CustomID) *discord.SelectMenuComponent { - for i := range m.Components { - for ii := range m.Components[i].Components() { - if button, ok := m.Components[i].Components()[ii].(*discord.SelectMenuComponent); ok && button.ID() == customID { - return button - } - } - } - return nil -}