kraigie / nostrum Goto Github PK
View Code? Open in Web Editor NEWElixir Discord Library
Home Page: https://kraigie.github.io/nostrum/
License: MIT License
Elixir Discord Library
Home Page: https://kraigie.github.io/nostrum/
License: MIT License
Version: github
Starting the application from iex -S mix (I used both the simple and the more complex samples), it shows the following warning.
16:04:21.780 [warn] Unhandled websocket message: {:DOWN, #Reference<0.436806687.830210049.7920>,
:process, #PID<0.242.0>, {:undef, [{:crypto, :rand_bytes, [16], []}, {:cow_ws, :key, 0,
[file: 'src/cow_ws.erl', line: 63]}, {:gun_http, :ws_upgrade, 7, [file: 'src/gun_http.erl', line: 407]},
{:gun, :loop, 1, [file: 'src/gun.erl', line: 629]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 247]}]}}
This warning comes from here, and it does nothing, and so (or maybe not) it never connects.
When I edited the source to do the same thing as this pattern, it keeps on doing the reconnection and never succeeds.
16:28:28.656 [warn] websocket caller received DOWN, attempting reconnect
16:28:28.656 [debug] WAITING 5454 BEFORE NEXT SHARD CONNECT
16:28:34.154 [warn] websocket caller received DOWN, attempting reconnect
16:28:34.154 [debug] WAITING 5460 BEFORE NEXT SHARD CONNECT
...
This is curious because the hex version will succeed with no warnings.
Right now we're passing tuples to relay information, we should move this to structs with the appropriate information.
def deps do
[{:nostrum, "~> 1.0"]
end
should be
def deps do
[{:nostrum, "~> 0.1"]
end
Without any warning, I've been seeing the following in the logs:
17:41:26.324 [warn] websocket disconnected with reason {:remote, 1000, ""}, attempting reconnect
17:42:21.409 [warn] websocket disconnected with reason {:remote, 1000, ""}, attempting reconnect
17:43:16.475 [warn] websocket disconnected with reason {:remote, 1000, ""}, attempting reconnect
17:44:11.543 [warn] websocket disconnected with reason {:remote, 1000, ""}, attempting reconnect
17:45:06.617 [warn] websocket disconnected with reason {:remote, 1000, ""}, attempting reconnect
17:46:01.692 [warn] websocket disconnected with reason {:remote, 1000, ""}, attempting reconnect
17:46:56.802 [warn] websocket disconnected with reason {:remote, 1000, ""}, attempting reconnect
17:47:51.872 [warn] websocket disconnected with reason {:remote, 1000, ""}, attempting reconnect
17:48:46.942 [warn] websocket disconnected with reason {:remote, 1000, ""}, attempting reconnect
17:49:42.026 [warn] websocket disconnected with reason {:remote, 1000, ""}, attempting reconnect
Until today, it would eventually reconnect, but now it seems stuck in eternal attempt to reconnect. Does anyone have any insight on what might be happening?
This includes
@spec
'sMethods that have documentation have been tested and will adhere to their documentation. I can't make any guarantees for those without documentation.
@spec
's@spec
's@spec
's@spec
's@spec
's@spec
'sHi all,
So I found this lib over the weekend and I was trying out the example consumer program. The bot is connected, sees when someone is typing, but when I write "!ping" in the general channel it says "message created" in the debug logs but I don't see a message on the channel.
Am I missing something obvious here? I granted all permissions to the bot to see if it worked (my example server that nobody uses so it's okay).
Here we're creating a stream and then never enumerating through it.
Additionally, we probably want to modify the user and guild cache to take in a list to improve performance, instead of calling these functions for each member.
I'm getting a no function clause matching in Nostrum.Api.handle_request_with_decode/2
exception being raised on the add_member_to_guild/3
function when that member already exists on the server.
The Discord API docs indicate that a 204 No Content status code is sent back in this scenario with an empty body. In this case, the function clause is being called with the following arguments:
and the following function clauses were attempted:
defp handle_request_with_decode({:error, _} = error, _type)
defp handle_request_with_decode({:ok, body}, type)
The error is being raised at line 2571
I've tried it on both the stable version 0.1
and the development version (currently on the development version) but the error persists in both. 😞
Using the method, it crashes with this output:
15:13:43.092 [error] GenServer Ratelimiter terminating
** (Poison.SyntaxError) Unexpected token at position 0: <
(poison) lib/poison/parser.ex:57: Poison.Parser.parse!/2
(poison) lib/poison.ex:83: Poison.decode!/2
(nostrum) lib/nostrum/api/ratelimiter.ex:110: Nostrum.Api.Ratelimiter.format_response/1
(nostrum) lib/nostrum/api/ratelimiter.ex:33: Nostrum.Api.Ratelimiter.handle_call/3
(stdlib) gen_server.erl:636: :gen_server.try_handle_call/4
(stdlib) gen_server.erl:665: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message (from #PID<0.233.0>): {:queue, %{body: %{limit: 1..100}, headers: [{"content-type", "application/json"}], method: :get, options: [], route: "/guilds/260291356562423809/members/"}, nil}
State: []
Client #PID<0.233.0> is alive
(stdlib) gen.erl:169: :gen.do_call/4
(elixir) lib/gen_server.ex:734: GenServer.call/3
(nostrum) lib/nostrum/api.ex:907: Nostrum.Api.get_guild_members/2
(test_discord_bot) lib/test_discord_bot.ex:54: ExampleConsumer.handle_event/2
(nostrum) lib/nostrum/consumer.ex:176: Nostrum.Consumer.do_event/3
(nostrum) lib/nostrum/consumer.ex:170: Nostrum.Consumer.handle_events/3
(gen_stage) lib/gen_stage.ex:2543: GenStage.consumer_dispatch/7
(gen_stage) lib/gen_stage.ex:2083: GenStage.handle_info/2
HTTPoison is crashing trying to parse this:
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 400 (Bad Request)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=//www.google.com/><span id=logo aria-label=Google></span></a>
<p><b>400.</b> <ins>That’s an error.</ins>
<p>Your client has issued a malformed or illegal request. <ins>That’s all we know.</ins>
and I can't understand why Google is returning the error.
This will also allow us to safely convert the maps received over the WS to atom-keyed maps.
HI,
Elixir 1.7.4 generates the following warnings when compiling
warning: variable "index_by" is unused
lib/nostrum/util.ex:222
warning: variable "type" is unused
lib/nostrum/util.ex:222
The Intro doc says to use the git master of nostrum, instead of a released version.
The version of this library hosted on Hex is severely outdated. Once the dependency
[gun](https://github.com/ninenines/gun) has a 2.0 release, a new package will be
released with the most up to date Elixir version (1.6.4 as of the time of this writing).
In the meantime it is recommended you use the version hosted on GitHub.
However, the 0.3.0 release replaced gun with websockex. Is it still advised to use the dev version? Or can I use nostrum 0.3.2 without causing extra trouble for myself?
Currently the state of the websocket-controlling process is just stored as a map. We should instead store this as a struct so it can be properly documented as well as provide the guarantees of a struct.
The current state documentation can be found here.
04:01:43.677 [warn] HEARTBEAT_ACK not received in time, disconnecting
04:03:31.167 [warn] Unhandled websocket message: {:DOWN, #Reference<0.2512857106.1813512198.243387>, :process, #PID<0.232.0>, {:shutdown, :nxdomain}}
If the user loses internet for a couple minutes and does not receive a HEARTBEAT_ACK in time, then the user will no longer receive events. This is even if the user reconnects his or her internet.
Expected: Even if losing internet for hours of time, lib user will start receiving events again after reconnecting to the internet.
Observed: Lib user no longer receives any events after the gun process shuts down. Even if the user reconnects to the internet.
Steps to reproduce:
I'm thinking it's likely because we instruct gun to shutdown if we don't receive a HEARTBEAT_ACK in time. From what it looks like, we also never ask for gun to reopen its connection.
Credit to barkerja#9999 for bringing up the issue on the nostrum DAPI channel.
For dicussion.
We would return structs, so the user facing side of things wouldn't change. But the way we're handling struct updates is leading to a lot of problems.
Currently, to the best of my knowledge, Nostrum doesn't support kicking a user from a guild. It supports banning however.
Could kick support be added to the roadmap for addition to Nostrum, or is there a limitation of Discord's API with regards to kicking a user?
Thanks 😄
Overtime it seems like heartbeats are being duplicated. On my testing bot with a couple weeks uptime there were two heartbeat acks within 5 seconds of each other, when they should be ~40s apart.
iex -S mix
sample log (from where bot gets kicked): gist
In dispatch.ex 's GUILD_DELETE
pattern, it tries to get a p.unavailable
boolean.
But from the Discord document it says unavailable
is true
or not set. (hey is that what we call a boolean!?)
whether the guild is unavailable, should always be true. if not set, this signifies that the user was removed from the guild
So the dot-access method might be the very first problem here.
Can someone point to an example where the example describes listening to a channel and replying?
Having troubles trying to get the hedwig discord adapter working.
Hi
is it possible to have to include nostrum in extra_applications rather than have it start automatically just because its listed as a dependency.
The reason - i use the same code base on multiple nodes but only want to run nostrum on one. My code explicity starts the applications it needs and not the ones that node does not. Despite this nostrum seems to be running regardless i.e. on call nodes.
From bucket.ex:
def lookup_bucket(route) do
route_time = :ets.lookup(:ratelimit_buckets, route)
global_time = :ets.lookup(:ratelimit_buckets, "GLOBAL")
Enum.max([route_time, global_time])
end
Intuitively, it seems like this ends up doing something to the effect of
iex(1)> Enum.max([{"route", 5, 1234567890, 2}, {"GLOBAL", 10, 1234567890, 4}])
{"route", 5, 1234567890, 2}
which probably isn't right.
Also you told me to open this issue https://i.imgur.com/ff4xy3T.png
Right now it's not possible to define customer consumers properly. You can see #126 for some discussion on the matter.
To properly implement this, if the config option is true, we should disable the cache supervisor as well as the gen_stage stages besides the producers. We might also want to consider creating a utility function so users can more easily subscribe to our producers, or mention the name of the producer somewhere in the docs.
** (exit) exited in: GenServer.call(#PID<0.491.0>, {:update, :member, 248859295414878208, %{guild_id: 248859295414878208, nick: nil, roles: [277668776382693376], user: %{avatar: "309b5063d0797a362a9d697c5fc67920", discriminator: "9796", id: 222244646317850624, username: "mcred"}}}, 5000)
** (EXIT) an exception was raised:
** (BadMapError) expected a map, got: nil
(stdlib) :maps.merge(nil, %{guild_id: 248859295414878208, nick: nil, roles: [277668776382693376], user: %{avatar: "309b5063d0797a362a9d697c5fc67920", discriminator: "9796", id: 222244646317850624, username: "mcred"}})
(nostrum) lib/nostrum/cache/guild/guild_server.ex:390: Nostrum.Cache.Guild.GuildServer.handle_call/3
(stdlib) gen_server.erl:636: :gen_server.try_handle_call/4
(stdlib) gen_server.erl:665: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
I have frequently this issue with member update, the member is not already in cache so the update is generating an exception crashing my consumer
Seems very similar to #35
22:26:44.468 [info] websocket closed, attempting reconnect
22:26:44.470 [error] GenServer #PID<0.800.0> terminating
** (stop) :data_error
:zlib.inflateEnd_nif(#Reference<0.2579208287.1398407170.85146>)
(nostrum) lib/nostrum/shard/session.ex:133: Nostrum.Shard.Session.handle_info/2
(stdlib) gen_server.erl:633: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:703: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: {:gun_down, #PID<0.803.0>, :ws, :closed, [], []}
State: %{gateway: 'gateway.discord.gg', gun_pid: #PID<0.803.0>, heartbeat_ack: true, producer_pid: #PID<0.801.0>, reconnect_attempts: 0, seq: 22, session: "2f2a3e582935ec8bb82d20bdf207446a", shard_num: 0, shard_pid: #PID<0.800.0>, token: "<CENSORED>", zlib_buffer: "", zlib_ctx: #Reference<0.2579208287.1398407170.85146>}
22:26:44.471 [info] GenStage consumer #PID<0.857.0> is stopping after receiving cancel from producer #PID<0.802.0> with reason: {:data_error, [{:zlib, :inflateEnd_nif, [#Reference<0.2579208287.1398407170.85146>], []}, {Nostrum.Shard.Session, :handle_info, 2, [file: 'lib/nostrum/shard/session.ex', line: 133]}, {:gen_server, :try_dispatch, 4, [file: 'gen_server.erl', line: 633]}, {:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 703]}, {:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 247]}]}
I couldn't find anything about audio in the documentation but I just wanted to confirm.
Does this library support reading or sending audio to voice channels?
Api.create_message/2
s :file
parameter currently only supports a file specified with an explicit path. Being able to send StringIO
s in addition to regular files would be great.
We're currently writing a lot of code to define the functions needed to work with structs:
defstruct
- To define the struct.
p_encode
- To decode poison results to structs
to_struct
- To decode websocket payloads to structs
Work has been done on creating a single macro that encapsulates the above methods, it can be found here.
In the new v7 api the way errors are returned is very different and way better. You could consider looking into this to provide better information about failed requests.
Right now, the Nostrum.Consumer behaviour specifies the GenStage behaviour with the :consumer type. Ideally, it would also support the :producer_consumer type (and handle_events would in that case pass its event objects in its return value), allowing other modules using the GenStage behaviour to subscribe directly to Nostrum.Consumer (or whatever would be named under this scheme, whether that name becomes something more general and it's parameterized or whether a Nostrum.ProducerConsumer behaviour is introduced alongside it).
In the README there is currently a note about OTP 20:
This means in order to run your bot, you will need the Gun 2.0 rc, as the latest release is for OTP 19 and will not run on OTP 20.
Looking at the Gun repository, the latest version seems to be 1.0-pre and not 2.0-rc.
Is there a typo in the README or am I missing something?
According to the Gun doc, requirements for version 1.0 is OTP 18+.
Nostrum currently caches guilds, channels, and users. I think that a message cache would prove useful to some bots. Some examples from mine:
This is not a common thing across bots, and having the message cache opt-in (maybe through another module) would be the best approach, since bots with a lot of channels will end up with very high memory usage.
As far as I'm aware, these are decent methods of caching messages:
I currently use an Agent
to accomplish caching on a per-channel basis: https://github.com/jchristgit/Bolt/blob/master/lib/bolt/message_cache.ex
It's very dumb but it does its job. An ETS table might be better suited, but I've never used ETS directly, so I wouldn't know ...
My question: is something like this planned for nostrum, would it be a "nice-to-have", or is the library supposed to keep the implementation of this up to the user?
The docs for Nostrum.Error.ApiError.message_map()
specify that the map keys are atoms, but they are currently being returned as strings.
May be relevant: https://github.com/Kraigie/nostrum/blob/master/lib/nostrum/api/ratelimiter.ex#L167
There are some cases where we're probably using the wrong logging levels, and more place where we could have logging that we don't.
Creating an issue to ensure it's addressed. 🙃
@spec
's@spec
's@spec
'sCurrently there is no ratelimiting on requests sent over the gateway.
It would be somewhat trivial to implement ratelimiting using GenStage, such that only x
amount of events are sent in a given time frame.
If we decide to use GenStage, there are a couple things we need to consider
Different types of messages have different ratelimits that we need to respect. This makes it a little more complicated as we need to do some sort of partitioning and/or spawn multiple consumers.
We want to be able to give certain messages a priority over others (I.E. we want to handle heartbeats before we send member requests). Given that we will likely not be storing demand in memory, we can develop some kind of naive priority queue to handle this for us.
I am noticing when a nickname is reset on a server (meaning the nick
is nil
), the GUILD_MEMBER_UPDATE
event payload received still contains the old nick in the new member payload.
Hi,
I've a problem sending mentionable roles in a message. E.g. the message <@&123456>
where 123456 is the id of a mentionable role, will result in the following error:
18:19:14.063 [error] GenServer #PID<0.240.0> terminating
** (BadMapError) expected a map, got: "123456"
(elixir) lib/map.ex:424: Map.get("123456", "avatar", nil)
(poison) lib/poison/decoder.ex:53: anonymous fn/3 in Poison.Decode.transform_struct/4
(stdlib) lists.erl:1263: :lists.foldl/3
(poison) lib/poison/decoder.ex:52: Poison.Decode.transform_struct/4
(poison) lib/poison/decoder.ex:24: anonymous fn/5 in Poison.Decode.transform/4
(elixir) lib/enum.ex:1826: Enum."-reduce/3-lists^foldl/2-0-"/3
(poison) lib/poison/decoder.ex:24: Poison.Decode.transform/4
(poison) lib/poison/decoder.ex:68: anonymous fn/6 in Poison.Decode.do_transform_struct/4
Here is a minimal project that reproduces the error: https://github.com/gerritwalther/nostrum_role_test.
It requires permission to create a role in the discord channel, but you can easily refactor it to use an existing role.
As far as I can see the problem occurs when handling the response from the Discord channel and Nostrum tries to decode the response with poison: https://github.com/kraigie/nostrum/blob/master/lib/nostrum/api.ex#L1755
Tell me if I can help to solve the problem, but my Elixir knowledge isn't that solid yet.
Like #49 , this is another issue for tracking changes that we do while working on fixing the Api. After the Api work is done, all Api functions should have the following documentation format:
@doc
attribute should use the ~S sigil.Here an example template for the create_guild_emoji/2
function.
@doc ~S"""
Creates a new emoji for the given guild.
This endpoint requires the `MANAGE_EMOJIS` permission. It fires the `GUILD_EMOJIS_UPDATE` event.
If successful, returns `{:ok, emoji}`. Otherwise, returns a `t:Nostrum.Api.error/0`.
## Options
* `:name` (string) - name of the emoji
* `:image` (base64 data URI) - the 128x128 emoji image. Maximum size of 256kb
* `:roles` (list of `t:Nostrum.Struct.Snowflake.t/0`) - roles for which this emoji will be whitelisted
(default: [])
`:name` and `:image` are always required.
## Examples
```Elixir
image = "data:image/png;base64,YXl5IGJieSB1IGx1a2luIDQgc3VtIGZ1az8="
Nostrum.Api.create_guild_emoji(43189401384091, name: "nostrum", image: image, roles: [])
```
"""
An example for delete_own_reaction/3
:
@doc ~S"""
Deletes a reaction made by the user.
If succesful, returns `{:ok}`. Otherwise, returns `t:Nostrum.Api.error/0`.
See `create_reaction/3` for similar examples.
"""
Nostrum.Api.get_user/1
are obsolete due to nostrum already having a cache. Shouldn't we document that these functions are obsolete?We will be addressing this by mentioning the cache and its usage in the Api module doc.
Cache get methods take keyword list for just one argument. It makes it harder to use pipes:
msg.channel_id |> ChannelCache.get!
doesn't work and I have to use msg.channel_id |> (&ChannelCache.get! id: &1).()
There is method that takes whole message, but it works only for normal get()
and not for banged get!()
:(
In the README it's stated that you have to fetch the 'dd1bfe4d6f9fb277781d922aa8bbb5648b3e6756' ref of gun to make the library work with OTP 20.
Doing so and then using the master branch (no ref/tag specified) of nostrum seems to have the same issue as without the supposed fix.
I'm running Elixir 1.5.2, OTP 20 and the specified dependency specifications. Any ideas on why this still seems to be an issue?
Here is the error message, for posterity's sake:
==> pomoshtnik_discord
Compiling 2 files (.ex)
Generated pomoshtnik_discord app
20:35:18.626 [error] SSL: :cipher: ssl_alert.erl:88:Fatal error: bad record mac
20:35:18.629 [error] SSL: :cipher: ssl_alert.erl:88:Fatal error: bad record mac
20:35:18.652 [error] SSL: :cipher: ssl_alert.erl:88:Fatal error: bad record mac
20:35:18.671 [error] SSL: :cipher: ssl_alert.erl:88:Fatal error: bad record mac
20:35:18.695 [error] SSL: :cipher: ssl_alert.erl:88:Fatal error: bad record mac
20:35:18.725 [error] SSL: :cipher: ssl_alert.erl:88:Fatal error: bad record mac
=INFO REPORT==== 14-Oct-2017::20:35:18 ===
application: logger
exited: stopped
type: temporary
** (Mix) Could not start application nostrum: Nostrum.start(:normal, []) returned an error: shutdown: failed to start child: Nostrum.Shard.Supervisor
** (EXIT) shutdown: failed to start child: 0
** (EXIT) shutdown: failed to start child: Nostrum.Shard.Session
** (EXIT) an exception was raised:
** (ErlangError) Erlang error: {:gone, {:tls_alert, 'bad record mac'}}
(gun) /home/gonz/code/elixir/pomoshtnik/deps/gun/src/gun.erl:596: :gun.retry/2
(gun) /home/gonz/code/elixir/pomoshtnik/deps/gun/src/gun.erl:528: :gun.proc_lib_hack/5
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Here is the lock-file:
%{"certifi": {:hex, :certifi, "1.0.0", "1c787a85b1855ba354f0b8920392c19aa1d06b0ee1362f9141279620a5be2039", [], [], "hexpm"},
"cowlib": {:git, "https://github.com/ninenines/cowlib", "bd37be4d3b065600c3b76b492535e76e5d413fc1", [ref: "master"]},
"gen_stage": {:hex, :gen_stage, "0.12.2", "e0e347cbb1ceb5f4e68a526aec4d64b54ad721f0a8b30aa9d28e0ad749419cbb", [], [], "hexpm"},
"gun": {:git, "https://github.com/ninenines/gun.git", "dd1bfe4d6f9fb277781d922aa8bbb5648b3e6756", [ref: "dd1bfe4d6f9fb277781d922aa8bbb5648b3e6756"]},
"hackney": {:hex, :hackney, "1.7.1", "e238c52c5df3c3b16ce613d3a51c7220a784d734879b1e231c9babd433ac1cb4", [], [{:certifi, "1.0.0", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "4.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "1.0.1", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "1.0.2", [hex: :mimerl, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "1.1.1", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}], "hexpm"},
"httpoison": {:hex, :httpoison, "0.11.1", "d06c571274c0e77b6cc50e548db3fd7779f611fbed6681fd60a331f66c143a0b", [], [{:hackney, "~> 1.7.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm"},
"idna": {:hex, :idna, "4.0.0", "10aaa9f79d0b12cf0def53038547855b91144f1bfcc0ec73494f38bb7b9c4961", [], [], "hexpm"},
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [], [], "hexpm"},
"mimerl": {:hex, :mimerl, "1.0.2", "993f9b0e084083405ed8252b99460c4f0563e41729ab42d9074fd5e52439be88", [], [], "hexpm"},
"nostrum": {:git, "https://github.com/Kraigie/nostrum", "06af555ea07fc09b340740eb7c10345551be8799", []},
"poison": {:hex, :poison, "3.1.0", "d9eb636610e096f86f25d9a46f35a9facac35609a7591b3be3326e99a0484665", [], [], "hexpm"},
"ranch": {:git, "https://github.com/ninenines/ranch", "70f9696b6c35d029ac7bce67485713aee3983917", [ref: "master"]},
"slack": {:hex, :slack, "0.12.0", "a305f87adca043e056a86f92151d085a8c359718f9c4ca7f1d1012d67b75db8a", [], [{:httpoison, "~> 0.11", [hex: :httpoison, repo: "hexpm", optional: false]}, {:poison, "~> 3.0", [hex: :poison, repo: "hexpm", optional: false]}, {:websocket_client, "~> 1.2.4", [hex: :websocket_client, repo: "hexpm", optional: false]}], "hexpm"},
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.1", "28a4d65b7f59893bc2c7de786dec1e1555bd742d336043fe644ae956c3497fbe", [], [], "hexpm"},
"websocket_client": {:hex, :websocket_client, "1.2.4", "14ec1ca4b6d247b44ccd9a80af8f6ca98328070f6c1d52a5cb00bc9d939d63b8", [], [], "hexpm"}}
I'm not sure there is much you can do about this, or if some hex package needs updating, but after upgrading to OpenSSL v1.1.0f I have been unable to start a nostrum bot. Here is a log of what it looks like when I attempt to start:
$ iex -S mix
Erlang/OTP 20 [erts-9.0] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
14:42:25.005 [error] SSL: :cipher: ssl_alert.erl:88:Fatal error: bad record mac
14:41:22.743 [error] SSL: :cipher: ssl_alert.erl:88:Fatal error: bad record mac
14:41:22.767 [error] SSL: :cipher: ssl_alert.erl:88:Fatal error: bad record mac
14:41:22.794 [error] SSL: :cipher: ssl_alert.erl:88:Fatal error: bad record mac
14:41:22.815 [error] SSL: :cipher: ssl_alert.erl:88:Fatal error: bad record mac
14:41:22.831 [info] Application nostrum exited: Nostrum.start(:normal, []) returned an error: shutdown: failed to start child: Nostrum.Shard.Supervisor
** (EXIT) shutdown: failed to start child: 0
** (EXIT) shutdown: failed to start child: Nostrum.Shard.Session
** (EXIT) normal
14:41:22.831 [info] Application gun exited: :stopped
14:41:22.831 [info] Application ranch exited: :stopped
14:41:22.831 [info] Application cowlib exited: :stopped
14:41:22.831 [info] Application httpoison exited: :stopped
14:41:22.831 [info] Application hackney exited: :stopped
14:41:22.831 [info] Application metrics exited: :stopped
14:41:22.831 [info] Application ssl_verify_fun exited: :stopped
14:41:22.831 [info] Application certifi exited: :stopped
14:41:22.831 [info] Application mimerl exited: :stopped
14:41:22.831 [info] Application idna exited: :stopped
14:41:22.831 [info] Application poison exited: :stopped
14:41:22.831 [info] Application gen_stage exited: :stopped
=INFO REPORT==== 19-Jul-2017::14:41:22 ===
application: logger
exited: stopped
type: temporary
** (Mix) Could not start application nostrum: Nostrum.start(:normal, []) returned an error: shutdown: failed to start child: Nostrum.Shard.Supervisor
** (EXIT) shutdown: failed to start child: 0
** (EXIT) shutdown: failed to start child: Nostrum.Shard.Session
** (EXIT) normal
Again, I've not really seen anything like this so I have no idea if this is an issue I created during the update to v1.1.0f or not. Any insight will be wonderful.
You can see the source of my code here: https://github.com/KumaKaiNi/discord-kuma
Thank you!
Reading from config.exs is bad practice for a library in general, but this both prehibits nostrum from being used to create a hedwig adapter and for a large spectrum of use-cases, including, for example, discord bots as a service, where users can input their own token, etc, and set up a bot under a custom bot account for their server.
Generating snowflake values has a few use cases:
nonce
in creating messagesThe bot randomly disconnected, and upon reconnect this appeared:
21:32:36.595 [info] websocket closed, attempting reconnect
21:32:36.992 [info] WAITING 5251 BEFORE NEXT SHARD CONNECT
21:32:37.045 [error] GenServer #PID<0.304.0> terminating
** (stop) :data_error
zlib.erl:558: :zlib.call/3
zlib.erl:270: :zlib.inflate/2
(nostrum) lib/nostrum/shard/session.ex:101: Nostrum.Shard.Session.handle_info/2
(stdlib) gen_server.erl:616: :gen_server.try_dispatch/4
(stdlib) gen_server.erl:686: :gen_server.handle_msg/6
(stdlib) proc_lib.erl:247: :proc_lib.init_p_do_apply/3
Last message: {:gun_ws, #PID<0.307.0>, {:binary, <<120, 156, 36, 204, 77, 14, 68, 64, 16, 197, 241, 231, 35, 22, 150, 18, 23, 176, 239, 51, 73, 153, 42, 180, 180, 70, 171, 24, 179, 118, 18, 55, 213, 19, 155, 151, 223, 219, 252, 47, 5, 144, 51, 18, 254, 35, 101, ...>>}}
State: %{gateway: 'gateway.discord.gg', gun_pid: #PID<0.307.0>,
21:32:37.046 [info] GenStage consumer #PID<0.313.0> is stopping after receiving cancel from producer #PID<0.306.0> with reason: {:data_error,
[{:zlib, :call, 3, [file: 'zlib.erl', line: 558]},
{:zlib, :inflate, 2, [file: 'zlib.erl', line: 270]},
{Nostrum.Shard.Session, :handle_info, 2,
[file: 'lib/nostrum/shard/session.ex', line: 101]},
{:gen_server, :try_dispatch, 4, [file: 'gen_server.erl', line: 616]},
{:gen_server, :handle_msg, 6, [file: 'gen_server.erl', line: 686]},
{:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 247]}]}
relevant line would be:
|> :zlib.inflate(new_buffer)
Is there a known issue with the CHANNEL_UPDATE
event when it's triggered by a permission overwrite? The consumer crashes when this occurs:
15:34:05.436 [error] GenServer #PID<0.437.0> terminating
** (stop) exited in: GenServer.call(#PID<0.435.0>, {:update, :channel, %Nostrum.Struct.Channel{application_id: nil, bitrate: nil, guild_id: 105713369939480576, icon: nil, id: 419255918199439363, last_message_id: 458680159143460864, last_pin_timestamp: nil, name: "bot-testing", nsfw: false, owner_id: nil, parent_id: nil, permission_overwrites: [%Nostrum.Struct.Overwrite{allow: 0, deny: 1024, id: 105713369939480576, name: nil}, %Nostrum.Struct.Overwrite{allow: 805829713, deny: 0, id: 168192499293224960, name: nil}], position: 24, recipients: nil, topic: nil, type: 0, user_limit: nil}}, 5000)
** (EXIT) an exception was raised:
** (Protocol.UndefinedError) protocol Enumerable not implemented for %Nostrum.Struct.Overwrite{allow: 0, deny: 1024, id: 105713369939480576, name: nil}. This protocol is implemented for: DBConnection.PrepareStream, DBConnection.Stream, Date.Range, File.Stream, Function, GenEvent.Stream, HashDict, HashSet, IO.Stream, List, Map, MapSet, Postgrex.Stream, Range, Stream
(elixir) /private/tmp/elixir-20180316-64850-zsrybb/elixir-1.6.4/lib/elixir/lib/enum.ex:1: Enumerable.impl_for!/1
(elixir) /private/tmp/elixir-20180316-64850-zsrybb/elixir-1.6.4/lib/elixir/lib/enum.ex:141: Enumerable.reduce/3
(elixir) lib/enum.ex:1911: Enum.reverse/1
(elixir) lib/enum.ex:2588: Enum.to_list/1
(elixir) lib/map.ex:192: Map.new/2
(nostrum) lib/nostrum/struct/overwrite.ex:44: Nostrum.Struct.Overwrite.to_struct/1
(elixir) lib/enum.ex:1294: Enum."-map/2-lists^map/1-0-"/2
(elixir) lib/map.ex:571: Map.update/4
Last message: {:DOWN, #Reference<0.1399560593.7340038.203953>, :process, #PID<0.436.0>, {{%Protocol.UndefinedError{description: "", protocol: Enumerable, value: %Nostrum.Struct.Overwrite{allow: 0, deny: 1024, id: 105713369939480576, name: nil}}, [{Enumerable, :impl_for!, 1, [file: '/private/tmp/elixir-20180316-64850-zsrybb/elixir-1.6.4/lib/elixir/lib/enum.ex', line: 1]}, {Enumerable, :reduce, 3, [file: '/private/tmp/elixir-20180316-64850-zsrybb/elixir-1.6.4/lib/elixir/lib/enum.ex', line: 141]}, {Enum, :reverse, 1, [file: 'lib/enum.ex', line: 1911]}, {Enum, :to_list, 1, [file: 'lib/enum.ex', line: 2588]}, {Map, :new, 2, [file: 'lib/map.ex', line: 192]}, {Nostrum.Struct.Overwrite, :to_struct, 1, [file: 'lib/nostrum/struct/overwrite.ex', line: 44]}, {Enum, :"-map/2-lists^map/1-0-", 2, [file: 'lib/enum.ex', line: 1294]}, {Map, :update, 4, [file: 'lib/map.ex', line: 571]}]}, {GenServer, :call, [#PID<0.435.0>, {:update, :channel, %Nostrum.Struct.Channel{application_id: nil, bitrate: nil, guild_id: 105713369939480576, icon: nil, id: 419255918199439363, last_message_id: 458680159143460864, last_pin_timestamp: nil, name: "bot-testing", nsfw: false, owner_id: nil, parent_id: nil, permission_overwrites: [%Nostrum.Struct.Overwrite{allow: 0, deny: 1024, id: 105713369939480576, name: nil}, %Nostrum.Struct.Overwrite{allow: 805829713, deny: 0, id: 168192499293224960, name: nil}], position: 24, recipients: nil, topic: nil, type: 0, user_limit: nil}}, 5000]}}}
State: %ConsumerSupervisor{args: [UsmcBot.Handler, []], children: %{}, max_restarts: 3, max_seconds: 5, mod: Nostrum.Consumer, name: {#PID<0.437.0>, Nostrum.Consumer}, producers: %{}, restarting: 0, restarts: [], strategy: :one_for_one, template: {UsmcBot.Handler, {UsmcBot.Handler, :start_link, []}, :transient, 5000, :worker, [UsmcBot.Handler]}}
The CDN URLs here and here should be moved to the constants folder.
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.