mirror of
https://github.com/processone/ejabberd
synced 2025-10-03 01:39:35 +02:00
Better Matrix room topic and room roles to MUC conversion, support room aliases in invites
This commit is contained in:
parent
2a85c0a474
commit
30a7b0ef3b
2 changed files with 87 additions and 16 deletions
|
@ -148,7 +148,7 @@ process([<<"federation">>, <<"v2">>, <<"invite">>, RoomID, EventID],
|
||||||
<<"room_id">> := RoomID,
|
<<"room_id">> := RoomID,
|
||||||
<<"sender">> := Sender,
|
<<"sender">> := Sender,
|
||||||
<<"state_key">> := UserID} = Event,
|
<<"state_key">> := UserID} = Event,
|
||||||
<<"room_version">> := RoomVer},
|
<<"room_version">> := RoomVer} = JSON,
|
||||||
Origin} ->
|
Origin} ->
|
||||||
case mod_matrix_gw_room:binary_to_room_version(RoomVer) of
|
case mod_matrix_gw_room:binary_to_room_version(RoomVer) of
|
||||||
#room_version{} = RoomVersion ->
|
#room_version{} = RoomVersion ->
|
||||||
|
@ -167,7 +167,11 @@ process([<<"federation">>, <<"v2">>, <<"invite">>, RoomID, EventID],
|
||||||
#{<<"is_direct">> := true} ->
|
#{<<"is_direct">> := true} ->
|
||||||
mod_matrix_gw_room:join_direct(Host, Origin, RoomID, Sender, UserID);
|
mod_matrix_gw_room:join_direct(Host, Origin, RoomID, Sender, UserID);
|
||||||
_ ->
|
_ ->
|
||||||
mod_matrix_gw_room:send_muc_invite(Host, Origin, RoomID, Sender, UserID, Event)
|
IRS = case JSON of
|
||||||
|
#{<<"invite_room_state">> := IRS1} -> IRS1;
|
||||||
|
_ -> []
|
||||||
|
end,
|
||||||
|
mod_matrix_gw_room:send_muc_invite(Host, Origin, RoomID, Sender, UserID, Event, IRS)
|
||||||
end,
|
end,
|
||||||
?DEBUG("res ~s~n", [misc:json_encode(ResJSON)]),
|
?DEBUG("res ~s~n", [misc:json_encode(ResJSON)]),
|
||||||
{200, [{<<"Content-Type">>, <<"application/json;charset=UTF-8">>}], misc:json_encode(ResJSON)};
|
{200, [{<<"Content-Type">>, <<"application/json;charset=UTF-8">>}], misc:json_encode(ResJSON)};
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
create_new_room/3, room_add_event/3,
|
create_new_room/3, room_add_event/3,
|
||||||
binary_to_room_version/1,
|
binary_to_room_version/1,
|
||||||
parse_user_id/1,
|
parse_user_id/1,
|
||||||
send_muc_invite/6,
|
send_muc_invite/7,
|
||||||
escape/1, unescape/1,
|
escape/1, unescape/1,
|
||||||
route/1]).
|
route/1]).
|
||||||
|
|
||||||
|
@ -102,6 +102,7 @@
|
||||||
-define(ROOM_3PI, <<"m.room.third_party_invite">>).
|
-define(ROOM_3PI, <<"m.room.third_party_invite">>).
|
||||||
-define(ROOM_MESSAGE, <<"m.room.message">>).
|
-define(ROOM_MESSAGE, <<"m.room.message">>).
|
||||||
-define(ROOM_HISTORY_VISIBILITY, <<"m.room.history_visibility">>).
|
-define(ROOM_HISTORY_VISIBILITY, <<"m.room.history_visibility">>).
|
||||||
|
-define(ROOM_TOPIC, <<"m.room.topic">>).
|
||||||
|
|
||||||
-define(MAX_DEPTH, 16#7FFFFFFFFFFFFFFF).
|
-define(MAX_DEPTH, 16#7FFFFFFFFFFFFFFF).
|
||||||
-define(MAX_TXN_RETRIES, 5).
|
-define(MAX_TXN_RETRIES, 5).
|
||||||
|
@ -1206,6 +1207,16 @@ do_auth_and_store_external_events(EventList, Data) ->
|
||||||
auth_and_store_external_events(Pid, EventList) ->
|
auth_and_store_external_events(Pid, EventList) ->
|
||||||
gen_statem:call(Pid, {auth_and_store_external_events, EventList}).
|
gen_statem:call(Pid, {auth_and_store_external_events, EventList}).
|
||||||
|
|
||||||
|
statemap_find(Key, StateMap, Data) ->
|
||||||
|
case maps:find(Key, StateMap) of
|
||||||
|
{ok, #event{}} = Res ->
|
||||||
|
Res;
|
||||||
|
{ok, EventID} when is_binary(EventID) ->
|
||||||
|
maps:find(EventID, Data#data.events);
|
||||||
|
error ->
|
||||||
|
error
|
||||||
|
end.
|
||||||
|
|
||||||
check_event_auth(Event, Data) ->
|
check_event_auth(Event, Data) ->
|
||||||
StateMap =
|
StateMap =
|
||||||
maps:from_list(
|
maps:from_list(
|
||||||
|
@ -1572,7 +1583,7 @@ get_event_power_level(Type, PL) ->
|
||||||
get_user_power_level(User, StateMap, Data) ->
|
get_user_power_level(User, StateMap, Data) ->
|
||||||
RoomVersion = Data#data.room_version,
|
RoomVersion = Data#data.room_version,
|
||||||
PL =
|
PL =
|
||||||
case maps:find({?ROOM_POWER_LEVELS, <<"">>}, StateMap) of
|
case statemap_find({?ROOM_POWER_LEVELS, <<"">>}, StateMap, Data) of
|
||||||
{ok, #event{json = #{<<"content">> := C}}} -> C;
|
{ok, #event{json = #{<<"content">> := C}}} -> C;
|
||||||
_ -> #{}
|
_ -> #{}
|
||||||
end,
|
end,
|
||||||
|
@ -1580,12 +1591,12 @@ get_user_power_level(User, StateMap, Data) ->
|
||||||
#{<<"users">> := #{User := Level}} -> get_int(Level);
|
#{<<"users">> := #{User := Level}} -> get_int(Level);
|
||||||
#{<<"users_default">> := Level} -> get_int(Level);
|
#{<<"users_default">> := Level} -> get_int(Level);
|
||||||
_ ->
|
_ ->
|
||||||
case {RoomVersion#room_version.implicit_room_creator, StateMap} of
|
case {RoomVersion#room_version.implicit_room_creator,
|
||||||
|
statemap_find({?ROOM_CREATE, <<"">>}, StateMap, Data)} of
|
||||||
{false,
|
{false,
|
||||||
#{{?ROOM_CREATE, <<"">>} :=
|
{ok, #event{json = #{<<"content">> := #{<<"creator">> := User}}}}} ->
|
||||||
#event{json = #{<<"content">> := #{<<"creator">> := User}}}}} ->
|
|
||||||
100;
|
100;
|
||||||
{true, #{{?ROOM_CREATE, <<"">>} := #event{sender = User}}} ->
|
{true, {ok, #event{sender = User}}} ->
|
||||||
100;
|
100;
|
||||||
_ ->
|
_ ->
|
||||||
0
|
0
|
||||||
|
@ -2744,8 +2755,9 @@ notify_event_xmpp(
|
||||||
false
|
false
|
||||||
end,
|
end,
|
||||||
UserJID = jid:make(LUser, LServer, LResource),
|
UserJID = jid:make(LUser, LServer, LResource),
|
||||||
Item = #muc_item{affiliation = member,
|
Item =
|
||||||
role = participant},
|
get_user_muc_item(
|
||||||
|
Sender, Event#event.state_map, Data),
|
||||||
Status = case IsSelfPresence of
|
Status = case IsSelfPresence of
|
||||||
true -> [110];
|
true -> [110];
|
||||||
false -> []
|
false -> []
|
||||||
|
@ -2760,12 +2772,24 @@ notify_event_xmpp(
|
||||||
ejabberd_router:route(Pres),
|
ejabberd_router:route(Pres),
|
||||||
case IsSelfPresence of
|
case IsSelfPresence of
|
||||||
true ->
|
true ->
|
||||||
|
Topic =
|
||||||
|
case Event#event.state_map of
|
||||||
|
#{{?ROOM_TOPIC, <<"">>} := TEID} ->
|
||||||
|
case maps:find(TEID, Data#data.events) of
|
||||||
|
{ok, #event{json = #{<<"content">> := #{<<"topic">> := T}}}} when is_binary(T) ->
|
||||||
|
T;
|
||||||
|
_ ->
|
||||||
|
<<"">>
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
<<"">>
|
||||||
|
end,
|
||||||
Subject =
|
Subject =
|
||||||
#message{
|
#message{
|
||||||
from = RoomJID,
|
from = RoomJID,
|
||||||
to = UserJID,
|
to = UserJID,
|
||||||
type = groupchat,
|
type = groupchat,
|
||||||
subject = [#text{}]
|
subject = [#text{data = Topic}]
|
||||||
},
|
},
|
||||||
ejabberd_router:route(Subject);
|
ejabberd_router:route(Subject);
|
||||||
false -> ok
|
false -> ok
|
||||||
|
@ -2795,7 +2819,7 @@ notify_event_xmpp(
|
||||||
when JoinTS =< OriginTS ->
|
when JoinTS =< OriginTS ->
|
||||||
From = jid:replace_resource(RoomJID, RUser),
|
From = jid:replace_resource(RoomJID, RUser),
|
||||||
UserJID = jid:make(LUser, LServer, LResource),
|
UserJID = jid:make(LUser, LServer, LResource),
|
||||||
Item = #muc_item{affiliation = member,
|
Item = #muc_item{affiliation = none,
|
||||||
role = none},
|
role = none},
|
||||||
Pres = #presence{from = From,
|
Pres = #presence{from = From,
|
||||||
to = UserJID,
|
to = UserJID,
|
||||||
|
@ -2843,11 +2867,13 @@ send_initial_presences(JID, RoomJID, Event, Data) ->
|
||||||
fun({?ROOM_MEMBER, _}, EID, ok) ->
|
fun({?ROOM_MEMBER, _}, EID, ok) ->
|
||||||
case maps:find(EID, Data#data.events) of
|
case maps:find(EID, Data#data.events) of
|
||||||
{ok, #event{
|
{ok, #event{
|
||||||
sender = <<$@, SenderUser/binary>>,
|
sender = <<$@, SenderUser/binary>> = Sender,
|
||||||
json = #{<<"content">> :=
|
json = #{<<"content">> :=
|
||||||
#{<<"membership">> := <<"join">>}}}} ->
|
#{<<"membership">> := <<"join">>}}}} ->
|
||||||
From = jid:replace_resource(RoomJID, SenderUser),
|
From = jid:replace_resource(RoomJID, SenderUser),
|
||||||
Item = #muc_item{affiliation = member, role = participant},
|
Item =
|
||||||
|
get_user_muc_item(
|
||||||
|
Sender, Event#event.state_map, Data),
|
||||||
Pres = #presence{from = From,
|
Pres = #presence{from = From,
|
||||||
to = JID,
|
to = JID,
|
||||||
type = available,
|
type = available,
|
||||||
|
@ -2862,6 +2888,23 @@ send_initial_presences(JID, RoomJID, Event, Data) ->
|
||||||
ok
|
ok
|
||||||
end, ok, Event#event.state_map).
|
end, ok, Event#event.state_map).
|
||||||
|
|
||||||
|
get_user_muc_item(User, StateMap, Data) ->
|
||||||
|
SenderLevel = get_user_power_level(User, StateMap, Data),
|
||||||
|
BanLevel =
|
||||||
|
case statemap_find({?ROOM_POWER_LEVELS, <<"">>}, StateMap, Data) of
|
||||||
|
{ok, #event{json = #{<<"content">> := #{<<"ban">> := S}}}} ->
|
||||||
|
get_int(S);
|
||||||
|
_ -> 50
|
||||||
|
end,
|
||||||
|
if
|
||||||
|
SenderLevel >= BanLevel ->
|
||||||
|
#muc_item{affiliation = admin,
|
||||||
|
role = moderator};
|
||||||
|
true ->
|
||||||
|
#muc_item{affiliation = member,
|
||||||
|
role = participant}
|
||||||
|
end.
|
||||||
|
|
||||||
|
|
||||||
send_new_txn(Events, Server, Data) ->
|
send_new_txn(Events, Server, Data) ->
|
||||||
TxnID = p1_rand:get_string(),
|
TxnID = p1_rand:get_string(),
|
||||||
|
@ -3198,12 +3241,36 @@ update_client(#data{kind = #multi{users = Users}} = Data) ->
|
||||||
end.
|
end.
|
||||||
|
|
||||||
|
|
||||||
send_muc_invite(Host, Origin, RoomID, Sender, UserID, Event) ->
|
send_muc_invite(Host, Origin, RoomID, Sender, UserID, Event, IRS) ->
|
||||||
case {user_id_to_jid(Sender, Host), user_id_to_jid(UserID, Host)} of
|
case {user_id_to_jid(Sender, Host), user_id_to_jid(UserID, Host)} of
|
||||||
{#jid{} = SenderJID, #jid{lserver = Host} = UserJID} ->
|
{#jid{} = SenderJID, #jid{lserver = Host} = UserJID} ->
|
||||||
process_pdu(Host, Origin, Event),
|
process_pdu(Host, Origin, Event),
|
||||||
ServiceHost = mod_matrix_gw_opt:host(Host),
|
ServiceHost = mod_matrix_gw_opt:host(Host),
|
||||||
{ok, EscRoomID} = room_id_to_xmpp(RoomID),
|
Alias =
|
||||||
|
lists:foldl(
|
||||||
|
fun(#{<<"type">> := <<"m.room.canonical_alias">>,
|
||||||
|
<<"content">> := #{<<"alias">> := A}}, _)
|
||||||
|
when is_binary(A) -> A;
|
||||||
|
(_, Acc) -> Acc
|
||||||
|
end, none, IRS),
|
||||||
|
{ok, EscRoomID} =
|
||||||
|
case Alias of
|
||||||
|
<<$#, Parts/binary>> ->
|
||||||
|
case binary:split(Parts, <<":">>) of
|
||||||
|
[R, S] ->
|
||||||
|
User = <<$#, R/binary, $%, S/binary>>,
|
||||||
|
case jid:nodeprep(User) of
|
||||||
|
error ->
|
||||||
|
room_id_to_xmpp(RoomID);
|
||||||
|
_ ->
|
||||||
|
{ok, User}
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
room_id_to_xmpp(RoomID)
|
||||||
|
end;
|
||||||
|
_ ->
|
||||||
|
room_id_to_xmpp(RoomID)
|
||||||
|
end,
|
||||||
RoomJID = jid:make(EscRoomID, ServiceHost),
|
RoomJID = jid:make(EscRoomID, ServiceHost),
|
||||||
Invite = #muc_invite{to = undefined, from = SenderJID},
|
Invite = #muc_invite{to = undefined, from = SenderJID},
|
||||||
XUser = #muc_user{invites = [Invite]},
|
XUser = #muc_user{invites = [Invite]},
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue