cronokirby / alchemy

A discord library for Elixir
MIT License
152 stars 34 forks source link

Endpoint Guilds.move_roles() encodes payload without crashing #111

Open aarontc opened 4 years ago

cronokirby commented 4 years ago

I'm unsure if this is the right thing to do here :thinking:

I'm pretty sure the Api.encode was there for a reason

aarontc commented 4 years ago

I'm unsure if this is the right thing to do here thinking

I'm pretty sure the Api.encode was there for a reason

The discord API endpoint expects an array of objects, just like the move_channels endpoint, which uses encoding at this level as well. It's working for me with the change. Before the change, this error occurred when calling Alchemy.Client.move_roles("<guild_id>", [{"299416349313073153", 9}]):

19:19:15.596 [error] ** (FunctionClauseError) no function clause matching in anonymous fn/2 in Collectable.Map.into/1
    (elixir 1.10.4) anonymous fn(%{}, {:cont, %{id: "299416349313073153", position: 9}}) in Collectable.Map.into/1
    (elixir 1.10.4) lib/enum.ex:3383: anonymous fn/3 in Enum.into/4
    (elixir 1.10.4) lib/stream.ex:1597: anonymous fn/3 in Enumerable.Stream.reduce/3
    (elixir 1.10.4) lib/enum.ex:3686: Enumerable.List.reduce/3
    (elixir 1.10.4) lib/stream.ex:1609: Enumerable.Stream.do_each/4
    (elixir 1.10.4) lib/enum.ex:3383: Enum.into/4
    (alchemy 0.6.5) lib/Discord/api.ex:10: Alchemy.Discord.Api.encode/1
    (alchemy 0.6.5) lib/Discord/Endpoints/guilds.ex:134: Alchemy.Discord.Guilds.move_roles/3

Edit: Here's the reference https://github.com/cronokirby/alchemy/blob/4c64e5c619977a62a5674dbd2b1ef29f76f6f44e/lib/Discord/Endpoints/guilds.ex#L48

aramsm commented 4 years ago

@cronokirby I was checking Api.encode/1, it converts a value (opts) into a map and then encodes using Poison.encode!/2 (code). So, since Guilds.move_role/3 returns a Stream the Enum.into breaks:

iex(1)> tuples = [{"12", 1}, {"13", 2}]
[{"12", 1}, {"13", 2}]
iex(2)> r = Stream.map(tuples, fn {id, pos} -> %{id: id, position: pos} end)
#Stream<enum: [{"12", 1}, {"13", 2}], funs: [#Function<48.35876588/1 in Stream.map/2>]]>
iex(3)> r |> Enum.into(%{})
** (FunctionClauseError) no function clause matching in anonymous fn/2 in Collectable.Map.into/1    

    The following arguments were given to anonymous fn/2 in Collectable.Map.into/1:

        # 1
        %{}

        # 2
        {:cont, %{id: "12", position: 1}}

    (elixir 1.10.2) lib/collectable.ex:145: anonymous fn/2 in Collectable.Map.into/1
    (elixir 1.10.2) lib/enum.ex:3383: anonymous fn/3 in Enum.into/4
    (elixir 1.10.2) lib/stream.ex:1597: anonymous fn/3 in Enumerable.Stream.reduce/3
    (elixir 1.10.2) lib/enum.ex:3686: Enumerable.List.reduce/3
    (elixir 1.10.2) lib/stream.ex:1609: Enumerable.Stream.do_each/4
    (elixir 1.10.2) lib/enum.ex:3383: Enum.into/4

With Poison.encode!:

iex(4)> r |> Poison.encode!
"[{\"position\":1,\"id\":\"12\"},{\"position\":2,\"id\":\"13\"}]"