From b4ed5456a29f21be556355e01e23500d2909e3e1 Mon Sep 17 00:00:00 2001 From: hampus-fluxer Date: Tue, 6 Jan 2026 05:55:06 +0100 Subject: [PATCH] fix(presence): custom status propagation (#55) --- fluxer_gateway/src/presence/presence.erl | 71 ++++++++++++++++++------ 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/fluxer_gateway/src/presence/presence.erl b/fluxer_gateway/src/presence/presence.erl index 03387dd0..4f866919 100644 --- a/fluxer_gateway/src/presence/presence.erl +++ b/fluxer_gateway/src/presence/presence.erl @@ -110,6 +110,10 @@ handle_call({dispatch, EventAtom, Data}, _From, State) -> false -> {reply, ok, State} end; + user_settings_update -> + NewState = handle_user_settings_update(Data, State), + FinalState = force_publish_global_presence(NewState), + {reply, ok, FinalState}; message_create -> HasMobile = lists:any( fun(Session) -> @@ -194,6 +198,10 @@ handle_cast({dispatch, Event, Data}, State) -> false -> {noreply, State} end; + user_settings_update -> + NewState = handle_user_settings_update(Data, State), + FinalState = force_publish_global_presence(NewState), + {noreply, FinalState}; message_create -> HasMobile = lists:any( fun(Session) -> @@ -399,11 +407,25 @@ publish_global_if_needed({noreply, NewState}) -> {noreply, FinalState}. publish_global_presence(_Sessions, State) -> - UserId = maps:get(user_id, State), + {Payload, CurrentExternal, ExternalStatus} = build_presence_external(State), + LastPublished = maps:get(last_published_presence, State, undefined), + + case presence_changed(LastPublished, CurrentExternal) of + true -> + publish_presence_payload(State, Payload, CurrentExternal, ExternalStatus); + false -> + State + end. + +force_publish_global_presence(State) -> + {Payload, CurrentExternal, ExternalStatus} = build_presence_external(State), + publish_presence_payload(State, Payload, CurrentExternal, ExternalStatus). + +build_presence_external(State) -> Payload = build_presence_payload(State), - ExternalStatus = maps:get(<<"status">>, Payload), - Mobile = maps:get(<<"mobile">>, Payload), - Afk = maps:get(<<"afk">>, Payload), + ExternalStatus = maps:get(<<"status">>, Payload, <<"offline">>), + Mobile = maps:get(<<"mobile">>, Payload, false), + Afk = maps:get(<<"afk">>, Payload, false), CustomStatus = maps:get(<<"custom_status">>, Payload, null), CurrentExternal = #{ status => ExternalStatus, @@ -411,21 +433,18 @@ publish_global_presence(_Sessions, State) -> afk => Afk, custom_status => CustomStatus }, - LastPublished = maps:get(last_published_presence, State, undefined), + {Payload, CurrentExternal, ExternalStatus}. - case presence_changed(LastPublished, CurrentExternal) of - true -> - case ExternalStatus of - <<"offline">> -> - presence_cache:delete(UserId); - _ -> - presence_cache:put(UserId, Payload) - end, - presence_bus:publish(UserId, Payload), - maps:put(last_published_presence, CurrentExternal, State); - false -> - State - end. +publish_presence_payload(State, Payload, CurrentExternal, ExternalStatus) -> + UserId = maps:get(user_id, State), + case ExternalStatus of + <<"offline">> -> + presence_cache:delete(UserId); + _ -> + presence_cache:put(UserId, Payload) + end, + presence_bus:publish(UserId, Payload), + maps:put(last_published_presence, CurrentExternal, State). presence_changed(undefined, _Current) -> true; @@ -724,6 +743,22 @@ custom_status_comparator(Map) when is_map(Map) -> <<"emoji_name">> => field_or_null(Map, <<"emoji_name">>) }. +handle_user_settings_update(Data, State) -> + case maps:find(<<"custom_status">>, Data) of + error -> + State; + {ok, CustomStatus} -> + Normalized = normalize_state_custom_status(CustomStatus), + maps:put(custom_status, Normalized, State) + end. + +normalize_state_custom_status(null) -> + null; +normalize_state_custom_status(Map) when is_map(Map) -> + Map; +normalize_state_custom_status(_) -> + null. + field_or_null(Map, Key) -> case maps:get(Key, Map, undefined) of undefined -> null;