andersfylling / disgord Goto Github PK
View Code? Open in Web Editor NEWGo module for interacting with the documented Discord's bot interface; Gateway, REST requests and voice
License: BSD 3-Clause "New" or "Revised" License
Go module for interacting with the documented Discord's bot interface; Gateway, REST requests and voice
License: BSD 3-Clause "New" or "Revised" License
When reconnect takes place, the sequence code is overwritten and lost; forcing a invalid session and a identity packet to be sent.
Change the way heartbeats are stored in the disgord instance
Event handlers should not be allowed to run in parallel, and developers should utilise channels for handling an event in parallel. The only reason is for convenience and readability.
By enforcing handlers to run in sequence, the behavior won't drastically change, causing software to break just because of a boolean in the config file. The developers can go through the code with the expectation of handlers to run in sequence, while seeing the use of channels they will know that any other functions/use cases of the same channel will cause a parallel environment, without having to check the config file for Disgord.
see the following URL for tips and tricks.
https://godoc.org/github.com/fluhus/godoc-tricks
As of the way this project is written now, this issue is complete once golint does not show an issue.
https://goreportcard.com/report/github.com/andersfylling/disgord#golint
On operation code 0, the event data should be pushed to disgord for transforming the data byte array into correct discord objects. Disgord can then dispatch those events correctly to users.
When running emoji unit tests, I get rate limited (try again in <1s). However, since the default timeout of the http client is 10 second, the expected behavior is to wait until Disgord can send the request.
when the function client.Disconnect() is called, the socket client should disconnect properly. Sending a disconnect packet, and waiting for the discord response before shutting down.
If the gateway ever issues a disconnect to your client, it will provide a close event code that you can use to properly handle the disconnection. A full list of these close codes can be found in the Response Codes documentation.
https://discordapp.com/developers/docs/topics/opcodes-and-status-codes#gateway-close-event-codes
Some events and the operation 7 requires reconnecting the client and the discord gateway.
Line 3 in ce4f302
might increase the time, but avoids any desyncs if the local system is offset/incorrect.
Update the discord and local time whenever a response from discord is processed.
Keep a private struct with the values:
with the method:
Assumptions:
the local clock counts seconds correctly.
Thanks to meew0 on Discord API server for pointing this out:
when ratelimiting, you should get the "current" time from the HTTP Date header, instead of
the local computer's time, to avoid problems because of time desynchronisation. This isn't
written down anywhere, I know, but most libs do it and there's really no reason not to
Most of the functions are similar on a stupid level.
The json unmarshalling should be a function of it's own such that we can easily swap json packages in case we want to try a third party.
There's a ton of hardcoded URL's.
Currently the client structs rewrite the caching and concurrency logic for every api call, which is identical except the types used. rewrite this using interfaces to reduce code size and potential lazy bugs.
One of the earlier requirements was that when unmarshalling JSON set A into struct a, then marshalling of struct a should give the exact same json data as A. That was a requirement as I wanted Disgord to have the option to behave as a Discord server proxy. That's not happening anymore as this is causing issues with data integrity.
Now the only goal is to make sure we don't overwrite correct data with simple default values when the incoming JSON data is of a partial object.
There was shown interest for having a command register for bots.
Because of this I suggest creating a Bot interface. But not to mix any of this into the existing disgord.Session interface. Instead the Bot interface will hold a disgord.Session instance and enforce some bot behavior rules as written later in this article.
disgord.NewBotInstance:
An exported function for constructing the Bot called NewBotInstance
and will handle the following:
disgord.Bot
disgord.BotConfig:
disgord.BotCommand:
!chessgame --start --name="something" --player1=@user1 --player2=@user2
disgord.BotService:
Rules:
Please discuss the matter. All comments are welcome. If you only want to express thoughts such as "I like this" or "I dislike this" without any reason. Use emoji's / reactions such as thumbs up and thumbs down.
Once a Operation code 10 is received; The client should begin sending Opcode 1 Heartbeat payloads every heartbeat_interval milliseconds, until the connection is eventually closed or terminated. This OP code is also bidirectional. The gateway may request a heartbeat from you in some situations, and you should send a heartbeat back to the gateway as you normally would.
Get inspired by the atom contributing guidelines: https://github.com/atom/atom/blob/master/CONTRIBUTING.md#git-commit-messages
todo:
issues:
when the current values, requests left before rate limited, subtracted by one does not match the rate limits in the header response; output to log, the url + bucket key.
the docs says "For example, /channels/:channel_id and /channels/:channel_id/messages/:message_id both take channel_id into account when generating rate limits since it's the major parameter."
Meaning the rate limit of "/channels/:channel_id" and "/channels/:channel_id/messages/:message_id" is not the same, however the parameter of channel_id is a part of the rate limiter such that the rate limits are:
Currently this library use the same rate limit for both: "/channels/:channel_id"
A brief install guide would be handy for newcomers to the project. :)
After creating a custom unmarshaller for the socket layer, major performance improvements was noticed:
goos: linux
goarch: amd64
pkg: github.com/andersfylling/disgord/websocket
BenchmarkEvent_CustomUnmarshal_smallJSON-8 20000000 114 ns/op
BenchmarkEvent_Unmarshal_smallJSON-8 3000000 528 ns/op
BenchmarkEvent_CustomUnmarshal_largeJSON-8 10000000 195 ns/op
BenchmarkEvent_Unmarshal_largeJSON-8 5000 222485 ns/op
PASS
While the marshaller ignores the byte array at d
, it is still significantly faster with small JSON's (114ns/op vs. 528ns/op, on my laptop).
With this in mind, I suggest creating custom json unmarshallers for every discord data structure in the repository to reduce any wait time.
Note! The json.Marshaler
and json.Unmarshaler
interfaces should be implemented on the data structures. Doing so allows us to still use json.Unmarshal(...)
intuitively.
checkout ffjson
Edit2: Due to adding voice, json.RawMessage is tmp used until further testing.
There has not been any effort into designing a library that can execute REST requests without authentication. As there are REST endpoints in the Discord API that does not require authentication, this must be fixed.
run tests with the race flag to identify the issue
Line 150 in 9fee927
The following list suggests methods to simplify Discord interaction.
Line 310 in db9030d
Every socket package is categorized based on their operation value (0 - 11) and discord events can be extracted when the operation code is 0.
There are still events that directly affect the socket connection, and needs to be handled on the socket layer.
The events are READY and RESUMED.
output:
------
TODO
Implement event handler for ``, data:
------
DEBU[2018-09-11 01:10:58] <-:
ERRO[2018-09-11 01:10:58] readObjectStart: expect { or n, but found , error found in #0 byte of ...||..., bigger context ...||...
DEBU[2018-09-11 01:10:58] <-:
ERRO[2018-09-11 01:10:58] readObjectStart: expect { or n, but found , error found in #0 byte of ...||..., bigger context ...||...
DEBU[2018-09-11 01:10:58] <-:
ERRO[2018-09-11 01:10:58] readObjectStart: expect { or n, but found , error found in #0 byte of ...||..., bigger context ...||...
panic: repeated read on failed websocket connection
goroutine 69 [running]:
github.com/gorilla/websocket.(*Conn).NextReader(0xc0000fe9a0, 0xc000204ea0, 0x4067a5, 0xc000034180, 0xc000204f70, 0xc000204f01)
/home/anders/go/src/github.com/gorilla/websocket/conn.go:967 +0x356
github.com/gorilla/websocket.(*Conn).ReadMessage(0xc0000fe9a0, 0xc000204f70, 0x1, 0x7de0c0, 0xc0004af000, 0x8c2d40, 0xc00021abb0)
/home/anders/go/src/github.com/gorilla/websocket/conn.go:1028 +0x2f
github.com/andersfylling/disgord/websocket.(*Client).readPump(0xc000134000)
/home/anders/go/src/github.com/andersfylling/disgord/websocket/client.go:325 +0xcd
created by github.com/andersfylling/disgord/websocket.(*Client).Connect
/home/anders/go/src/github.com/andersfylling/disgord/websocket/client.go:427 +0x2a5
exit status 2
LRFU (Least Recently / Frequently Used), a combination of LRU (Least Recently Used) and LFU (Least Frequently Used).
Months ago, Disgord implemented the pro-actor pattern; this would run handlers in parallel, making locking of shared resources required. However, that pattern has been removed.
Disgord now uses the reactor pattern and allows the use of channels. Neither of which, in themselves, causes the need for locking. Handlers in the reactor pattern are run in sequence, and the way channels are implemented doesn't cause any parallel use of the data structures.
The cache layer is run before the data structures, from the events are dispatched. And caching is also done on responses from REST requests before the user/developer is given access to said structs.
Instead of checking the error type by casting in a switch or if sentence, cast it once and get access to a error ID.
if disgordErr, ok := err.(*DisgordErr); ok && disgordErr.ID == disgord.DiscordGatewayDown {
// ...
}
Current way of handling custom errors (which adds a bunch of extra code):
switch err.(type) {
case disgord.UnsupportedEventType:
// ...
}
Disgord depends on the disconnect channel, and when this is closed (during reconnect), the user cannot stop Disgord using interrupts.
TODO
Implement event handler for `PRESENCES_REPLACE`, data:
[]
event_dispatcher.go is large, and might get larger in the future. It needs to be refactored and can follow the same file pattern as rest_* and struct_*. However, the methods triggerChan and triggerCallbacks should have a switch that groups together event types based on their file category (channel, guild, user, etc.). These events would then be handled in a non-exported function within the given files.
This splits up the demultiplexer; the client holds the demultiplexer to identify group of events which is then passed down to the relevant function which deals with all the specific triggering and building logic (consider using the component pattern).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.