Socket
Socket
Sign inDemoInstall

github.com/LaevusDexter/disgord

Package Overview
Dependencies
13
Alerts
File Explorer

Install Socket

Detect and block malicious and high-risk dependencies

Install

    github.com/LaevusDexter/disgord

Package disgord provides Go bindings for the documented Discord API, and allows for a stateful Client using the Session interface, with the option of a configurable caching system or bypass the built-in caching logic all together. Create a Disgord session to get access to the REST API and socket functionality. In the following example, we listen for new messages and write a "hello" message when our handler function gets fired. Session interface: https://godoc.org/github.com/LaevusDexter/disgord/#Session Disgord also provides the option to listen for events using a channel. The setup is exactly the same as registering a function. Simply define your channel, add buffering if you need it, and register it as a handler in the `.On` method. Never close a channel without removing the handler from Disgord. You can't directly call Remove, instead you inject a controller to dictate the handler's lifetime. Since you are the owner of the channel, disgord will never close it for you. Here is what it would look like to use the channel for handling events. Please run this in a go routine unless you know what you are doing. Disgord handles sharding for you automatically; when starting the bot, when discord demands you to scale up your shards (during runtime), etc. It also gives you control over the shard setup in case you want to run multiple instances of Disgord (in these cases you must handle scaling yourself as Disgord can not). Sharding is done behind the scenes, so you do not need to worry about any settings. Disgord will simply ask Discord for the recommended amount of shards for your bot on startup. However, to set specific amount of shards you can use the `disgord.ShardConfig` to specify a range of valid shard IDs (starts from 0). starting a bot with exactly 5 shards Running multiple instances each with 1 shard (note each instance must use unique shard ids) Handle scaling options yourself > Note: if you create a CacheConfig you don't have to set every field. > Note: Only LFU is supported. > Note: Lifetime options does not currently work/do anything (yet). A part of Disgord is the control you have; while this can be a good detail for advanced users, we recommend beginners to utilise the default configurations (by simply not editing the configuration). Example of configuring the cache: If you just want to change a specific field, you can do so. The fields are always default values. > Note: Disabling caching for some types while activating it for others (eg. disabling channels, but activating guild caching), can cause items extracted from the cache to not reflect the true discord state. Example, activated guild but disabled channel caching: The guild is stored to the cache, but it's channels are discarded. Guild channels are dismantled from the guild object and otherwise stored in the channel cache to improve performance and reduce memory use. So when you extract the cached guild object, all of the channel will only hold their channel ID, and nothing more. To keep it safe and reliable, you can not directly affect the contents of the cache. Unlike discordgo where everything is mutable, the caching in disgord is immutable. This does reduce performance as a copy must be made (only on new cache entries), but as a performance freak, I can tell you right now that a simple struct copy is not that expensive. This also means that, as long as discord sends their events properly, the caching will always reflect the true state of discord. If there is a bug in the cache and you keep getting the incorrect data, please file an issue at github.com/LaevusDexter/disgord so it can quickly be resolved(!) Whenever you call a REST method from the Session interface; the cache is always checked first. Upon a cache hit, no REST request is executed and you get the data from the cache in return. However, if this is problematic for you or there exist a bug which gives you bad/outdated data, you can bypass it by using Disgord flags. In addition to disgord.IgnoreCache, as shown above, you can pass in other flags such as: disgord.SortByID, disgord.OrderAscending, etc. You can find these flags in the flag.go file. `disgord_diagnosews` will store all the incoming and outgoing JSON data as files in the directory "diagnose-report/packets". The file format is as follows: unix_clientType_direction_shardID_operationCode_sequenceNumber[_eventName].json `json_std` switches out jsoniter with the json package from the std libs. `disgord_removeDiscordMutex` replaces mutexes in discord structures with a empty mutex; removes locking behaviour and any mutex code when compiled. `disgord_parallelism` activates built-in locking in discord structure methods. Eg. Guild.AddChannel(*Channel) does not do locking by default. But if you find yourself using these discord data structures in parallel environment, you can activate the internal locking to reduce race conditions. Note that activating `disgord_parallelism` and `disgord_removeDiscordMutex` at the same time, will cause you to have no locking as `disgord_removeDiscordMutex` affects the same mutexes. `disgord_legacy` adds wrapper methods with the original discord naming. eg. For REST requests you will notice Disgord uses a consistency between update/create/get/delete/set while discord uses edit/update/modify/close/delete/remove/etc. So if you struggle find a REST method, you can enable this build tag to gain access to mentioned wrappers. `disgordperf` does some low level tweaking that can help boost json unmarshalling and drops json validation from Discord responses/events. Other optimizations might take place as well. `disgord_websocket_gorilla` replaces nhooyr/websocket dependency with gorilla/websocket for gateway communication. In addition to the typical REST endpoints for deleting data, you can also use Client/Session.DeleteFromDiscord(...) for basic deletions. If you need to delete a specific range of messages, or anything complex as that; you can't use .DeleteFromDiscord(...). Not every struct has implemented the interface that allows you to call DeleteFromDiscord. Do not fret, if you try to pass a type that doesn't qualify, you get a compile error.


Version published

Readme

Source
Build Status

Code coverage Godoc

Discord Gophers Discord API

About

Go module with context support that handles some of the difficulties from interacting with Discord's bot interface for you; websocket sharding, auto-scaling of websocket connections, advanced caching, helper functions, middlewares and lifetime controllers for event handlers, etc.

Warning

The develop branch is under continuous breaking changes, as the interface and exported funcs/consts are still undergoing planning. Because Disgord is under development and pushing for a satisfying interface, the SemVer logic is not according to spec. Until v1.0.0, every minor release is considered possibly breaking and patch releases might contain additional features. Please see the issue and current PR's to get an idea about coming changes before v1.

There might be bugs in the cache, or the cache processing might not exist yet for some REST methods. Bypass the cache for REST methods by supplying the flag argument disgord.IgnoreCache. eg. client.GetCurrentUser(disgord.IgnoreCache).

Remember to read the docs/code for whatever version of disgord you are using. This README file reflects the latest state in the develop branch, or at least, I try to reflect the latest state.

Data types & tips

  • Use disgord.Snowflake, not snowflake.Snowflake.
  • Use disgord.Time, not time.Time when dealing with Discord timestamps. This is because Discord returns a weird time format.

Starter guide

This project uses Go Modules for dealing with dependencies, remember to activate module support in your IDE

Examples can be found in docs/examples and some open source projects Disgord projects in the wiki

I highly suggest reading the Discord API documentation and the Disgord go doc.

Here is a basic bot program that prints out every message. Save it as main.go, run go mod init bot and go mod download. You can then start the bot by writing go run .

package main

import (
    "context"
    "fmt"
    "github.com/LaevusDexter/disgord"
    "os"
)

func printMessage(session disgord.Session, evt *disgord.MessageCreate) {
    msg := evt.Message
    fmt.Println(msg.Author.String() + ": "+ msg.Content) // Anders#7248{435358734985}: Hello there
}

func main() {
    client := disgord.New(disgord.Config{
        BotToken: os.Getenv("DISGORD_TOKEN"),
        // You can inject any logger that implements disgord.Logger interface (eg. logrus)
        // Disgord provides a simple logger to get you started. Nothing is logged if nil.
        Logger: disgord.DefaultLogger(false), // debug=false
    })
    // connect, and stay connected until a system interrupt takes place
    defer client.StayConnectedUntilInterrupted(context.Background())
    
    // create a handler and bind it to new message events
    // handlers/listener are run in sequence if you register more than one
    // so you should not need to worry about locking your objects unless you do any
    // parallel computing with said objects
    client.On(disgord.EvtMessageCreate, printMessage)
}
Linux script

To create a new bot you can use the disgord.sh script to get a bot with some event middlewares and Dockerfile. Paste the following into your terminal:

bash <(curl -s -L https://git.io/disgord-script)

Starter guide as a gif: https://terminalizer.com/view/469961d0695

Architecture & Behavior

Discord provide communication in different forms. Disgord tackles the main ones, events (ws), voice (udp + ws), and REST calls.

You can think of Disgord as layered, in which case it will look something like: Simple way to think about Disgord architecture from a layered perspective

Events

For Events, Disgord uses the reactor pattern. Every incoming event from Discord is processed and checked if any handler is registered for it, otherwise it's discarded to save time and resource use. Once a desired event is received, Disgord starts up a Go routine and runs all the related handlers in sequence; avoiding locking the need to use mutexes the handlers.

In addition to traditional handlers, Disgord allows you to use Go channels. Note that if you use more than one channel per event, one of the channels will randomly receive the event data; this is how go channels work. It will act as a randomized load balancer.

But before either channels or handlers are triggered, the cache is updated.

REST

The "REST manager", or the httd.Client, handles rate limiting for outgoing requests, and updated the internal logic on responses. All the REST methods are defined on the disgord.Client and checks for issues before the request is sent out.

If the request is a standard GET request, the cache is always checked first to reduce delay, network traffic and load on the Discord servers. And on responses, regardless of the http method, the data is copied into the cache.

Some of the REST methods (updating existing data structures) will use the builder+command pattern. While the remaining will take a simple config struct.

Note: Methods that update a single field, like SetCurrentUserNick, does not use the builder pattern.

// bypasses local cache
client.GetCurrentUser(context.Background(), disgord.IgnoreCache)
client.GetGuildMembers(context.Background(), guildID, disgord.IgnoreCache)

// always checks the local cache first
client.GetCurrentUser(context.Background())
client.GetGuildMembers(context.Background(), guildID)
Voice

Whenever you want the bot to join a voice channel, a websocket and UDP connection is established. So if your bot is currently in 5 voice channels, then you have 5 websocket connections and 5 udp connections open to handle the voice traffic.

Cache

The cache tries to represent the Discord state as accurate as it can. Because of this, the cache is immutable by default. Meaning the does not allow you to reference any cached objects directly, and every incoming and outgoing data of the cache is deep copied.

Contributing

Please see the CONTRIBUTING.md file (Note that it can be useful to read this regardless if you have the time)

You can contribute with pull requests, issues, wiki updates and helping out in the discord servers mentioned above.

To notify about bugs or suggesting enhancements, simply create a issue. The more the better. But be detailed enough that it can be reproduced and please provide logs.

To contribute with code, always create an issue before you open a pull request. This allows automating change logs and releases.

Q&A

NOTE: To see more examples go to the docs/examples folder. See the GoDoc for a in-depth introduction on the various topics.

1. How do I find my bot token and/or add my bot to a server?

Tutorial here: https://github.com/LaevusDexter/disgord/wiki/Get-bot-token-and-add-it-to-a-server
2. Is there an alternative Go package?

Yes, it's called DiscordGo (https://github.com/bwmarrin/discordgo). Its purpose is to provide a 
minimalistic API wrapper for Discord, it does not handle multiple websocket sharding, scaling, etc. 
behind the scenes such as Disgord does. Currently I do not have a comparison chart of Disgord and 
DiscordGo. But I do want to create one in the future, for now the biggest difference is that 
Disgord does not support self bots.
3. Why make another Discord lib in Go?

I'm trying to take over the world and then become a intergalactic war lord. Have to start somewhere.
4. Does this project re-use any code from DiscordGo?

Yes. See guild.go. The permission consts are pretty much a copy from DiscordGo.
5. Will Disgord support self bots?

No. Self bots are againts ToS and could result in account termination (see
https://support.discord.com/hc/en-us/articles/115002192352-Automated-user-accounts-self-bots-). 
In addition, self bots aren't a part of the official Discord API, meaning support could change at any 
time and Disgord could break unexpectedly if this feature were to be added.

FAQs

Last updated on 13 May 2020

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc