refactor progress
This commit is contained in:
@@ -20,9 +20,17 @@
|
||||
-export([switch_voice_region_handler/2]).
|
||||
-export([switch_voice_region/3]).
|
||||
|
||||
-type guild_state() :: map().
|
||||
-type guild_reply(T) :: {reply, T, guild_state()}.
|
||||
-type voice_state() :: map().
|
||||
|
||||
-ifdef(TEST).
|
||||
-include_lib("eunit/include/eunit.hrl").
|
||||
-endif.
|
||||
|
||||
-spec switch_voice_region_handler(map(), guild_state()) -> guild_reply(map()).
|
||||
switch_voice_region_handler(Request, State) ->
|
||||
#{channel_id := ChannelId} = Request,
|
||||
|
||||
Channel = guild_voice_member:find_channel_by_id(ChannelId, State),
|
||||
case Channel of
|
||||
undefined ->
|
||||
@@ -37,42 +45,21 @@ switch_voice_region_handler(Request, State) ->
|
||||
end
|
||||
end.
|
||||
|
||||
-spec switch_voice_region(integer(), integer(), pid()) -> ok.
|
||||
switch_voice_region(GuildId, ChannelId, GuildPid) ->
|
||||
case gen_server:call(GuildPid, {get_sessions}, 10000) of
|
||||
State when is_map(State) ->
|
||||
VoiceStates = voice_state_utils:voice_states(State),
|
||||
|
||||
UsersInChannel = maps:fold(
|
||||
fun(ConnectionId, VoiceState, Acc) ->
|
||||
case voice_state_utils:voice_state_channel_id(VoiceState) of
|
||||
ChannelId ->
|
||||
case voice_state_utils:voice_state_user_id(VoiceState) of
|
||||
undefined ->
|
||||
logger:warning(
|
||||
"[guild_voice_region] Missing user_id for connection ~p",
|
||||
[ConnectionId]
|
||||
),
|
||||
Acc;
|
||||
UserId ->
|
||||
SessionId = maps:get(<<"session_id">>, VoiceState, undefined),
|
||||
[{UserId, SessionId, VoiceState} | Acc]
|
||||
end;
|
||||
_ ->
|
||||
Acc
|
||||
end
|
||||
end,
|
||||
[],
|
||||
VoiceStates
|
||||
),
|
||||
|
||||
UsersInChannel = collect_users_in_channel(VoiceStates, ChannelId),
|
||||
lists:foreach(
|
||||
fun({UserId, SessionId, VoiceState}) ->
|
||||
fun({UserId, SessionId, ExistingConnectionId, VoiceState}) ->
|
||||
case SessionId of
|
||||
undefined ->
|
||||
ok;
|
||||
_ ->
|
||||
send_voice_server_update_for_region_switch(
|
||||
GuildId, ChannelId, UserId, SessionId, VoiceState, GuildPid
|
||||
GuildId, ChannelId, UserId, SessionId, ExistingConnectionId,
|
||||
VoiceState, GuildPid
|
||||
)
|
||||
end
|
||||
end,
|
||||
@@ -82,42 +69,61 @@ switch_voice_region(GuildId, ChannelId, GuildPid) ->
|
||||
ok
|
||||
end.
|
||||
|
||||
-spec collect_users_in_channel(map(), integer()) ->
|
||||
[{integer(), binary() | undefined, binary(), voice_state()}].
|
||||
collect_users_in_channel(VoiceStates, ChannelId) ->
|
||||
maps:fold(
|
||||
fun(ConnectionId, VoiceState, Acc) ->
|
||||
case voice_state_utils:voice_state_channel_id(VoiceState) of
|
||||
ChannelId ->
|
||||
case voice_state_utils:voice_state_user_id(VoiceState) of
|
||||
undefined ->
|
||||
Acc;
|
||||
UserId ->
|
||||
SessionId = maps:get(<<"session_id">>, VoiceState, undefined),
|
||||
[{UserId, SessionId, ConnectionId, VoiceState} | Acc]
|
||||
end;
|
||||
_ ->
|
||||
Acc
|
||||
end
|
||||
end,
|
||||
[],
|
||||
VoiceStates
|
||||
).
|
||||
|
||||
-spec send_voice_server_update_for_region_switch(
|
||||
integer(), integer(), integer(), binary(), binary(), voice_state(), pid()
|
||||
) -> ok.
|
||||
send_voice_server_update_for_region_switch(
|
||||
GuildId, ChannelId, UserId, SessionId, ExistingVoiceState, GuildPid
|
||||
GuildId, ChannelId, UserId, SessionId, ExistingConnectionId, ExistingVoiceState, GuildPid
|
||||
) ->
|
||||
case gen_server:call(GuildPid, {get_sessions}, 10000) of
|
||||
State when is_map(State) ->
|
||||
VoicePermissions = voice_utils:compute_voice_permissions(UserId, ChannelId, State),
|
||||
TokenNonce = voice_utils:generate_token_nonce(),
|
||||
case
|
||||
guild_voice_connection:request_voice_token(
|
||||
GuildId, ChannelId, UserId, VoicePermissions
|
||||
GuildId, ChannelId, UserId, ExistingConnectionId, VoicePermissions, TokenNonce
|
||||
)
|
||||
of
|
||||
{ok, TokenData} ->
|
||||
Token = maps:get(token, TokenData),
|
||||
Endpoint = maps:get(endpoint, TokenData),
|
||||
ConnectionId = maps:get(connection_id, TokenData),
|
||||
|
||||
PendingMetadata = #{
|
||||
user_id => UserId,
|
||||
guild_id => GuildId,
|
||||
channel_id => ChannelId,
|
||||
session_id => SessionId,
|
||||
self_mute => maps:get(<<"self_mute">>, ExistingVoiceState, false),
|
||||
self_deaf => maps:get(<<"self_deaf">>, ExistingVoiceState, false),
|
||||
self_video => maps:get(<<"self_video">>, ExistingVoiceState, false),
|
||||
self_stream => maps:get(<<"self_stream">>, ExistingVoiceState, false),
|
||||
is_mobile => maps:get(<<"is_mobile">>, ExistingVoiceState, false),
|
||||
server_mute => maps:get(<<"mute">>, ExistingVoiceState, false),
|
||||
server_deaf => maps:get(<<"deaf">>, ExistingVoiceState, false),
|
||||
member => maps:get(<<"member">>, ExistingVoiceState, #{})
|
||||
},
|
||||
gen_server:cast(
|
||||
GuildPid, {store_pending_connection, ConnectionId, PendingMetadata}
|
||||
PendingMetadata = build_pending_metadata(
|
||||
UserId, GuildId, ChannelId, SessionId, ExistingVoiceState, TokenNonce
|
||||
),
|
||||
_ = gen_server:call(
|
||||
GuildPid, {store_pending_connection, ConnectionId, PendingMetadata}, 10000
|
||||
),
|
||||
|
||||
guild_voice_broadcast:broadcast_voice_server_update_to_session(
|
||||
GuildId, SessionId, Token, Endpoint, ConnectionId, State
|
||||
GuildId,
|
||||
ChannelId,
|
||||
SessionId,
|
||||
Token,
|
||||
Endpoint,
|
||||
ConnectionId,
|
||||
State
|
||||
);
|
||||
{error, _Reason} ->
|
||||
ok
|
||||
@@ -125,3 +131,73 @@ send_voice_server_update_for_region_switch(
|
||||
_ ->
|
||||
ok
|
||||
end.
|
||||
|
||||
-spec build_pending_metadata(integer(), integer(), integer(), binary(), voice_state(), binary()) -> map().
|
||||
build_pending_metadata(UserId, GuildId, ChannelId, SessionId, ExistingVoiceState, TokenNonce) ->
|
||||
Now = erlang:system_time(millisecond),
|
||||
#{
|
||||
user_id => UserId,
|
||||
guild_id => GuildId,
|
||||
channel_id => ChannelId,
|
||||
session_id => SessionId,
|
||||
self_mute => maps:get(<<"self_mute">>, ExistingVoiceState, false),
|
||||
self_deaf => maps:get(<<"self_deaf">>, ExistingVoiceState, false),
|
||||
self_video => maps:get(<<"self_video">>, ExistingVoiceState, false),
|
||||
self_stream => maps:get(<<"self_stream">>, ExistingVoiceState, false),
|
||||
is_mobile => maps:get(<<"is_mobile">>, ExistingVoiceState, false),
|
||||
server_mute => maps:get(<<"mute">>, ExistingVoiceState, false),
|
||||
server_deaf => maps:get(<<"deaf">>, ExistingVoiceState, false),
|
||||
member => maps:get(<<"member">>, ExistingVoiceState, #{}),
|
||||
viewer_stream_keys => [],
|
||||
token_nonce => TokenNonce,
|
||||
created_at => Now,
|
||||
expires_at => Now + 30000
|
||||
}.
|
||||
|
||||
-ifdef(TEST).
|
||||
|
||||
switch_voice_region_handler_not_found_test() ->
|
||||
State = #{data => #{<<"channels">> => []}},
|
||||
Request = #{channel_id => 999},
|
||||
{reply, Error, _} = switch_voice_region_handler(Request, State),
|
||||
?assertEqual({error, not_found, voice_channel_not_found}, Error).
|
||||
|
||||
switch_voice_region_handler_not_voice_test() ->
|
||||
State = #{
|
||||
data => #{
|
||||
<<"channels">> => [
|
||||
#{<<"id">> => <<"100">>, <<"type">> => 0}
|
||||
]
|
||||
}
|
||||
},
|
||||
Request = #{channel_id => 100},
|
||||
{reply, Error, _} = switch_voice_region_handler(Request, State),
|
||||
?assertEqual({error, validation_error, voice_channel_not_voice}, Error).
|
||||
|
||||
switch_voice_region_handler_success_test() ->
|
||||
State = #{
|
||||
data => #{
|
||||
<<"channels">> => [
|
||||
#{<<"id">> => <<"100">>, <<"type">> => 2}
|
||||
]
|
||||
}
|
||||
},
|
||||
Request = #{channel_id => 100},
|
||||
{reply, Reply, _} = switch_voice_region_handler(Request, State),
|
||||
?assertEqual(true, maps:get(success, Reply)).
|
||||
|
||||
collect_users_in_channel_test() ->
|
||||
VoiceState = #{
|
||||
<<"channel_id">> => <<"100">>,
|
||||
<<"user_id">> => <<"10">>,
|
||||
<<"session_id">> => <<"sess1">>
|
||||
},
|
||||
VoiceStates = #{<<"conn1">> => VoiceState},
|
||||
Result = collect_users_in_channel(VoiceStates, 100),
|
||||
?assertEqual(1, length(Result)),
|
||||
[{UserId, SessionId, ConnectionId, _}] = Result,
|
||||
?assertEqual(10, UserId),
|
||||
?assertEqual(<<"sess1">>, SessionId),
|
||||
?assertEqual(<<"conn1">>, ConnectionId).
|
||||
|
||||
-endif.
|
||||
|
||||
Reference in New Issue
Block a user