A Quick History on the Development of Disgo

You want to contribute to Disgo but don't know where to start? Read this article.
Jan 25, 2023
7 min

What Problem Does Disgo Solve?

Discord is a chat application. In order to automate actions in Discord servers, you must create a bot. A bot is a software application, which is created using a programming language. In order for the bot to interact with Discord, it must use Discord’s Application Programmer Interface (API). Software that interacts with an API (computer server) is called an API Wrapper.

Disgo is a Discord API Wrapper for the Go programming language. In other words, Disgo can be used by other Go programmers to quickly implement the ability to interact with the Discord API in their (Go) Discord Bots. Read “Why Go?” to understand why a programmer would use Go to create a Discord Bot.

Confused about APIs? Read the first section of “What is a Request?”, then watch “What are APIs?”, then watch “What is a REST API?

Why Was Disgo Created?

Both DiscordGo and Disgo solve the exact same problem. However, DiscordGo has existed for a longer time than Disgo. This prompts the question, “Why Was Disgo Created?Personal experiences aside, the quality of DiscordGo’s developer operations is not high enough to keep up with the constantly updating Discord API. This has resulted in missing features and relatively poor performance.

Disgo was created as a response to DiscordGo’s unsolvable shortcomings (as a result of its backwards compatibility). A modern comparison of DiscordGo vs. Disgo shows how Disgo is better than DiscordGo. Understanding the history of Disgo’s creation will provide you the information you need to contribute to Disgo.

What is Dasgo?

A solution to a programming problem typically follows a pattern. When it comes to web services and applications, that programming problem is centered around data manipulation. As an example, sending a Discord Message involves collecting data (i.e message content) and sending that data elsewhere. Such that the following pattern emerges for any action.

  1. Define the Data Model of the problem.
  2. Add Code Logic that manipulates the data (on a conditional basis).

For a concrete example of this pattern being implemented, read the steps required to add a Disgo Request. Steps 1 and 2 define the data models of a request. Step 3 sets up the generator (used to generate code logic). Step 4 and 5 adds the code logic that performs actions based upon the provided data during runtime. Step 6 contributes to a step — testing — that ensures the code logic works.

Disgo must perform both steps for every feature of the Discord API. Of course, this becomes problematic when Discord has 180 requests and 70 events to implement. In other words, an API Wrapper that implements every feature of the Discord API must define over 250 data models and the subsequent code logic for those data models. 

So how does a Discord API Wrapper solve this problem?

DiscordGo implements features from the Discord API by defining the Go data models within the wrapper by hand. However, this requires the maintainer to define every data model correctly and also implement the code logic for it. The reality is that humans are prone to make mistakes. So it’s no surprise that many of the (60+) issues on DiscordGo’s issue tracker result from incorrect definitions of a Discord API Data Model.

Define a Data Model

To be specific, a Go API Wrapper must be able to marshal (convert) a Go Programming Language object to a JSON object.

Data must be converted from this (Go object).

type Emoji struct {
 ID            *Snowflake  `json:"id"`
 Name          *string     `json:"name,omitempty"`
 Roles         []Snowflake `json:"roles,omitempty"`
 User          *User       `json:"user,omitempty"`
 RequireColons *bool       `json:"require_colons,omitempty"`
 Managed       *bool       `json:"managed,omitempty"`
 Animated      *bool       `json:"animated,omitempty"`
 Available     *bool       `json:"available,omitempty"`
}

To this (JSON object).

{
  "id": "41771983429993937",
  "name": "LUL",
  "roles": ["41771983429993000", "41771983429993111"],
  "user": {
    "username": "Luigi",
    "discriminator": "0002",
    "id": "96008815106887111",
    "avatar": "5500909a3274e1812beb4e8de6631111",
    "public_flags": 131328
  },
  "require_colons": true,
  "managed": false,
  "animated": false
}

Such that there are certain rules that must be adhered to in defining the Go object. When these rules are NOT met, there is a possibility for certain configurations of the JSON object to be impossible. This is significant since the JSON that a Discord Bot sends to Discord determines the actions that occur (once the request has been received). So to connect the dots…

Creating a Go object incorrectly results in missing features.

Instead of solving this problem by relying on a maintainer, the Disgo founders decided to use a specification (to create the Go objects). In modern times, it’s typical for the API Provider (Discord) to provide a machine readable specification. However, Discord refuses. So we had to create one.

The Discord API Specification

The Discord API Specification (DAS) was created to automatically generate data models from the Discord API Documentation. Unfortunately, we ran into many issues: #4. As a result, Dasgo was created alongside its specification in order to provide Go objects that represent Discord Data Models.

A major benefit of this approach is that the Go objects maintain a direct representation of the Discord API Objects. This direct representation is what makes the Disgo API Wrapper a one-to-one implementation of the Discord API. In addition, Disgo is the only struct-based Discord API Wrapper (as opposed to a function-based Discord API Wrapper). To understand the benefits of a struct-based API, read "I released vaporware" or the "Arikawa vs. Disgo Comparison".

How Was Disgo Created?

Dasgo provides the data models that are used within the API Wrapper. Then, code logic is added to provide the functionality for a variety of features. In order to do this, we must pull the Dasgo objects into the Disgo codebase after each Discord API Update: Generators were created in order to perform these tasks in an efficient manner.

What is a Request?” describes how requests work and how they are implemented. Disgo requests are implemented with optimal rate limits. However, implementing optimal rate limits took time as the Discord Documentation for Rate Limits remain ambiguous. The Disgo implementation for rate limits is described in #14 and #22.

When you check the implementation of a few requests, you will realize that each request’s code logic is similar to other requests (with slight variations). Rather than code each request by hand, Copygen — a type-based code generator — is used to generate code based on the defined Dasgo types. As a result, request code is automatically added following a Dasgo update via generators.

What is an Event?” describes how WebSocket Session connections and events work for event handling. DiscordGo implements these features using reflection and type assertion which results in suboptimal performance. Disgo avoids the use of reflection and type assertion by having the user directly define the handler, and by directly parsing the Event Payload (Binary or JSON) to its Go object. This implementation also allows for Selective Event Handling.

In order to implement event handling code, Copygen is used to generate code based on the defined Dasgo types. As a result, event handling code is automatically added following a Dasgo update via generators (in a similar manner to requests). Combining each generator operation into a single command gen allows the maintainer of Disgo to stay up-to-date with the Discord API in a low-effort manner.

Understanding Voice Connections

Voice Connections function in a similar manner to WebSocket Session Gateway connections. As a result, the code is similar to the WebSocket Session code. This feature is still being implemented.

Understanding Sharding

Read “What is Discord Sharding?” for a simple yet full understanding of sharding on Discord. This feature is still being implemented in #26.

Understanding Caching

Read "What is a Cache?" for a simple yet full understanding of the Disgo Cache. This feature is still being implemented in #39.

Understanding Developer Operations

Every time a change is made to the codebase, we must verify that it doesn’t break functionality for end users. Static Code Analysis is used to ensure that code remains high quality. Unit testing ensures that code logic within the application remains bug free. Integration testing ensures that the bot interacts with the Discord API in a real environment. These changes are run in a GitHub Actions pipeline which runs specified workflows on a computer server every commit.

What is a Bundle?

A fieldaligntment bundle is used to optimize the memory of the Dasgo structs. This provides yet another performance boost compared to Disgo’s predecessors. For more information, read Implementing The Fieldalignment Bundle.

Why Is Disgo Significant?

Disgo is significant for various reasons. While its performance improvements for Go Discord API Wrappers are awesome, more significant is the time it took to create Disgo. Version one took 9 months to completion with 3 contributors total. Contrast that with DiscordGo which has 150+ contributors and 6 years of development, but still maintains many technical issues. Others will debate on whether or not it’s fair to compare new libraries to old libraries (in the same niche). However, when that new library covers more features, is more performant, and is more tested, it’s hard to argue that Disgo is NOT a successor to DiscordGo.

What Challenges Does Disgo Face Today?

Officialization

Disgo aims to be mentioned in the Discord API Documentation. However, this requires the usage of Disgo in 1,000 users’ Discord Bots. If you are interested in assisting with this goal while also gaining project experience in pull requests from other libraries, consider performing Roadmap Refactor tasks.

Brigading

Another challenge that Disgo faces is brigading. Certain DiscordGo members (or more so fans) have attempted to get the owner’s GitHub account banned. This group does NOT include the hard working maintainer of that library, FedorLap. This article will not focus on that situation, but it should be noted that various forms of misinformation have been spread about the Disgo maintainers in order to prevent its growth. Please do your best to prevent this misinformation so this software continues to grow.

How Do I Start Contributing?

Read the Disgo Contribution Guide for a full guide on how to contribute to Disgo (without prior programming knowledge). Don’t hesitate to contact a maintainer if you need help at any point in this process.

Read More

improve Your Mindset

Unsubscribe at any time. See Privacy Policy

link