Skip to content

Commit 6abdaaa

Browse files
committed
fix: try to reuse the same room
1 parent 71e39e9 commit 6abdaaa

File tree

3 files changed

+82
-60
lines changed

3 files changed

+82
-60
lines changed

main_test.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -651,13 +651,14 @@ func TestIntegration_SendMessageWithPhoneNumberMapping(t *testing.T) {
651651
t.Fatalf("failed to create matrix client: %v", err)
652652
}
653653

654-
roomName := fmt.Sprintf("Phone Test Room %d", time.Now().Unix())
655-
createResp, err := matrixClient.CreateRoom(context.Background(), id.UserID(user1MatrixID), roomName, []id.UserID{id.UserID(user2MatrixID)})
654+
// Create a direct room between user1 and user2 using CreateDirectRoom
655+
aliasKey := fmt.Sprintf("phone_test_%d", time.Now().Unix())
656+
createResp, err := matrixClient.CreateDirectRoom(context.Background(), id.UserID(user1MatrixID), id.UserID(user2MatrixID), aliasKey)
656657
if err != nil {
657-
t.Fatalf("failed to create room: %v", err)
658+
t.Fatalf("failed to create direct room: %v", err)
658659
}
659660
roomID := createResp.RoomID
660-
t.Logf("Created room %s", roomID)
661+
t.Logf("Created direct room %s", roomID)
661662

662663
// Step 2: Join the room as user2
663664
_, err = matrixClient.JoinRoom(context.Background(), id.UserID(user2MatrixID), roomID)
@@ -749,13 +750,14 @@ func TestIntegration_RoomMessaging(t *testing.T) {
749750
t.Fatalf("failed to create matrix client: %v", err)
750751
}
751752

752-
roomName := fmt.Sprintf("Test Room %d", time.Now().Unix())
753-
createResp, err := matrixClient.CreateRoom(context.Background(), id.UserID(user1MatrixID), roomName, []id.UserID{id.UserID(user2MatrixID)})
753+
// Create a direct room between user1 and user2 using CreateDirectRoom
754+
aliasKey := fmt.Sprintf("test_room_%d", time.Now().Unix())
755+
createResp, err := matrixClient.CreateDirectRoom(context.Background(), id.UserID(user1MatrixID), id.UserID(user2MatrixID), aliasKey)
754756
if err != nil {
755-
t.Fatalf("failed to create room: %v", err)
757+
t.Fatalf("failed to create direct room: %v", err)
756758
}
757759
roomID := createResp.RoomID
758-
t.Logf("Created room %s", roomID)
760+
t.Logf("Created direct room %s", roomID)
759761

760762
// Step 2: Join the room as user2
761763
_, err = matrixClient.JoinRoom(context.Background(), id.UserID(user2MatrixID), roomID)

matrix/client.go

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -160,25 +160,26 @@ func (mc *MatrixClient) Sync(ctx context.Context, userID id.UserID, since, filte
160160
}
161161

162162
// CreateDirectRoom creates a new direct message room impersonating 'userID' and inviting 'targetUserID'.
163-
func (mc *MatrixClient) CreateDirectRoom(ctx context.Context, userID id.UserID, targetUserID id.UserID) (*mautrix.RespCreateRoom, error) {
163+
func (mc *MatrixClient) CreateDirectRoom(ctx context.Context, userID id.UserID, targetUserID id.UserID, aliasKey string) (*mautrix.RespCreateRoom, error) {
164164
mc.mu.Lock()
165165
defer mc.mu.Unlock()
166166

167-
logger.Debug().Str("user_id", string(userID)).Str("target_user_id", string(targetUserID)).Msg("matrix: creating direct room")
167+
logger.Debug().Str("user_id", string(userID)).Str("target_user_id", string(targetUserID)).Str("alias_key", aliasKey).Msg("matrix: creating direct room")
168168

169169
mc.cli.UserID = userID
170170
req := &mautrix.ReqCreateRoom{
171-
Invite: []id.UserID{targetUserID},
172-
Preset: "trusted_private_chat",
173-
IsDirect: true,
171+
Invite: []id.UserID{targetUserID},
172+
Preset: "trusted_private_chat",
173+
IsDirect: true,
174+
RoomAliasName: aliasKey,
174175
}
175176
resp, err := mc.cli.CreateRoom(ctx, req)
176177
if err != nil {
177-
logger.Error().Str("user_id", string(userID)).Str("target_user_id", string(targetUserID)).Err(err).Msg("matrix: failed to create direct room")
178+
logger.Error().Str("user_id", string(userID)).Str("target_user_id", string(targetUserID)).Str("alias_key", aliasKey).Err(err).Msg("matrix: failed to create direct room")
178179
return nil, err
179180
}
180181

181-
logger.Info().Str("user_id", string(userID)).Str("target_user_id", string(targetUserID)).Str("room_id", string(resp.RoomID)).Msg("matrix: direct room created")
182+
logger.Info().Str("user_id", string(userID)).Str("target_user_id", string(targetUserID)).Str("alias_key", aliasKey).Str("room_id", string(resp.RoomID)).Msg("matrix: direct room created")
182183
return resp, nil
183184
}
184185

@@ -210,21 +211,26 @@ func (mc *MatrixClient) JoinRoom(ctx context.Context, userID id.UserID, roomID i
210211
return mc.cli.JoinRoom(ctx, roomIDStr, req)
211212
}
212213

213-
// CreateRoom creates a new room impersonating the specified userID.
214-
func (mc *MatrixClient) CreateRoom(ctx context.Context, userID id.UserID, name string, invitees []id.UserID) (*mautrix.RespCreateRoom, error) {
215-
mc.mu.Lock()
216-
defer mc.mu.Unlock()
217-
218-
mc.cli.UserID = userID
219-
req := &mautrix.ReqCreateRoom{
220-
Name: name,
221-
Invite: invitees,
222-
}
223-
return mc.cli.CreateRoom(ctx, req)
224-
}
225-
226214
// ResolveRoomAlias resolves a room alias to a room ID.
227215
func (mc *MatrixClient) ResolveRoomAlias(ctx context.Context, roomAlias string) (*mautrix.RespAliasResolve, error) {
228216
// This action does not require impersonation, so no lock is needed.
229217
return mc.cli.ResolveAlias(ctx, id.RoomAlias(roomAlias))
230218
}
219+
220+
func (mc *MatrixClient) GetRoomAliases(ctx context.Context, roomID id.RoomID) []string {
221+
// This action does not require impersonation, so no lock is needed.
222+
resp, err := mc.cli.GetAliases(ctx, roomID)
223+
if err != nil {
224+
logger.Error().Str("room_id", roomID.String()).Err(err).Msg("matrix: failed to get room aliases")
225+
return []string{}
226+
}
227+
if resp == nil || len(resp.Aliases) == 0 {
228+
return []string{}
229+
}
230+
231+
aliases := make([]string, 0, len(resp.Aliases))
232+
for _, a := range resp.Aliases {
233+
aliases = append(aliases, string(a))
234+
}
235+
return aliases
236+
}

service/messages.go

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ func (s *MessageService) FetchMessages(ctx context.Context, req *models.FetchMes
183183
// Determine Recipient
184184
if isSent {
185185
// I sent it. Recipient is the other person in the room.
186-
other := s.resolveRoomIDToOtherIdentifier(evt.RoomID, string(userID))
186+
other := s.resolveRoomIDToOtherIdentifier(ctx, evt.RoomID, string(userID))
187187
if other != "" {
188188
msg.Recipient = other
189189
}
@@ -202,6 +202,16 @@ func (s *MessageService) FetchMessages(ctx context.Context, req *models.FetchMes
202202
StreamID: msg.StreamID,
203203
}
204204

205+
// Debug each processed message
206+
logger.Debug().
207+
Str("event_id", msg.ID).
208+
Str("room_id", msg.StreamID).
209+
Str("sender", msg.Sender).
210+
Str("recipient", msg.Recipient).
211+
Bool("is_sent", isSent).
212+
Interface("sms", sms).
213+
Msg("processed message from sync")
214+
205215
if isSent {
206216
sms.Recipient = msg.Recipient
207217
sent = append(sent, sms)
@@ -308,43 +318,55 @@ func (s *MessageService) resolveMatrixIDToIdentifier(matrixID string) string {
308318
}
309319

310320
// resolveRoomIDToOtherIdentifier finds the identifier of the "other" participant in a room.
311-
func (s *MessageService) resolveRoomIDToOtherIdentifier(roomID id.RoomID, myMatrixID string) string {
312-
s.mu.RLock()
313-
defer s.mu.RUnlock()
314-
for _, entry := range s.mappings {
315-
// Find mapping for this room where the Matrix ID is NOT me
316-
if entry.RoomID == roomID && !strings.EqualFold(entry.MatrixID, myMatrixID) {
317-
// Ignore internal mappings
318-
if strings.Contains(entry.Number, "|") {
319-
continue
320-
}
321-
return entry.Number
321+
func (s *MessageService) resolveRoomIDToOtherIdentifier(ctx context.Context, roomID id.RoomID, myMatrixID string) string {
322+
aliases := s.matrixClient.GetRoomAliases(ctx, roomID)
323+
my := strings.TrimSpace(myMatrixID)
324+
325+
for _, alias := range aliases {
326+
parts := strings.SplitN(alias, "|", 2)
327+
if len(parts) != 2 {
328+
continue
329+
}
330+
left := strings.TrimSpace(parts[0])
331+
right := strings.TrimSpace(parts[1])
332+
333+
if strings.EqualFold(left, my) {
334+
return right
335+
}
336+
if strings.EqualFold(right, my) {
337+
return left
322338
}
323339
}
340+
324341
return ""
325342
}
326343

327-
func (s *MessageService) ensureDirectRoom(ctx context.Context, actingUserID, targetUserID id.UserID) (id.RoomID, error) {
328-
// Use both user IDs to create a consistent mapping key for the DM.
344+
func generateRoomAliasKey(actingUserID id.UserID, targetUserID id.UserID) string {
345+
// Use both user IDs to create a consistent mapping key for the DM:
346+
// alias is composed by "smallerID|largerID"
329347
key := fmt.Sprintf("%s|%s", actingUserID, targetUserID)
330348
if actingUserID > targetUserID {
331349
key = fmt.Sprintf("%s|%s", targetUserID, actingUserID)
332350
}
351+
return key
352+
}
353+
354+
func (s *MessageService) ensureDirectRoom(ctx context.Context, actingUserID, targetUserID id.UserID) (id.RoomID, error) {
355+
key := generateRoomAliasKey(actingUserID, targetUserID)
333356

334357
logger.Debug().Str("acting_user", string(actingUserID)).Str("target_user", string(targetUserID)).Msg("ensuring direct room exists")
335358

336-
if entry, ok := s.getMapping(key); ok && entry.RoomID != "" {
337-
logger.Debug().Str("acting_user", string(actingUserID)).Str("target_user", string(targetUserID)).Str("room_id", string(entry.RoomID)).Msg("existing DM room found in cache")
338-
return entry.RoomID, nil
339-
}
340-
if !strings.HasPrefix(string(targetUserID), "@") {
341-
logger.Warn().Str("acting_user", string(actingUserID)).Str("target_user", string(targetUserID)).Msg("invalid target user ID format")
342-
return "", ErrInvalidRecipient
359+
// Search between existing rooms
360+
logger.Debug().Str("key", key).Msg("Searching for direct room with alias")
361+
alias, aliasErr := s.matrixClient.ResolveRoomAlias(ctx, key)
362+
if aliasErr == nil && alias.RoomID != "" {
363+
return alias.RoomID, nil
343364
}
344365

345-
logger.Info().Str("acting_user", string(actingUserID)).Str("target_user", string(targetUserID)).Msg("creating new direct room")
366+
// Create a new direct room
346367

347-
resp, err := s.matrixClient.CreateDirectRoom(ctx, actingUserID, targetUserID)
368+
logger.Info().Str("acting_user", string(actingUserID)).Str("target_user", string(targetUserID)).Msg("creating new direct room")
369+
resp, err := s.matrixClient.CreateDirectRoom(ctx, actingUserID, targetUserID, key)
348370
if err != nil {
349371
logger.Error().Str("acting_user", string(actingUserID)).Str("target_user", string(targetUserID)).Err(err).Msg("failed to create direct room")
350372
return "", err
@@ -357,15 +379,7 @@ func (s *MessageService) ensureDirectRoom(ctx context.Context, actingUserID, tar
357379
return "", fmt.Errorf("join room as target user: %w", err)
358380
}
359381

360-
entry := mappingEntry{
361-
Number: key, // Use the combined key for internal storage
362-
MatrixID: string(targetUserID),
363-
RoomID: resp.RoomID,
364-
UpdatedAt: s.now(),
365-
}
366-
entry = s.setMapping(entry)
367-
logger.Info().Str("acting_user", string(actingUserID)).Str("target_user", string(targetUserID)).Str("room_id", string(resp.RoomID)).Msg("direct room created and cached")
368-
return entry.RoomID, nil
382+
return resp.RoomID, nil
369383
}
370384

371385
func (s *MessageService) getMapping(key string) (mappingEntry, bool) {

0 commit comments

Comments
 (0)