From db522b75477d4c12e70f5ea322eb979af7cf9687 Mon Sep 17 00:00:00 2001 From: Hans Svensson Date: Mon, 8 Jun 2020 15:04:52 +0200 Subject: [PATCH 1/2] Keep roster room status for member when patching room --- apps/roster/src/protocol/roster_room.erl | 6 ++++-- apps/roster/src/roster.erl | 16 +++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/apps/roster/src/protocol/roster_room.erl b/apps/roster/src/protocol/roster_room.erl index c177d1890..71b02cdce 100644 --- a/apps/roster/src/protocol/roster_room.erl +++ b/apps/roster/src/protocol/roster_room.erl @@ -69,8 +69,10 @@ info(#'Room'{status = patch, id = Room, name = Name, data = AvatarDesc} = R, Req #'Member'{status = admin, phone_id = PId} -> case R3 = roster:patch_room(R2, R) of #error{} = E -> #io{code = E}; - #'Room'{} -> R4 = R3#'Room'{admins = [], members = []}, - [roster:update_rooms(PhoneId, R4) || #'Member'{phone_id = PhoneId} <- roster:members(#muc{name = Room})], + #'Room'{} -> + R4 = R3#'Room'{admins = [], members = []}, + [roster:update_rooms(PhoneId, R4#'Room'{status = keep}) + || #'Member'{phone_id = PhoneId} <- roster:members(#muc{name = Room}, active)], RoomFeed = #muc{name = Room}, %% check was Room.name changed NameLastMsgId = case Name of diff --git a/apps/roster/src/roster.erl b/apps/roster/src/roster.erl index 057d9a5f9..9f1804df6 100644 --- a/apps/roster/src/roster.erl +++ b/apps/roster/src/roster.erl @@ -1211,7 +1211,15 @@ update_rooms(RosterId, #'Room'{status = Status} = R) when is_integer(RosterId) - case kvs:get('Roster', RosterId) of {error, _} -> {error, roster_not_found}; {ok, #'Roster'{roomlist = Rooms} = Roster} -> - R2 = case Status of removed -> R;_ -> R#'Room'{last_msg = []} end, + R2 = case Status of + removed -> R; + keep -> + case lists:keyfind(R#'Room'.id, #'Room'.id, Rooms) of + false -> R#'Room'{last_msg = [], status = []}; + #'Room'{status = St} -> R#'Room'{last_msg = [], status = St} + end; + _ -> R#'Room'{last_msg = []} + end, kvs:put(Roster#'Roster'{roomlist = lists:ukeymerge(#'Room'.id, [R2], Rooms)}) end end), Res; @@ -2286,12 +2294,6 @@ parse_data(<>, RE) -> {match, Captured} -> [list_to_binary(C)||[C]<-Captured]; _ -> [] end. -parse_msg(#'Message'{mentioned = Mentioned}) -> - lists:flatten([case kvs:get('Member', Id) of - {ok, #'Member'{phone_id = PhoneId}} -> PhoneId; - _ -> [] - end ||Id<-Mentioned]). - % FAKE NUMBERS MANAGEMENT init_default_fake_numbers() -> -- GitLab From e58ea6eb3f3b3cf4bdc809441c267d5555405a3d Mon Sep 17 00:00:00 2001 From: Hans Svensson Date: Mon, 8 Jun 2020 15:05:34 +0200 Subject: [PATCH 2/2] Model Room/mute --- eqc/server_eqc.erl | 78 +++++++++++++++++++++++++++++++++------------- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/eqc/server_eqc.erl b/eqc/server_eqc.erl index e3520be4a..024860838 100644 --- a/eqc/server_eqc.erl +++ b/eqc/server_eqc.erl @@ -38,6 +38,7 @@ -type phone_id() :: binary(). -type msg_id() :: nat(). -type star_id() :: nat(). +-type room_id() :: binary(). -record(client, { handle :: symbolic(pid()) @@ -49,6 +50,7 @@ , phone_id :: symbolic(phone_id()) , friends = #{} :: #{phone() => true} , stars = [] :: list({star_id(), msg_id()}) + , muted = #{} :: #{room_id() => boolean()} }). -record(message, @@ -78,11 +80,11 @@ -record(room_info, { name :: string() - , status :: [] | atom() , members :: list(#member{}) , admins :: list(#member{}) , readers :: list(msg_id()) - , unread :: nat() }). + , unread :: nat() + , status :: [] | atom() }). -record(feed_info, { id :: {p2p, phone(), phone()} | {muc, binary()} @@ -337,7 +339,8 @@ del_room_member(RoomId, Member, Role, S) -> member -> Room0#room{ members = Room0#room.members -- [Member] }; admin -> Room0#room{ admins = Room0#room.admins -- [Member] } end, - S#state{ rooms = lists:keyreplace(RoomId, #room.id, S#state.rooms, Room1) }. + S1 = S#state{ rooms = lists:keyreplace(RoomId, #room.id, S#state.rooms, Room1) }, + set_muted(Member, RoomId, false, S1). rename_room(OldRoom, NewRoom, S) -> Room0 = get_room(S, OldRoom), @@ -365,6 +368,16 @@ starred_msg(S, Phone, StarId) -> {_, MsgId} = lists:keyfind(StarId, 1, Stars), MsgId. +set_muted(Phone, RoomId, IsMuted, S) -> + on_user(Phone, S, + fun(U = #user{ muted = Muted }) -> + U#user{ muted = Muted#{RoomId => IsMuted} } + end). + +get_muted(S, Phone, RoomId) -> + #user{ muted = Muted } = get_user(S, Phone), + maps:get(RoomId, Muted, false). + %% -- Generators ------------------------------------------------------------- gen_phone() -> noshrink(choose(1, 1000)). @@ -504,18 +517,6 @@ check_room(S, Phone, #room_info{ name = Room0, unread = Unread, admins = As, mem conj([check_feed(S, Phone, {muc, Room}, Reader, Unread), check_status(S, Phone, Room, St)]). -check_status(S, Phone, Room, Status) -> - #room{ members = Ms, admins = As } = get_room(S, Room), - case Status of - admin -> tag(status, lists:member(Phone, As)); - member -> tag(status, lists:member(Phone, Ms)); - [] -> tag(status, lists:member(Phone, As ++ Ms)); - mute -> tag(status, lists:member(Phone, As ++ Ms)); - delete -> tag(status, lists:member(Phone, As ++ Ms)); - _ -> tag(status, {false, Status}) - end. -%% check_status(_S, _Phone, _Room, _X) -> true. - check_feed(S, Phone, FeedId, LastRead, Unread) -> ExpLastRead = feed_last_seen(S, Phone, FeedId), ExpUnread = count_unread(ExpLastRead, feed_history(S, FeedId, Phone)), @@ -530,6 +531,11 @@ count_unread(MsgId, N, [#message{ id = MsgId2 } | _]) when MsgId >= MsgId2 -> N; count_unread(MsgId, N, [_ | Msgs]) -> count_unread(MsgId, N + 1, Msgs); count_unread(_, N, []) -> N. +check_status(S, Phone, Room, St) -> + case get_muted(S, Phone, Room) of + true -> tag(status, eq(St, mute)); + false -> tag(status, eq(St, [])) + end. %% --- get_room_info --- @@ -1041,7 +1047,7 @@ joinable_clients(S) -> [ {Handle, Room} || #client{ handle = Handle, phone = Phone } <- S#state.clients, #room{ id = Room, members = Ms, admins = As } <- S#state.rooms, - not lists:member(Phone, Ms ++ As) ]. + not lists:member(Phone, Ms ++ As), Ms ++ As /= [] ]. join_room_pre(S) -> [] /= joinable_clients(S). @@ -1185,8 +1191,8 @@ remove_from_room_callouts(S, [Handle, RoomId, MemberId, Role]) -> [ ?message(H1, '_', '_', '_', [sys], '_') || Phone <- Phones, H1 <- get_clients(S, Phone), H1 /= Handle ]) end. -remove_member_callouts(_S, [Room, Member, Role]) -> - ?APPLY(del_room_member, [Room, Member, Role]). +remove_member_next(S, _V, [Room, Member, Role]) -> + del_room_member(Room, Member, Role, S). %% --- promote_member --- @@ -1273,6 +1279,34 @@ do_demote_member_next(S, _V, [Room, MemberId]) -> S#state{ rooms = lists:keyreplace(Room, #room.id, S#state.rooms, Room1) }. +%% --- mute_room --- + +muteable_rooms(S) -> + [ {Handle, Room} + || #client{ handle = Handle, phone = Phone } <- S#state.clients, + #room{ id = Room, admins = As, members = Ms } <- S#state.rooms, + lists:member(Phone, As ++ Ms) ]. + +mute_room_pre(S) -> + muteable_rooms(S) /= []. + +mute_room_args(S) -> + ?LET({Handle, Room}, elements(muteable_rooms(S)), [Handle, Room, elements([mute, unmute])]). + +mute_room_pre(S, [Handle, Room, _Mute]) -> + lists:member({Handle, Room}, muteable_rooms(S)). + +mute_room(Handle, Room, Mute) -> + call_client(Handle, {mute_room, room_name(Room), Mute}). + +mute_room_callouts(S, [Handle, RoomId, Mute]) -> + Room = room_name(S, RoomId), + Phone = client_phone(S, Handle), + ?PAR([?room(H, Room, Mute, '_', '_', '_') || H <- get_clients(S, Phone) ]). + +mute_room_next(S, _V, [Handle, RoomId, Mute]) -> + set_muted(client_phone(S, Handle), RoomId, Mute == mute, S). + %% --- delete_room --- deleteable_rooms(S) -> @@ -1316,9 +1350,6 @@ add_feed_next(S, _V, [FeedId]) -> add_room_member_next(S, _V, [Room, Phone, Role]) -> add_room_member(Room, Phone, Role, S). -del_room_member_next(S, _V, [Room, Phone, Role]) -> - del_room_member(Room, Phone, Role, S). - feed_set_history_limit_next(S, _V, [FeedId, User, HL]) -> feed_set_history_limit(FeedId, User, HL, S). @@ -1383,6 +1414,7 @@ weight(_, add_to_room) -> 5; weight(_, remove_from_room) -> 3; weight(_, promote_member) -> 4; weight(_, demote_member) -> 4; +weight(_, mute_room) -> 2; weight(_, leave_room) -> 3; weight(_, add_star) -> 2; weight(_, delete_star) -> 2. @@ -1575,6 +1607,10 @@ handle_call(User, {demote_member, RoomName, MemberId}) -> Room = singleton_room(RoomId, M, admin, add), async_send(User, Room); +handle_call(User, {mute_room, RoomName, Mute}) -> + Room = singleton_room(RoomName, User, member, Mute), + async_send(User, Room); + handle_call(User, disconnect) -> nynja:ws_close(User), self() ! stop, %% yuck -- GitLab