Giter Site home page Giter Site logo

twilight-rs / twilight Goto Github PK

View Code? Open in Web Editor NEW
634.0 11.0 125.0 324.42 MB

Powerful, flexible, and scalable ecosystem of Rust libraries for the Discord API.

Home Page: https://discord.gg/twilight-rs

License: ISC License

Rust 99.98% Shell 0.02%
discord-api discord-bot discord rust twilight-rs

twilight's Issues

[gateway] Opt-in to receive raw payloads

In the gateway, add a variant of the Event enum which contains the raw bytes of the payload. By default, this should be disabled and opt-in through the existing Cluster::some_events and Shard::some_events methods. This isn't costly because we don't consume the bytes when deserializing into a GatewayEvent, so no cloning is needed here.

[http] Expose raw client requests

Expose the functionality in the HTTP client to perform raw requests, still backed by the ratelimiter but avoiding convenience methods (such as Client::create_message).

[command-parser] Command parser is not deterministic and may chose wrong commands.

So at the moment the code below will sometimes fail and other times pass, it depends on the order
of the elements in the HashSet Commands and as that order is not deterministic it will sometime fail.

There are a couple of ways we could resolve this:

  • Force a separator after commands
  • Use a ordered set like a vector instead, but this will not solve that some commands would shadow others.
fn double_config() -> Parser<'static> {
    let mut config = Config::new();
    config.add_prefix("!");
    config.add_command("echo");
    config.add_command("echolocate");
    
    Parser::new(config)
}

#[test]
fn test_double_config() {
    let parser = double_config();
    
    match parser.parse("!echolocate") {
        Some(Command { name: "echo", .. }) => {
            panic!("Wrong command")
        },
        Some(Command { name: "echolocate", .. }) => {
        },
        // Ignore all other commands.
        Some(_) => panic!("This should not happen (1)"),
        None => panic!("This should not happen (2)"),
    }
}

[http] add 'reason' to all moderation requests

Add the 'X-Audit-Log-Reason` header to all moderation requests that can be audited.

This is already in the CreateBan request, but as a query parameter: https://github.com/dawn-rs/dawn/blob/ddfe693cb112ed8ceebb83af17ae02067bc6ab17/http/src/request/create_ban.rs#L35

We'll probably need to add better handling of UTF-8. A description of reasons is at the top of this page: https://discordapp.com/developers/docs/resources/audit-log#audit-logs

What this mostly means is manually creating the Request in the start method of requests and specifying the ratelimit header in the header map: https://github.com/dawn-rs/dawn/blob/ddfe693cb112ed8ceebb83af17ae02067bc6ab17/http/src/request/create_ban.rs#L42

[http] Parse error messages

Parse the error messages that Discord provides into error structs. An example of an error struct is this one, sent when a message embed's field name's length is 0:

{
    "code": 50035,
    "errors": {
        "embed": {
            "fields": {
                "0": {
                    "name": {
                        "_errors": [
                            {
                                "code": "BASE_TYPE_REQUIRED",
                                "message": "This field is required"
                            }
                        ]
                    }
                }
            }
        }
    },
    "message": "Invalid Form Body"
}

[gateway] Fix reconnection logic

On reconnects we're creating a new session but aren't propagating it to the heartbeater, so a heartbeat doesn't seem to be sent out, which then causes a close shortly after.

[gateway] Add new gateway event

The reconnect event is dispatched when a client should reconnect to the gateway (and resume their existing session, if they have one). This event usually occurs during deploys to migrate sessions gracefully off old hosts.

relevant commit

[gateway] Make compression optional

This is the first thing we need to do before getting on #14 since discord explicitly says

When using ETF, the client must not send compressed messages to the server.

Every other resume fails

Every other resume fails because the id fails to be set correctly after reconnecting to a new session.

[gateway] Request gateway URI via HTTP

On every shard connection, request the gateway URI via the given HTTP client in the config rather than hardcoding it, which is discouraged behaviour.

[gateway, http] Add serde-ignored feature

Add an optional opt-in feature for the gateway and http crates to use serde_ignored to deserialize payloads and log to INFO if there are any keys we didn't catch.

This should also log unknown keys directly in the custom deserializers where applicable.

[gateway] Implement Cluster events

The stream returned by Cluster::events and Cluster::some_events is currently unimplemented. We basically just need to merge all of the streams dynamically from all of the shards as new shard sessions are up.

[model] Add custom statuses

Add support for activity type 4, custom statuses.

The payload looks like this:

{
    "t": "PRESENCE_UPDATE",
    "s": 23,
    "op": 0,
    "d": {
        "user": {
            "id": "114941315417899012"
        },
        "status": "dnd",
        "roles": [
            "620984892410429470",
            "635845304947703808"
            "621037383416283137",
            "621124153361170452",
            "621273850138591262"
        ],
        "guild_id": "620980184606048276",
        "game": {
            "type": 4,
            "state": "Rainy",
            "name": "Custom Status",
            "id": "custom",
            "emoji": {
                "name": "๐ŸŒง"
            },
            "created_at": 1572196553812
        },
        "client_status": {
            "desktop": "dnd"
        },
        "activities": [
            {
                "type": 4,
                "state": "Rainy",
                "name": "Custom Status",
                "id": "custom",
                "emoji": {
                    "name": "๐ŸŒง"
                },
                "created_at": 1572196553812
            }
        ]
    }
}

It looks like we just need to add the activity.emoji key - which has the same payload as channel::ReactionType::Custom - and add a test for it like with other models.

See discord/discord-api-docs#1162

ShardConfig::builder issues with queue configuration function

This could be a simple mistake on my part or something counter-intuitive but looking at the function I should be able to just provide something simple like Box::new(Queue::new()). Except this doesn't work.

A bare bones example is importing dawn-gateway and only dawn-gateway like so dawn-gateway = { git = "https://github.com/dawn-rs/dawn" } then providing the built-in LocalQueue from dawn as a reproductive example.

use dawn_gateway::{Shard, ShardConfig, queue::LocalQueue};

let token = env::var("DISCORD_TOKEN")?;
let config = ShardConfig::builder(&token);
config.queue(Box::new(LocalQueue::new()));

I would assume this would work and be how it's performed as per this line doing this exact thing, just outside the function https://github.com/dawn-rs/dawn/blob/cc35c8532171ab1e02f7a5cf664599e50465107f/gateway/src/shard/config.rs#L105

[gateway] Request from queue on connects

When attempting to start a connection, a Shard needs to go through the queue already given to it, to ensure that only one shard is attempting to connect in a given 5 second period.

[http] Add Path parsing

Add parsing for http::routing::Path to parse from URLs or URI paths. For example, the string channels/123/messages should parse to the path Path::ChannelsIdMessages(123).

[project] add 'cache/in-memory'

Add the cache/in-memory crate, named dawn-cache-inmemory. This is an in-memory, (mostly) immutable cache with no public locking.

[http] Validate request parameters

Validate that request parameters and body values are within the accepted ranges. For example, getting some members from a guild can only get at most 1000 at a time. This will help prevent as many 400s as we can.

[model] member::guild_id can be non-optional

The model::guild::Member::guild_id structfield doesn't have to be optional.

Currently most types in the model crate are naive serde (de)serialization derives, and this type isn't any different. The gateway provides members with the guild_id, but the HTTP API doesn't. Since we already know the guild ID when using the HTTP API (we need it as a reference for where to get members from), we can use it as a serde::de::DeserializeSeed seed implementation for Member, avoiding the need for the structfield to be optional.

Right now, we get unfortunate real-world code like this:

use anyhow::Result;
use crate::State;
use dawn::model::gateway::payload::MemberAdd;

pub async fn handler(state: State, event: MemberAdd) -> Result<()> {
    // An unfortunate consequence of combining the HTTP and gateway models for
    // the Member struct -- we should change this.
    if let Some(guild_id) = event.guild_id {
        // work with the guild id here
    }

    Ok(())
}

Naming consistency across Config structs

ShardConfig builds into a Config, but then you start with a Config in the Command module. I would suggest explicit XConfig and XConfigBuilder names across the board, but being consistent in scheme is a minimum I would ask for in this issue.

[project] add 'cache/base'

Add the cache/base library, named dawn-cache. This is a library exporting the types from dawn-cache-trait (Cache and CacheUpdate), as well as exporting the dawn-cache-inmemory library.

Blocks on #5.

[meta] Standardize logging scheme

Standardize logging to use a single structure for messages. Right now it's stuff like "Error connecting: {:?}", "[SocketForwarder] Starting driving loop", and with #36 "[ShardProcessor {:?}] message" with {:?} being the shard ID/total.

I think the last one is the best.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.