Skip to content

Commit

Permalink
add support for changing voice state
Browse files Browse the repository at this point in the history
  • Loading branch information
Kraigie committed Jul 23, 2019
1 parent a45eda5 commit 4a6642d
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 2 deletions.
14 changes: 14 additions & 0 deletions lib/nostrum/api.ex
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,20 @@ defmodule Nostrum.Api do
:ok
end

@doc """
Joins, moves, or disconnects the bot from a voice channel.
The correct shard to send the update to will be inferred from the
`guild_id`. If a corresponding `guild_id` is not found a cache error will be
raised.
To disconnect from a channel, `channel_id` should be set to `nil`.
"""
@spec update_voice_state(Guild.id(), Channel.id(), boolean, boolean) :: no_return | :ok
def update_voice_state(guild_id, channel_id, self_mute \\ false, self_deaf \\ false) do
Supervisor.update_voice_state(guild_id, channel_id, self_mute, self_deaf)
end

@doc ~S"""
Posts a message to a guild text or DM channel.
Expand Down
2 changes: 0 additions & 2 deletions lib/nostrum/cache/mapping/guild_shard.ex
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,6 @@ defmodule Nostrum.Cache.Mapping.GuildShard do
"""
@spec get_shard(Guild.id()) :: {:ok, integer} | {:error, :id_not_found}
def get_shard(guild_id) do
:ets.lookup_element(:guild_shard_map, guild_id, 2)

case :ets.lookup(:guild_shard_map, guild_id) do
[{_guild_id, shard_num}] -> {:ok, shard_num}
[] -> {:error, :id_not_found}
Expand Down
11 changes: 11 additions & 0 deletions lib/nostrum/shard/payload.ex
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ defmodule Nostrum.Shard.Payload do
|> build_payload("STATUS_UPDATE")
end

@doc false
def update_voice_state_payload(guild_id, channel_id, self_mute, self_deaf) do
%{
"guild_id" => guild_id,
"channel_id" => channel_id,
"self_mute" => self_mute,
"self_deaf" => self_deaf
}
|> build_payload("VOICE_STATUS_UPDATE")
end

@doc false
def request_members_payload(guild_id, limit) do
%{
Expand Down
9 changes: 9 additions & 0 deletions lib/nostrum/shard/session.ex
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ defmodule Nostrum.Shard.Session do
WebSockex.cast(pid, {:status_update, payload})
end

def update_voice_state(pid, guild_id, channel_id, self_mute, self_deaf) do
payload = Payload.update_voice_state_payload(guild_id, channel_id, self_mute, self_deaf)
WebSockex.cast(pid, {:update_voice_state, payload})
end

def request_guild_members(pid, guild_id, limit \\ 0) do
payload = Payload.request_members_payload(guild_id, limit)
WebSockex.cast(pid, {:request_guild_members, payload})
Expand Down Expand Up @@ -92,6 +97,10 @@ defmodule Nostrum.Shard.Session do
{:reply, {:binary, payload}, state}
end

def handle_cast({:update_voice_state, payload}, state) do
{:reply, {:binary, payload}, state}
end

def handle_cast({:request_guild_members, payload}, state) do
{:reply, {:binary, payload}, state}
end
Expand Down
21 changes: 21 additions & 0 deletions lib/nostrum/shard/supervisor.ex
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ defmodule Nostrum.Shard.Supervisor do
use Supervisor

alias Nostrum.{Shard, Util}
alias Nostrum.Cache.Mapping.GuildShard
alias Nostrum.Error.CacheError
alias Nostrum.Shard.Session
alias Nostrum.Shard.Stage.{Cache, Producer}

Expand Down Expand Up @@ -48,6 +50,25 @@ defmodule Nostrum.Shard.Supervisor do
end)
end

def update_voice_state(guild_id, channel_id, self_mute, self_deaf) do
case GuildShard.get_shard(guild_id) do
{:ok, shard_id} ->
ShardSupervisor
|> Supervisor.which_children()
|> Enum.filter(fn {_id, _pid, _type, [modules]} -> modules == Nostrum.Shard end)
|> Enum.filter(fn {id, _pid, _type, _modules} -> id == shard_id end)
|> Enum.map(fn {_id, pid, _type, _modules} -> Supervisor.which_children(pid) end)
|> List.flatten()
|> Enum.filter(fn {_id, _pid, _type, [modules]} -> modules == Nostrum.Shard.Session end)
|> List.first()
|> elem(1)
|> Session.update_voice_state(guild_id, channel_id, self_mute, self_deaf)

{:error, :id_not_found} ->
raise CacheError, key: guild_id, cache_name: GuildShardMapping
end
end

@doc false
def init([url, num_shards]) do
children =
Expand Down

0 comments on commit 4a6642d

Please # to comment.