HiLleywyn /
Carlos
A feature-rich, security-hardened Discord moderation bot written in 100% pure Go using the GoDiscord framework. Zero external dependencies.
8/100 healthLoading repository data…
streame-gg / repository
Feature rich Discord API wrapper made in Golang
A transparent discovery signal based on current public GitHub metadata.
This score does not audit code, security, maintainers, documentation quality, or suitability. Verify the repository and its current documentation before adoption.
A Go library for the Discord gateway and REST API.
Also see Features in the documentation: docs/README.md.
v1.0 — first stable release. The public API is frozen and follows semantic versioning: no breaking changes within the v1 line. That said, this is a young library — expect to hit bugs in less-travelled corners. Please open an issue when you do; reports against v1.0 are very welcome.
The original foundation of this library was written by hand. Most of the surface area beyond that — the breadth of REST endpoints, event handling, and supporting code — was built with substantial AI assistance and has not yet been reviewed line-by-line by a human. Correctness is instead guarded by an extensive automated test suite (see COVERAGE.md); the tests, not a manual read-through, are the primary correctness guarantee today. We're being upfront about this so you can weigh it for your use case. Human review is ongoing, and — as above — bug reports are the fastest way to harden the library.
go get github.com/streame-gg/go-discord-wrapper
Requires Go 1.26 or later.
package main
import (
"context"
"log/slog"
"os"
"os/signal"
"syscall"
"github.com/streame-gg/go-discord-wrapper/connection"
"github.com/streame-gg/go-discord-wrapper/types/discord"
"github.com/streame-gg/go-discord-wrapper/types/events"
"github.com/streame-gg/go-discord-wrapper/types/interactions/responses"
)
func main() {
bot, err := connection.NewClient(os.Getenv("DISCORD_TOKEN"), discord.IntentGuilds|discord.IntentGuildMessages)
if err != nil {
slog.Error("failed to create client", "err", err)
os.Exit(1)
}
bot.OnMessageCreate(func(c *connection.Client, e *events.MessageCreateEvent) {
if e.Author == nil {
return
}
slog.Info("new message", "author", e.Author.Username, "content", e.Content)
})
bot.OnEvent(events.EventInteractionCreate, func(c *connection.Client, e *events.InteractionCreateEvent) {
if e.IsCommand() && e.GetFullCommand() == "ping" {
_, _ = c.Reply(context.Background(), &e.Interaction, &responses.InteractionResponseDataDefault{
Content: "Pong!",
}, false)
}
})
if err := bot.Login(context.Background()); err != nil {
slog.Error("login failed", "err", err)
os.Exit(1)
}
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
<-ctx.Done()
_ = bot.Shutdown()
}
Most cache and listing operations return a *collection.Collection[K, V] —
a map with insertion order, plus 30+ utility methods inspired by
@discordjs/collection.
import "github.com/streame-gg/go-discord-wrapper/collection"
users := bot.Cache.Users().All() // returns *Collection[Snowflake, *User]
count := users.Len()
admin, ok := users.Get(adminID)
humanCount := users.Filter(func(u *discord.User) bool { return !u.Bot }).Len()
bots, humans := users.Partition(func(u *discord.User) bool { return u.Bot })
recent := messages.Filter(func(m *discord.Message) bool {
return time.Since(m.Created()) < time.Hour
})
oldest, _ := messages.Sorted(func(a, b *discord.Message) bool {
return a.Created().Before(b.Created())
}).First()
// Method-based: returns a new Collection
sorted := users.Sorted(func(a, b *discord.User) bool {
return a.Username < b.Username
})
// Top-level: transforms to a different value-type
names := collection.Map(users, func(u *discord.User) string {
return u.Username
})
// names is []string
// Iterate (Go 1.23+ range-over-func)
for id, user := range users.All() {
fmt.Printf("%s -> %s\n", id, user.Username)
}
Full API: see godoc.
Pass a cache to NewClient and the gateway will populate it automatically:
import "github.com/streame-gg/go-discord-wrapper/cache"
mc := cache.NewMemoryCache(cache.Options{
TTL: 30 * time.Minute,
SweepInterval: 5 * time.Minute,
Limits: cache.Limits{
MaxMessages: 10_000,
MaxUsers: 5_000,
},
Messages: cache.MessageOptions{
MaxPerChannel: 200,
},
})
bot, err := connection.NewClient(token, intents, options.WithCache(mc))
Look up entities without hitting the REST API:
if ch, ok := bot.Cache.Channels().Get(channelID); ok {
fmt.Println(ch.Name)
}
| Backend | Import |
|---|---|
| In-process memory (default) | cache.NewMemoryCache(...) |
| Redis | cache/rediscache package |
| MongoDB | cache/mongocache package |
// Shard 0 of 4 total shards.
bot, err := connection.NewClient(token, intents, options.WithSharding(4, 0))
_, err := bot.BulkRegisterCommands(ctx, []*commands.ApplicationCommand{
{
Name: "ping",
Description: "Replies with Pong!",
Type: discord.ApplicationCommandTypeChatInput,
},
})
| Option | Description |
|---|---|
options.WithCache(c) | Attach a cache backend |
options.WithSharding(total, shardID) | Enable sharding |
options.WithLogger(l) | Custom *slog.Logger |
options.WithRetry(opts) | Retry policy for REST requests |
options.WithRateLimiting(opts) | Rate-limiter tuning (safety margin, disable) |
options.WithMinRequestInterval(d) | Global minimum delay between REST requests |
options.WithAPIVersion(v) | Discord API version (default: v10) |
options.WithBaseURL(url) | Override the Discord API base URL (useful for mock servers in tests) |
Use WithBaseURL together with Go's net/http/httptest to run integration tests without
hitting Discord:
import (
"net/http/httptest"
"github.com/streame-gg/go-discord-wrapper/api"
"github.com/streame-gg/go-discord-wrapper/options"
)
ts := httptest.NewServer(myHandler)
defer ts.Close()
client, err := api.NewRestClient("test-token",
options.WithBaseURL(ts.URL),
)
Synthetic events are high-level events derived by the wrapper from raw Discord gateway events. They are never sent by Discord directly — the library computes them by diffing state across consecutive gateway payloads.
Synthetic events require the cache to be enabled (via options.WithCache). When the cache
is cold (no prior state), the event is silently skipped rather than firing with incomplete data.
mc := cache.NewMemoryCache(cache.Options{})
bot, err := connection.NewClient(token, intents, options.WithCache(mc))
// Fires once per emoji added to a guild.
bot.OnGuildEmojiAdd(func(c *connection.Client, ev *events.GuildEmojiAddEvent) {
fmt.Printf("emoji %s added to guild %s\n", ev.Emoji.Name, ev.GuildID)
})
// Fires once per sticker removed from a guild.
bot.OnGuildStickerRemove(func(c *connection.Client, ev *events.GuildStickerRemoveEvent) {
fmt.Printf("sticker %s removed from guild %s\n", ev.Sticker.Name, ev.GuildID)
})
GUILD_EMOJIS_UPDATE, cache required)| Helper | Struct | Fires when |
|---|---|---|
OnGuildEmojiAdd | GuildEmojiAddEvent | An emoji is created in a guild |
OnGuildEmojiRemove | GuildEmojiRemoveEvent | An emoji is deleted from a guild |
OnGuildEmojiUpdate | GuildEmojiUpdateEvent | An emoji's name, roles, or availability changes |
GUILD_STICKERS_UPDATE, cache required)| Helper | Struct | Fires when |
|---|---|---|
OnGuildStickerAdd | GuildStickerAddEvent | A sticker is created in a guild |
OnGuildStickerRemove | GuildStickerRemoveEvent | A sticker is deleted from a guild |
OnGuildStickerUpdate | GuildStickerUpdateEvent | A sticker's name, tags, or availability changes |
| Event | Constant |
|---|---|
| Ready | events.EventReady |
| Resumed | events.EventResumed |
| Application Command Permissions Update | events.EventApplicationCommandPermissionsUpdate |
| Auto Moderation Rule Create | events.EventAutoModerationRuleCreate |
| Auto Moderation Rule Update | events.EventAutoModerationRuleUpdate |
| Auto Moderation Rule Delete | events.EventAutoModerationRuleDelete |
| Auto Moderation Action Execution | events.EventAutoModerationActionExecution |
| Channel Create | events.EventChannelCreate |
| Channel Update | events.EventChannelUpdate |
| Channel Delete | events.EventChannelDelete |
| Channel Pins Update | events.EventChannelPinsUpdate |
| Thread Create | events.EventThreadCreate |
| Thread Update | events.EventThreadUpdate |
| Thread Delete | events.EventThreadDelete |
| Thread List Sync | events.EventThreadListSync |
| Thread Member Update | events.EventThreadMemberUpdate |
| Thread Members Update | events.EventThreadMembersUpdate |
| Entitlement Create | events.EventEntitlementCreate |
| Entitlement Update | events.EventEntitlementUpdate |
| Entitlement Delete | events.EventEntitlementDelete |
| Guild Create | events.EventGuildCreate |
| Guild Update | events.EventGuildUpdate |
| Guild Delete | events.EventGuildDelete |
| Guild Audit Log Entry Create | events.EventGuildAuditLogEntryCreate |
Selected from shared topics, language and repository description—not editorial ratings.
HiLleywyn /
A feature-rich, security-hardened Discord moderation bot written in 100% pure Go using the GoDiscord framework. Zero external dependencies.
8/100 health| Guild Ban Add |
events.EventGuildBanAdd |
| Guild Ban Remove | events.EventGuildBanRemove |
| Guild Emojis Update | events.EventGuildEmojisUpdate |
| Guild Stickers Update | events.EventGuildStickersUpdate |
| Guild Integrations Update | events.EventGuildIntegrationsUpdate |
| Guild Member Add | events.EventGuildMemberAdd |
| Guild Member Update | events.EventGuildMemberUpdate |
| Guild Member Remove | events.EventGuildMemberRemove |
| Guild Members Chunk | events.EventGuildMembersChunk |
| Guild Role Create | events.EventGuildRoleCreate |
| Guild |