Skip to content

chore: send a message on the DM when an internal call ends#37419

Merged
gabriellsh merged 13 commits intofeat/voip-room-messagesfrom
chore/send-message-to-channel-when-call-end
Nov 19, 2025
Merged

chore: send a message on the DM when an internal call ends#37419
gabriellsh merged 13 commits intofeat/voip-room-messagesfrom
chore/send-message-to-channel-when-call-end

Conversation

@pierre-lehnen-rc
Copy link
Contributor

@pierre-lehnen-rc pierre-lehnen-rc commented Nov 6, 2025

Proposed changes (including videos or screenshots)

Issue(s)

VGA-54

Steps to test or reproduce

Further comments

Summary by CodeRabbit

  • New Features

    • Media call history now shows localized, iconified state labels and readable durations (mm:ss / hh:mm:ss).
    • History messages are automatically posted to rooms after internal calls complete.
  • Tests

    • Added comprehensive tests covering history payload formatting, state mappings, icons, and duration handling.
  • Chores

    • Updated typings and localization strings; adjusted test config for server-side specs.

@changeset-bot
Copy link

changeset-bot bot commented Nov 6, 2025

⚠️ No Changeset found

Latest commit: ceb2780

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@dionisio-bot
Copy link
Contributor

dionisio-bot bot commented Nov 6, 2025

Looks like this PR is not ready to merge, because of the following issues:

  • This PR is missing the 'stat: QA assured' label
  • This PR is missing the required milestone or project

Please fix the issues and try again

If you have any trouble, please check the PR guidelines

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 6, 2025

Walkthrough

Adds sending of an info-card history message when internal media calls are saved: new payload builder, duration formatting, icon/translation mappings, service integration to send and link the message ID to call history, tests, typing for messageId, and new i18n keys.

Changes

Cohort / File(s) Summary
Test Configuration
apps/meteor/jest.config.ts
Added '<rootDir>/server/services/media-call/**.spec.ts' to server testMatch to include media-call tests.
History Payload & Tests
apps/meteor/server/services/media-call/getHistoryMessagePayload.ts, apps/meteor/server/services/media-call/getHistoryMessagePayload.spec.ts
New module exporting getHistoryMessagePayload, getFormattedCallDuration, callStateToTranslationKey, callStateToIcon; builds info-card payload with state label, icon, and optional duration. Comprehensive unit tests for states, icons, translations, and duration formatting/edge cases.
Call Service Integration
apps/meteor/server/services/media-call/service.ts
After saving internal call history, emit history message when rid exists via new private sendHistoryMessage(); send message, store returned messageId on call history; updated createDirectMessage call site to match new signature; added necessary imports.
Type Definitions
packages/core-typings/src/ICallHistoryItem.ts
Added messageId?: IMessage['_id']; to IInternalMediaCallHistoryItem and imported IMessage.
Internationalization
packages/i18n/src/locales/en.i18n.json
Added bold variants: Call_ended_bold, Call_not_answered_bold, Call_failed_bold, Call_transferred_bold.

Sequence Diagram(s)

sequenceDiagram
    actor Service as Call Service
    participant History as CallHistory DB
    participant Payload as getHistoryMessagePayload
    participant Message as sendMessage
    Service->>History: Save call history
    alt rid exists
        Service->>Payload: getHistoryMessagePayload(callState, duration)
        Payload-->>Service: InfoCard payload
        Service->>Message: sendMessage(to room)
        Message-->>Service: messageId
        Service->>History: Update call history with messageId
    else no rid
        Note over Service: No history message sent
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Pay attention to: duration formatting logic in getFormattedCallDuration, correctness of translation key mapping, payload structure compatibility with IMessage types, error handling and persistence in sendHistoryMessage().

Possibly related PRs

Suggested labels

stat: ready to merge, stat: QA assured

Suggested reviewers

  • tassoevan
  • dougfabris

Poem

🐰 A ring, a blink, a call that flew,
I craft the card with icon and hue,
Bold the state, the seconds chime,
Message linked to history, snug in time,
Hop! — the log now tells the view.

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: sending a message to the DM when an internal call ends, which is the primary objective of this PR.
Linked Issues check ✅ Passed The PR successfully implements the objective from VGA-54 by adding formatted messages with proper block-structured content when calls are saved to history.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the linked issue objective of sending formatted messages when calls are saved to history; no unrelated modifications detected.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/send-message-to-channel-when-call-end

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Nov 6, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 67.94%. Comparing base (a8ffe29) to head (d439562).

Additional details and impacted files

Impacted file tree graph

@@                     Coverage Diff                     @@
##           feat/voip-room-messages   #37419      +/-   ##
===========================================================
- Coverage                    67.99%   67.94%   -0.05%     
===========================================================
  Files                         3359     3357       -2     
  Lines                       115377   114981     -396     
  Branches                     20801    20780      -21     
===========================================================
- Hits                         78448    78123     -325     
+ Misses                       34246    34170      -76     
- Partials                      2683     2688       +5     
Flag Coverage Δ
unit 72.02% <100.00%> (-0.03%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@gabriellsh gabriellsh marked this pull request as ready for review November 19, 2025 17:43
@gabriellsh gabriellsh requested a review from a team as a code owner November 19, 2025 17:43
@gabriellsh gabriellsh requested a review from a team as a code owner November 19, 2025 18:00
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (4)
apps/meteor/server/services/media-call/getHistoryMessagePayload.spec.ts (1)

1-278: Solid coverage; consider table‑driven tests to reduce duplication

The spec file exercises all states, duration edge cases, and the full payload structure, which is great. A future improvement would be to switch repeated per‑state tests (for both translation keys, icons, and payloads) to it.each / table‑driven patterns so adding a new call state or tweaking icons/text only requires editing a single data table instead of multiple hard‑coded expectations.

apps/meteor/server/services/media-call/service.ts (2)

91-133: Harden sendHistoryMessage for observability and idempotency

The wiring from saveInternalCallToHistory into sendHistoryMessage is reasonable, and the messageId back‑link into CallHistory fits the new typing. A couple of improvements would make this more robust:

  • When room or user can’t be resolved (Lines 136–146), the function silently returns. Emitting a logger.warn with callId, rid, and userId in those branches would make it much easier to diagnose “no history DM was sent” issues.
  • Depending on how often historyUpdate can fire for a given callId, sendHistoryMessage might send multiple DMs for the same call. You could guard this by checking for an existing messageId before sending, e.g. only send if CallHistory documents for that callId don’t already have messageId set.

These are not blockers but would strengthen reliability and debugging.

Also applies to: 135-165


167-175: Clamp negative call durations before converting to seconds

getCallDuration is now used not only for persistence but also for user‑visible duration formatting in getHistoryMessagePayload. If endedAt ever predates activatedAt (clock skew, bad data), diff becomes negative and will produce unexpected output when fed into intervalToDuration.

Consider clamping the difference to zero:

-		const diff = endedAt.valueOf() - activatedAt.valueOf();
+		const diff = Math.max(0, endedAt.valueOf() - activatedAt.valueOf());

This keeps persisted durations and rendered durations sane even under skewed timestamps.

apps/meteor/server/services/media-call/getHistoryMessagePayload.ts (1)

5-21: Payload helpers are coherent; clean up TODOs and consider a text fallback

The state/icon/duration helpers and getHistoryMessagePayload are consistent with the spec tests and produce a clear info_card structure. Two small improvements to consider:

  • The TODOs about “bold the text” and “proper translation keys” (Lines 7 and 58) are now outdated given the _bold i18n keys and tests. Removing or updating them will avoid confusion for future readers.
  • getHistoryMessagePayload sets msg: ''. If there are any clients that don’t yet support the info_card block type, these history messages may appear empty. You might want to populate msg with a simple translated fallback like “Call ended” / “Call failed” using the same state mapping, so legacy or minimal clients still show something meaningful even without blocks.

Functionality is otherwise solid and well-covered by the accompanying spec.

Also applies to: 36-56, 58-91

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 15f1a20 and f9cd012.

📒 Files selected for processing (6)
  • apps/meteor/jest.config.ts (1 hunks)
  • apps/meteor/server/services/media-call/getHistoryMessagePayload.spec.ts (1 hunks)
  • apps/meteor/server/services/media-call/getHistoryMessagePayload.ts (1 hunks)
  • apps/meteor/server/services/media-call/service.ts (3 hunks)
  • packages/core-typings/src/ICallHistoryItem.ts (2 hunks)
  • packages/i18n/src/locales/en.i18n.json (1 hunks)
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-11-17T22:38:48.631Z
Learnt from: gabriellsh
Repo: RocketChat/Rocket.Chat PR: 37505
File: packages/i18n/src/locales/en.i18n.json:3765-3765
Timestamp: 2025-11-17T22:38:48.631Z
Learning: Rocket.Chat i18n copy: Keep sentence case for the value of "Notification_Desktop_show_voice_calls" in packages/i18n/src/locales/en.i18n.json (“Show desktop notifications for voice calls”) per design directive; do not change to Title Case even if nearby labels differ.

Applied to files:

  • packages/i18n/src/locales/en.i18n.json
📚 Learning: 2025-09-16T13:33:49.237Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36890
File: apps/meteor/tests/e2e/e2e-encryption/e2ee-otr.spec.ts:21-26
Timestamp: 2025-09-16T13:33:49.237Z
Learning: The im.delete API endpoint accepts either a `roomId` parameter (requiring the actual DM room _id) or a `username` parameter (for the DM partner's username). Constructing slug-like identifiers like `user2${Users.userE2EE.data.username}` doesn't work for this endpoint.

Applied to files:

  • apps/meteor/server/services/media-call/service.ts
📚 Learning: 2025-09-16T13:33:49.237Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36890
File: apps/meteor/tests/e2e/e2e-encryption/e2ee-otr.spec.ts:21-26
Timestamp: 2025-09-16T13:33:49.237Z
Learning: In Rocket.Chat test files, the im.delete API endpoint accepts either a `roomId` parameter (requiring the actual DM room _id) or a `username` parameter (for the DM partner's username). It does not accept slug-like constructions such as concatenating usernames together.

Applied to files:

  • apps/meteor/server/services/media-call/service.ts
🧬 Code graph analysis (4)
packages/core-typings/src/ICallHistoryItem.ts (1)
packages/core-typings/src/IMessage/IMessage.ts (1)
  • IMessage (162-260)
apps/meteor/server/services/media-call/getHistoryMessagePayload.spec.ts (1)
apps/meteor/server/services/media-call/getHistoryMessagePayload.ts (4)
  • callStateToTranslationKey (8-20)
  • callStateToIcon (22-34)
  • getFormattedCallDuration (40-56)
  • getHistoryMessagePayload (59-91)
apps/meteor/server/services/media-call/getHistoryMessagePayload.ts (2)
packages/core-typings/src/ICallHistoryItem.ts (1)
  • CallHistoryItemState (6-16)
packages/core-typings/src/IMessage/IMessage.ts (1)
  • IMessage (162-260)
apps/meteor/server/services/media-call/service.ts (4)
packages/core-typings/src/mediaCalls/IMediaCall.ts (1)
  • IMediaCall (35-68)
packages/models/src/index.ts (3)
  • Rooms (204-204)
  • Users (213-213)
  • CallHistory (149-149)
apps/meteor/server/services/media-call/getHistoryMessagePayload.ts (1)
  • getHistoryMessagePayload (59-91)
ee/packages/media-calls/src/logger.ts (1)
  • logger (3-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (3)
apps/meteor/jest.config.ts (1)

46-46: LGTM!

The addition of the test discovery pattern for media-call service specs is correct and follows the existing pattern style in the server testMatch array. This properly enables Jest to discover and run the new test files introduced in this PR.

packages/core-typings/src/ICallHistoryItem.ts (1)

1-43: messageId linkage type looks correct

Using messageId?: IMessage['_id'] on IInternalMediaCallHistoryItem cleanly models the association created in MediaCallService.sendHistoryMessage and keeps it optional for failure paths. No further changes needed here.

apps/meteor/server/services/media-call/service.ts (1)

201-221: createDirectMessage call update looks aligned with new signature

Switching to createDirectMessage(usernames, dmCreatorId) and deriving dmCreatorId from createdBy/caller/uids[0] is consistent with how you already choose the DM creator, and avoids the now‑removed boolean argument. Assuming the method’s exported signature was updated accordingly, this call site looks correct.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Jira integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f9cd012 and ceb2780.

📒 Files selected for processing (1)
  • apps/meteor/server/services/media-call/service.ts (3 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-09-16T13:33:49.237Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36890
File: apps/meteor/tests/e2e/e2e-encryption/e2ee-otr.spec.ts:21-26
Timestamp: 2025-09-16T13:33:49.237Z
Learning: The im.delete API endpoint accepts either a `roomId` parameter (requiring the actual DM room _id) or a `username` parameter (for the DM partner's username). Constructing slug-like identifiers like `user2${Users.userE2EE.data.username}` doesn't work for this endpoint.

Applied to files:

  • apps/meteor/server/services/media-call/service.ts
📚 Learning: 2025-09-16T13:33:49.237Z
Learnt from: cardoso
Repo: RocketChat/Rocket.Chat PR: 36890
File: apps/meteor/tests/e2e/e2e-encryption/e2ee-otr.spec.ts:21-26
Timestamp: 2025-09-16T13:33:49.237Z
Learning: In Rocket.Chat test files, the im.delete API endpoint accepts either a `roomId` parameter (requiring the actual DM room _id) or a `username` parameter (for the DM partner's username). It does not accept slug-like constructions such as concatenating usernames together.

Applied to files:

  • apps/meteor/server/services/media-call/service.ts
🧬 Code graph analysis (1)
apps/meteor/server/services/media-call/service.ts (3)
packages/core-typings/src/mediaCalls/IMediaCall.ts (1)
  • IMediaCall (35-68)
apps/meteor/server/services/media-call/getHistoryMessagePayload.ts (1)
  • getHistoryMessagePayload (59-91)
ee/packages/media-calls/src/logger.ts (1)
  • logger (3-3)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: 📦 Build Packages
  • GitHub Check: CodeQL-Build
  • GitHub Check: CodeQL-Build
🔇 Additional comments (3)
apps/meteor/server/services/media-call/service.ts (3)

9-10: LGTM!

The new imports are appropriate for the history messaging feature.


130-133: LGTM!

The logic correctly sends one history message per call (not per history record) and ensures both CallHistory records are linked to the message.


220-223: No issues found.

The logic is correct. The excludeSelf parameter controls whether the creator (me) is included in roomUsers (line 44 of the implementation shows: const roomUsers = excludeSelf ? users : [me, ...users]). The conditional passing !dmCreatorIsPartOfTheCall properly excludes the creator only when they are not part of the call, which aligns with the stated intent.

@gabriellsh gabriellsh merged commit 7bc4f03 into feat/voip-room-messages Nov 19, 2025
16 checks passed
@gabriellsh gabriellsh deleted the chore/send-message-to-channel-when-call-end branch November 19, 2025 18:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants