Bind history to the recipient session and channel, not the name (closes #148)
check / check (push) Canceled after 0s

History was selected by msg_to, so whoever next held a released nick, or
created a deleted channel again under its old name, could read the
earlier holder's messages. Each message row now records the session a
DM or INVITE was sent to (to_session_id) and the channel a channel
message was sent to (to_channel_id), and GET /api/v1/history selects by
those ids. A session's DM history now also follows it across nick
changes.

Model: opus-5-5
This commit is contained in:
2026-10-20 15:45:57 +00:00
parent 0b09cf838c
commit bd5caeaba9
10 changed files with 314 additions and 85 deletions
+16 -12
View File
@@ -311,7 +311,7 @@ func (s *Service) SendWallops(
}
_, _, err = s.FanOut(
ctx, irc.CmdWallops, nick, "*",
ctx, irc.CmdWallops, nick, "*", 0, 0,
nil, body, nil, recipients,
)
if err != nil {
@@ -344,15 +344,19 @@ type DirectMsgResult struct {
}
// FanOut inserts a message and enqueues it to all given
// session IDs, notifying each via the broker.
// session IDs, notifying each via the broker. toSessionID
// and toChannelID are the recipient InsertMessage records
// for history, 0 when there is none.
func (s *Service) FanOut(
ctx context.Context,
command, from, to string,
toSessionID, toChannelID int64,
params, body, meta json.RawMessage,
sessionIDs []int64,
) (int64, string, error) {
dbID, msgUUID, err := s.db.InsertMessage(
ctx, command, from, to, params, body, meta,
ctx, command, from, to,
toSessionID, toChannelID, params, body, meta,
)
if err != nil {
return 0, "", fmt.Errorf("insert message: %w", err)
@@ -459,7 +463,7 @@ func (s *Service) SendChannelMessage(
recipients := excludeSession(memberIDs, sessionID)
dbID, uuid, fanErr := s.FanOut(
ctx, command, nick, channel,
ctx, command, nick, channel, 0, chID,
nil, body, meta, recipients,
)
if fanErr != nil {
@@ -495,7 +499,7 @@ func (s *Service) SendDirectMessage(
}
_, uuid, fanErr := s.FanOut(
ctx, command, nick, target,
ctx, command, nick, target, targetSID, 0,
nil, body, meta, recipients,
)
if fanErr != nil {
@@ -561,7 +565,7 @@ func (s *Service) JoinChannel(
body, _ := json.Marshal([]string{channel}) //nolint:errchkjson
_, _, _ = s.FanOut( //nolint:dogsled // fire-and-forget broadcast
ctx, irc.CmdJoin, nick, channel,
ctx, irc.CmdJoin, nick, channel, 0, chID,
nil, body, nil, memberIDs,
)
@@ -604,7 +608,7 @@ func (s *Service) PartChannel(
body, _ := json.Marshal([]string{reason}) //nolint:errchkjson
_, _, _ = s.FanOut( //nolint:dogsled // fire-and-forget broadcast
ctx, irc.CmdPart, nick, channel,
ctx, irc.CmdPart, nick, channel, 0, chID,
nil, body, nil, recipients,
)
@@ -666,7 +670,7 @@ func (s *Service) SetTopic(
body, _ := json.Marshal([]string{topic}) //nolint:errchkjson
_, _, _ = s.FanOut( //nolint:dogsled // fire-and-forget broadcast
ctx, irc.CmdTopic, nick, channel,
ctx, irc.CmdTopic, nick, channel, 0, chID,
nil, body, nil, memberIDs,
)
@@ -730,7 +734,7 @@ func (s *Service) KickUser(
)
_, _, _ = s.FanOut( //nolint:dogsled // fire-and-forget broadcast
ctx, irc.CmdKick, nick, channel,
ctx, irc.CmdKick, nick, channel, 0, chID,
params, body, nil, memberIDs,
)
@@ -886,7 +890,7 @@ func (s *Service) BroadcastQuit(
body, _ := json.Marshal([]string{reason}) //nolint:errchkjson
_, _, _ = s.FanOut(
ctx, irc.CmdQuit, nick, "",
ctx, irc.CmdQuit, nick, "", 0, 0,
nil, body, nil, recipients,
)
}
@@ -1074,7 +1078,7 @@ func (s *Service) BroadcastMode(
body, _ := json.Marshal([]string{modeText}) //nolint:errchkjson
_, _, _ = s.FanOut( //nolint:dogsled // fire-and-forget broadcast
ctx, irc.CmdMode, nick, channel,
ctx, irc.CmdMode, nick, channel, 0, chID,
nil, body, nil, memberIDs,
)
}
@@ -1351,7 +1355,7 @@ func (s *Service) broadcastNickChange(
notified := make(map[int64]bool)
dbID, _, insErr := s.db.InsertMessage(
ctx, irc.CmdNick, oldNick, "",
ctx, irc.CmdNick, oldNick, "", 0, 0,
nil, body, nil,
)
if insErr != nil {
+1 -1
View File
@@ -164,7 +164,7 @@ func TestFanOut(t *testing.T) {
body, _ := json.Marshal([]string{"hello"}) //nolint:errchkjson
dbID, uuid, err := env.svc.FanOut(
ctx, irc.CmdPrivmsg, "alice", "#test",
ctx, irc.CmdPrivmsg, "alice", "#test", 0, 0,
nil, body, nil,
[]int64{sid1, sid2},
)