Просмотр исходного кода

webapi: display buddy icon on login

Mike 1 день назад
Родитель
Сommit
a0b4580c17
2 измененных файлов с 41 добавлено и 7 удалено
  1. 5 7
      server/webapi/presence_handler.go
  2. 36 0
      server/webapi/presence_handler_test.go

+ 5 - 7
server/webapi/presence_handler.go

@@ -415,7 +415,7 @@ func (h *PresenceHandler) SetState(w http.ResponseWriter, r *http.Request, sessi
 	// "presence" broadcast above drives buddy dots, not the user's own state.
 	// Without this, changing to Busy/Away leaves the user still showing as
 	// available in their own UI.
-	h.pushMyInfo(session, stateParam, awayMsg, "")
+	h.pushMyInfo(ctx, session, stateParam, awayMsg, "")
 
 	h.Logger.InfoContext(ctx, "presence state updated",
 		"screenName", session.ScreenName.String(),
@@ -472,7 +472,7 @@ func (h *PresenceHandler) SetStatus(w http.ResponseWriter, r *http.Request, sess
 
 	// Notify the user's own client so its status message re-renders. Preserve the
 	// current presence state so a status-only change does not flip the self badge.
-	h.pushMyInfo(session, currentWebState(session.OSCARSession), session.OSCARSession.Session().AwayMessage(), statusMsg)
+	h.pushMyInfo(ctx, session, currentWebState(session.OSCARSession), session.OSCARSession.Session().AwayMessage(), statusMsg)
 
 	h.Logger.InfoContext(ctx, "status message updated",
 		"screenName", session.ScreenName.String(),
@@ -655,16 +655,14 @@ func currentWebState(instance *state.SessionInstance) string {
 // re-renders its self-presence badge. The client binds its identity-badge render
 // to "myInfo" events only, so state changes made via setState/setStatus are
 // invisible in the user's own UI unless a myInfo event is delivered.
-func (h *PresenceHandler) pushMyInfo(session *Session, webState, awayMsg, statusMsg string) {
+func (h *PresenceHandler) pushMyInfo(ctx context.Context, session *Session, webState, awayMsg, statusMsg string) {
 	if !session.IsSubscribedTo("myInfo") && !session.IsSubscribedTo("presence") {
 		return
 	}
 
-	// buddyIcon is omitted here (empty) so the client's merge preserves the icon it
-	// already holds; a setState/setStatus does not change the icon. Icon changes
-	// arrive on their own myInfo via the pump's MyInfoRefresher.
+	icon := h.IconSource.PublishedURL(ctx, session.BaseURL, session.ScreenName.IdentScreenName())
 	moodIcon := moodIconURL(session.BaseURL, webState, session.OSCARSession.Session().Caps())
-	myInfo := buildMyInfo(session.ScreenName, webState, "", moodIcon)
+	myInfo := buildMyInfo(session.ScreenName, webState, icon, moodIcon)
 	myInfo.AwayMsg = awayMsg
 	myInfo.StatusMsg = statusMsg
 

+ 36 - 0
server/webapi/presence_handler_test.go

@@ -1034,3 +1034,39 @@ func TestPresenceHandler_SetStatus_SetInfoError(t *testing.T) {
 
 	assert.Equal(t, http.StatusInternalServerError, rr.Code)
 }
+
+func TestPresenceHandler_SetState_MyInfoCarriesBuddyIcon(t *testing.T) {
+	// Mandarin replaces its identity from each myInfo rather than merging into it,
+	// clearing its avatar when buddyIcon is absent.
+	oscarInstance := state.NewSession().AddInstance()
+	sessionMgr, aimsid := createTestSessionManagerWithOSCAR("testuser", oscarInstance)
+
+	session, err := sessionMgr.GetSession(context.Background(), aimsid)
+	require.NoError(t, err)
+	session.BaseURL = "http://api.example.com"
+
+	broadcaster := newMockBuddyBroadcaster(t)
+	broadcaster.EXPECT().BroadcastBuddyArrived(mock.Anything, mock.Anything, mock.Anything).Return(nil)
+
+	iconRetriever := newMockBuddyIconRetriever(t)
+	iconRetriever.EXPECT().BuddyIconMetadata(mock.Anything, state.NewIdentScreenName("testuser")).
+		Return(bartID([]byte{0xab, 0xcd}), nil)
+
+	handler := &PresenceHandler{
+		SessionManager:   sessionMgr,
+		BuddyBroadcaster: broadcaster,
+		IconSource:       BuddyIconSource{IconRetriever: iconRetriever, Logger: slog.Default()},
+		Logger:           slog.Default(),
+	}
+
+	req, err := http.NewRequest("GET", "/presence/setState?aimsid="+aimsid+"&state=away", nil)
+	require.NoError(t, err)
+
+	rr := httptest.NewRecorder()
+	requireSession(handler.SessionManager, handler.SetState).ServeHTTP(rr, req)
+	require.Equal(t, http.StatusOK, rr.Code)
+
+	myInfo := queuedMyInfo(session)
+	require.NotNil(t, myInfo, "expected a myInfo event to be queued")
+	assert.Equal(t, "http://api.example.com/expressions/get?t=testuser&type=buddyIcon&bartId=abcd", myInfo.BuddyIcon)
+}