Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/1967-settings-line-attribution.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
The one line a group-settings save leaves in the room now names the person who saved it on the default single-user setup ([#1967](https://github.com/ThinkFlowLab/FlyBot/issues/1967)): the web UI has no member session, so the save reached the host with no name and every rename, notice, mode or admin change read "Someone updated the group notice". The line now takes the room's implicit owner — the local person whose Bots sit in it — while a signed-in member and a Bot saving through its own tool still win, and only a room with no owner at all falls back to "the user".
8 changes: 7 additions & 1 deletion core/src/host/roster.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { MAX_AVATAR_IMAGE, ROOM_MAX_MEMBERS, ROOM_MODES, ROOM_NAME_MAX, ROOM_NOT
import { currentColor, cut, isColor, unquote } from './text.js'
import { nameProblem } from '../shared/mentions.js'
import { cleanExternal } from './room-participant-external.js'
import { implicitRoomOwner } from './room-membership.js'
import { ownEntry } from './store.js'

export function install(rt) {
Expand Down Expand Up @@ -501,7 +502,12 @@ export function install(rt) {
}

function showSettings(room, settings, actor, actorId) {
const who = actor?.displayName ?? rt.botOf(actorId)?.name ?? 'Someone'
// The web UI has no member session (#1967), so the local user's save arrives with neither an actor nor a
// Bot id: the room's implicit owner names it, the way the room line already does. Only a room with no
// owner at all falls back to the host's own wording for the local person; a signed-in member and a Bot
// acting through its tool still win, as they did.
const who = actor?.displayName ?? rt.botOf(actorId)?.name
?? implicitRoomOwner(room, state)?.displayName ?? 'the user'
const said = settings.length === 1 ? settings[0] : `${settings.slice(0, -1).join(', ')} and ${settings.at(-1)}`
try {
void Promise.resolve(rt.postToRoom?.(room, { id: 'face-notice', name: who }, `${who} ${said}`, { quiet: true, notice: true }))
Expand Down
19 changes: 19 additions & 0 deletions core/test/remote-room.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2567,6 +2567,25 @@ test('writing back the reply mode the room already holds says nothing', async (t
assert.deepEqual(events, [], 'a save that writes the same mode back says nothing')
})

// #1967: the local user has no member session (nothing in this repository writes the client's
// `flybot-member-session` key), so a save from the web UI reaches the roster with neither an actor nor a
// Bot id. The line that says who changed what must still name the room's owner, and never read as a
// third party doing it.
test('a settings save with no session names the room owner, not Someone', async (t) => {
const { rt } = host(t, TEAM)
installRoster(rt)
await rt.load()
const events = []
rt.postToRoom = async (room, sender, text, extra) => { events.push({ room: room.id, sender, text, extra }) }

await rt.updateRoom('war', { notice: 'Stand up' })

assert.equal(events.length, 1, `one save is one line: ${JSON.stringify(events)}`)
assert.equal(events[0].text, 'Alice updated the group notice', 'the local user is named, not someone else')
assert.ok(!events[0].text.includes('Someone'), 'a save by the local user never reads as a third party')
assert.deepEqual(events[0].extra, { quiet: true, notice: true }, 'still quiet and a notice, so no turn opens')
})

// #904: a roster is stranger-written text, so the envelope that carries one is gated: only the room's
// own inviter, only the room this mirror is bound to, and nothing it says widens reach by itself.
test('#904: a roster from another home or for another room changes no participant', async (t) => {
Expand Down
Loading
Loading