Go
Post stats, check votes and verify webhooks with the Omniplex Go SDK.
The Go SDK needs Go 1.22 or newer and uses only the standard library. It works with discordgo, disgo, arikawa and anything else.
go get github.com/PlexiOSS/Omniplex/packages/sdk-goimport "github.com/PlexiOSS/Omniplex/packages/sdk-go"The package is named omniplex. Every method takes a context.Context.
Reference on pkg.go.dev.
Posting stats
client := omniplex.New(os.Getenv("OMNIPLEX_TOKEN"))
err := client.PostBotStats(ctx, omniplex.BotStats{
Servers: omniplex.Int(len(session.State.Guilds)),
Shards: omniplex.Int(1),
Status: omniplex.StatusOnline,
})Fields you leave nil aren't sent, so Omniplex keeps their last value.
omniplex.Int makes the pointer for you.
Or let the SDK post for you. AutoPostBotStats posts once straight away, then on
the interval you choose (at least a minute, 30 minutes if you pass 0), until the
context is cancelled. Run it in its own goroutine:
go client.AutoPostBotStats(ctx, 30*time.Minute,
func(ctx context.Context) (omniplex.BotStats, error) {
return omniplex.BotStats{Servers: omniplex.Int(len(session.State.Guilds))}, nil
},
func(err error) { log.Printf("posting stats to Omniplex: %v", err) },
)Status reports your bot's presence: StatusOnline, StatusIdle, StatusDND
or StatusOffline. Omniplex keeps showing the last value you posted, so post it
regularly if you use it. See Posting Bot Stats.
For a server, use a server token and
PostServerStats(ctx, omniplex.ServerStats{TotalMembers: ..., OnlineMembers: ...}).
Checking votes
Checking votes doesn't need a token.
client := omniplex.New("")
voted, err := client.HasVoted(ctx, botID, userID)
vote, err := client.GetBotVote(ctx, botID, userID)
if err == nil && vote.Wait != nil {
fmt.Println("They can vote again in", vote.Wait.Duration())
}HasVotedForServer and GetServerVote do the same for servers. GetBot,
GetServer and GetUser read public data as a map[string]any.
Webhooks
Set a secret on your webhook in the dashboard and choose HMAC signature.
The SDK also verifies the older splashtail and simple-auth methods.
Omniplex occasionally sends a webhook signed with the wrong secret to check that
your endpoint rejects it. WebhookHandler verifies every request, answers 401
when verification fails, 405 for anything other than POST, 500 if your
function returns an error and 204 otherwise:
http.Handle("/omniplex", omniplex.WebhookHandler(secret,
func(r *http.Request, event *omniplex.WebhookEvent) error {
if vote, ok := event.Data.(*omniplex.NewVoteData); ok && !vote.Downvote && !vote.Auto {
return rewardVoter(r.Context(), event.Creator.ID)
}
return nil
},
))To verify inside your own handler, use VerifyWebhookRequest(r, secret), or
VerifyWebhook(body, header, secret) if you've already read the body. Failures
match errors.Is(err, omniplex.ErrInvalidWebhook).
event.Data holds a pointer to the event's type, such as *NewVoteData. An
event this version doesn't know yet has Data set to nil, with its raw JSON in
RawData. The webhooks page lists every
event and its fields.
Errors
Failed requests return an *omniplex.APIError with the HTTP Status, the API's
Message, any validation Context, and RetryAfter when you're rate limited.
Posting without a token returns omniplex.ErrMissingToken.
var apiErr *omniplex.APIError
if errors.As(err, &apiErr) && apiErr.Status == http.StatusUnauthorized {
log.Print("Your Omniplex token is invalid")
}Options
client := omniplex.New(token,
omniplex.WithBaseURL("https://api.omniplex.gg"), // the default
omniplex.WithMaxRetries(2), // retries for rate limits and failed GETs
omniplex.WithHTTPClient(&http.Client{Timeout: 10 * time.Second}),
omniplex.WithUserAgent("my-bot/1.0"),
)client.Do(ctx, method, path, body, auth, &out) calls any other endpoint with
the same retry and error handling.