Skip to content

[localserver] implement message content access#340

Merged
capcom6 merged 2 commits intomasterfrom
codex/add-message-content-to-get-/messages-response
Apr 16, 2026
Merged

[localserver] implement message content access#340
capcom6 merged 2 commits intomasterfrom
codex/add-message-content-to-get-/messages-response

Conversation

@capcom6
Copy link
Copy Markdown
Owner

@capcom6 capcom6 commented Apr 3, 2026

Motivation

  • Provide an opt-in way to return message payloads (textMessage or dataMessage) from GET /messages without breaking existing clients.
  • Document the behavior in OpenAPI and a short plan to allow safe rollout and privacy considerations.

Description

  • Add optional query parameter includeContent to GET /messages and document it in app/src/main/assets/api/swagger.json so list responses can include message payloads when requested.
  • Extend the local domain Message model in Message.kt with textMessage: TextMessage? and dataMessage: DataMessage? fields.
  • Update MessagesRoutes.kt to parse includeContent query parameter, validate it, and conditionally parse message content using Gson when building list responses, and to always include content for the single GET /messages/{id} endpoint.
  • Add docs/plans/messages-content-in-list-plan.md describing design, rollout, and considerations.

Testing

  • No new automated tests were added in this change.
  • Ran the existing build and test commands locally with ./gradlew assemble and ./gradlew test, and the existing test suite completed successfully.

Codex Task

Summary by CodeRabbit

  • New Features

    • GET /messages adds includeContent (default false); responses can include textMessage, dataMessage or hashedMessage and richer processing state objects.
    • Added gateway settings, refresh_token in auth responses, and POST /auth/token/refresh.
    • New API-key–style auth schemes (MobileToken, ServerKey, UserCode).
  • Bug Fixes

    • Duplicate message POSTs return 409 Conflict; invalid includeContent returns 400 Bad Request.
  • Other

    • Stricter Base64 validation and expanded enum metadata.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 3, 2026

Walkthrough

Reworked localserver message domain into a messages subpackage with typed content (Text/Data/Hashed), changed persistence serialization and enqueue flow to return persisted messages and raise conflicts, updated routes to honor includeContent and surface 400/409, and expanded/modified OpenAPI schemas and auth/token endpoints.

Changes

Cohort / File(s) Summary
OpenAPI Schema & Auth
app/src/main/assets/api/swagger.json
Tightened Base64 regex; added smsgateway.HashedMessage and smsgateway.SettingsGateway; changed several state fields to ProcessingState object refs; added refresh_token + POST /auth/token/refresh; switched JWTAuth to apiKey header and added MobileToken/ServerKey/UserCode; added includeContent query param and updated enums/metadata.
HTTP Routes
app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt
GET /inbox parses includeContent with strict boolean validation (400 on invalid), GET /{id} forces content inclusion, POST catches ConflictException -> 409, and routes now map to new domain.messages.Message via toDomain(deviceId, includeContent).
Domain Model Reorg
app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/...
app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/*
Moved message types into domain.messages; added TextMessage, DataMessage, HashedMessage; Message gained nullable textMessage/dataMessage/hashedMessage; removed old inline Text/Data models and response type aliases.
Persistence Entity & Serialization
app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt
Made Room entity constructor explicit; added secondary constructor accepting MessageContent + createdAt that serializes content via Gson and sets type; added lazy textContent/dataContent accessors and companion gson.
Repository & Service Behavior
app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesRepository.kt, .../MessagesService.kt
MessagesRepository.enqueue now returns the inserted MessageWithRecipients and stores content directly; MessagesService.enqueueMessage returns the enqueued MessageWithRecipients, removes pre-insert existence check, and translates SQLite constraint violations into ConflictException.
Exception
app/src/main/java/me/capcom/smsgateway/modules/messages/exceptions/ConflictException.kt
Added ConflictException : RuntimeException with fixed message "Message with the same ID already exists".
Type Alias & API Model Removals
app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/GetMessagesResponse.kt, .../PostMessageResponse.kt
Removed GetMessageResponse and PostMessageResponse type aliases; callers must use concrete Message types.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Routes as MessagesRoutes
    participant Service as MessagesService
    participant Repo as MessagesRepository
    participant DB as Database

    rect rgba(100,150,200,0.5)
        Note over Client,DB: POST /inbox — enqueue with conflict handling
        Client->>Routes: POST /inbox (SendRequest)
        Routes->>Service: enqueueMessage(request)
        Service->>Repo: enqueue(request)
        Repo->>DB: insert message
        alt duplicate ID
            DB-->>Repo: constraint error
            Repo-->>Service: throws ConflictException
            Service-->>Routes: exception
            Routes-->>Client: 409 Conflict
        else success
            DB-->>Repo: MessageWithRecipients
            Repo-->>Service: MessageWithRecipients
            Service-->>Routes: MessageWithRecipients
            Routes->>Routes: toDomain(deviceId, includeContent=true)
            Routes-->>Client: 200 OK (message with content)
        end
    end

    rect rgba(150,100,200,0.5)
        Note over Client,DB: GET /inbox — conditional content inclusion
        Client->>Routes: GET /inbox?includeContent=true
        Routes->>Routes: parse includeContent (400 if invalid)
        Routes->>DB: fetch messages
        DB-->>Routes: messages list
        Routes->>Routes: map each message toDomain(includeContent)
        Routes-->>Client: 200 OK (list with/without content)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: implementing message content access in the localserver module through an optional includeContent parameter and Message model extensions.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/add-message-content-to-get-/messages-response

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.

Copy link
Copy Markdown

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/assets/api/swagger.json (1)

662-719: ⚠️ Potential issue | 🟠 Major

GET /messages/{id} is now out of contract in OpenAPI.

These properties were added only to smsgateway.MessageState, but /messages/{id} still advertises smsgateway.GetMessageResponse. Please mirror textMessage and dataMessage into smsgateway.GetMessageResponse starting at Line 338, or switch that endpoint to a schema that includes them, otherwise generated clients for the single-message endpoint will miss fields the server now returns.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/assets/api/swagger.json` around lines 662 - 719, The OpenAPI
contract is out of sync: the new textMessage and dataMessage properties were
added to smsgateway.MessageState but not to smsgateway.GetMessageResponse used
by GET /messages/{id}; update the GetMessageResponse schema (or change the
/messages/{id} response to reference a schema that includes these fields) to
include the textMessage and dataMessage properties (same structure/refs used in
smsgateway.MessageState) so generated clients receive the same fields the server
returns.
🧹 Nitpick comments (1)
app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt (1)

58-66: Please add route coverage for the new includeContent branches.

This change adds a new 400 path, changes the /messages response shape, and makes /messages/{id} depend on the same content mapper, but there are no tests covering omitted/true/invalid includeContent values or text/data payload mapping.

Also applies to: 119-121, 300-300, 321-364

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt`
around lines 58 - 66, Add tests to cover the new includeContent query handling
and response mapping: exercise the MessagesRoutes handlers that serve the
/messages list and /messages/{id} endpoints (locate the route code around the
includeContent parsing block and the content-mapper function used for both list
and single-item responses). Specifically add cases for includeContent=false
(default) to assert text/data payloads are omitted and response shape unchanged,
includeContent=true to assert the mapper returns text/data fields correctly, and
an invalid value (e.g., includeContent=notabool) to assert a 400 with message
"includeContent must be true or false". Also update existing message-list and
message-by-id test expectations to use the same content-mapper assertions so
both endpoints are covered under omitted/true/invalid branches.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt`:
- Around line 321-336: In MessageWithRecipients.toDomain (the includeContent
branch) wrap each gson.fromJson call for MessageContent.Text and
MessageContent.Data in a try/catch so a malformed message.content does not throw
for the whole GET /messages; on parse exception for the current row, log/debug
the error and return null (or an empty safe placeholder) for that message's
content while allowing the rest of the conversion to proceed. Ensure you only
catch JSON parsing exceptions around gson.fromJson for message.content and leave
other logic unchanged.

---

Outside diff comments:
In `@app/src/main/assets/api/swagger.json`:
- Around line 662-719: The OpenAPI contract is out of sync: the new textMessage
and dataMessage properties were added to smsgateway.MessageState but not to
smsgateway.GetMessageResponse used by GET /messages/{id}; update the
GetMessageResponse schema (or change the /messages/{id} response to reference a
schema that includes these fields) to include the textMessage and dataMessage
properties (same structure/refs used in smsgateway.MessageState) so generated
clients receive the same fields the server returns.

---

Nitpick comments:
In
`@app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt`:
- Around line 58-66: Add tests to cover the new includeContent query handling
and response mapping: exercise the MessagesRoutes handlers that serve the
/messages list and /messages/{id} endpoints (locate the route code around the
includeContent parsing block and the content-mapper function used for both list
and single-item responses). Specifically add cases for includeContent=false
(default) to assert text/data payloads are omitted and response shape unchanged,
includeContent=true to assert the mapper returns text/data fields correctly, and
an invalid value (e.g., includeContent=notabool) to assert a 400 with message
"includeContent must be true or false". Also update existing message-list and
message-by-id test expectations to use the same content-mapper assertions so
both endpoints are covered under omitted/true/invalid branches.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 675d1db1-22cc-44cf-affe-8abd85c5f3f7

📥 Commits

Reviewing files that changed from the base of the PR and between 4d6169b and 0b029df.

📒 Files selected for processing (4)
  • app/src/main/assets/api/swagger.json
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt
  • docs/plans/messages-content-in-list-plan.md

@capcom6 capcom6 force-pushed the codex/add-message-content-to-get-/messages-response branch from 0b029df to 7b92ffe Compare April 3, 2026 02:50
Copy link
Copy Markdown

@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

♻️ Duplicate comments (1)
app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt (1)

332-348: ⚠️ Potential issue | 🟠 Major

Wrap content deserialization in try-catch to prevent one malformed record from failing the entire response.

The message.textContent and message.dataContent properties internally call gson.fromJson(), which can throw JsonSyntaxException if the stored content JSON is malformed. Since these are optional fields, a parse failure for one message should not abort the entire GET /messages response.

🛡️ Proposed fix with error isolation
-            textMessage = when (includeContent) {
-                true -> message.textContent?.let {
-                    TextMessage(it.text)
-                }
-
-                else -> null
-            },
-            dataMessage = when (includeContent) {
-                true -> message.dataContent?.let {
-                    me.capcom.smsgateway.modules.localserver.domain.DataMessage(
-                        data = it.data,
-                        port = it.port.toInt()
-                    )
-                }
-
-                else -> null
-            },
+            textMessage = if (includeContent) {
+                try {
+                    message.textContent?.let { TextMessage(it.text) }
+                } catch (e: Exception) {
+                    null
+                }
+            } else null,
+            dataMessage = if (includeContent) {
+                try {
+                    message.dataContent?.let {
+                        me.capcom.smsgateway.modules.localserver.domain.DataMessage(
+                            data = it.data,
+                            port = it.port.toInt()
+                        )
+                    }
+                } catch (e: Exception) {
+                    null
+                }
+            } else null,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt`
around lines 332 - 348, The deserialization of message.textContent and
message.dataContent can throw JsonSyntaxException and must be isolated so one
bad record doesn't fail the whole GET /messages response; wrap each access to
message.textContent and message.dataContent in a try-catch that catches
JsonSyntaxException (or Exception) and on parse error log the failure and return
null for that field so TextMessage(...) or DataMessage(...) is only constructed
on successful parse; update the mapping in MessagesRoutes.kt where
includeContent is handled (the when branches constructing TextMessage and
me.capcom.smsgateway.modules.localserver.domain.DataMessage) to perform the
safe-parse logic instead.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt`:
- Around line 83-93: The gson instance used by the dataContent getter cannot
deserialize MessageContent.Data.port (UShort) because Gson has no UShort
support; replace the plain Gson() with a GsonBuilder configured to register a
UShort TypeAdapter (e.g. registerTypeAdapter for UShort via a UShortTypeAdapter)
and create() it, or ensure the existing gson creation/extension registers that
UShort adapter so gson.fromJson(content, MessageContent.Data::class.java)
succeeds; update the gson initialization (the variable named gson) rather than
changing the dataContent getter logic.

---

Duplicate comments:
In
`@app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt`:
- Around line 332-348: The deserialization of message.textContent and
message.dataContent can throw JsonSyntaxException and must be isolated so one
bad record doesn't fail the whole GET /messages response; wrap each access to
message.textContent and message.dataContent in a try-catch that catches
JsonSyntaxException (or Exception) and on parse error log the failure and return
null for that field so TextMessage(...) or DataMessage(...) is only constructed
on successful parse; update the mapping in MessagesRoutes.kt where
includeContent is handled (the when branches constructing TextMessage and
me.capcom.smsgateway.modules.localserver.domain.DataMessage) to perform the
safe-parse logic instead.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ea637741-2f67-45e6-b970-817294baaeed

📥 Commits

Reviewing files that changed from the base of the PR and between 0b029df and 7b92ffe.

📒 Files selected for processing (5)
  • app/src/main/assets/api/swagger.json
  • app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesRepository.kt
✅ Files skipped from review due to trivial changes (1)
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/Message.kt

Comment thread app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt
@capcom6 capcom6 marked this pull request as ready for review April 3, 2026 03:08
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 3, 2026

🤖 Pull request artifacts

file commit
app-release.apk aa13121
app-release.aab aa13121
app-insecure.apk aa13121
app-insecure.aab aa13121

@capcom6 capcom6 changed the title Add optional includeContent to GET /messages and include message payloads in list responses [localserver] implement message content access Apr 3, 2026
Copy link
Copy Markdown

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/Message.kt`:
- Around line 12-14: The Message model exposes hashedMessage but MessagesRoutes
constructs Message with hashedMessage = null causing inconsistent state with
isHashed; update the route that builds Message (in MessagesRoutes.kt) to
populate hashedMessage when isHashed is true (or remove/derive isHashed if you
prefer) by creating the appropriate HashedMessage instance from the existing
hashing logic/payload used elsewhere, and set hashedMessage = null only when
isHashed is false to keep Message.kt’s fields consistent with the isHashed flag.

In `@app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt`:
- Around line 93-95: The new throw in MessagesService.enqueueMessage (the
getMessage(request.message.id) != null branch) makes duplicates raise
ConflictException and breaks non-HTTP callers like
GatewayService.enqueueMessage; change enqueueMessage to be idempotent instead:
if getMessage(request.message.id) != null, return the existing
Message/appropriate result (or a boolean indicating already-enqueued) instead of
throwing, so callers such as GatewayService.enqueueMessage can continue without
catching exceptions; update the method signature/return type if needed and
adjust MessagesRoutes to still translate the "already exists" result into an
HTTP 409 where required.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 6ecfdfc1-fdf4-4442-bf10-70b18e3a7512

📥 Commits

Reviewing files that changed from the base of the PR and between 7b92ffe and 0fc23a9.

📒 Files selected for processing (7)
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/HashedMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/PostMessageRequest.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesRepository.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/exceptions/ConflictException.kt
✅ Files skipped from review due to trivial changes (3)
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/PostMessageRequest.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/HashedMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/exceptions/ConflictException.kt
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesRepository.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt

Comment thread app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt Outdated
@capcom6 capcom6 linked an issue Apr 3, 2026 that may be closed by this pull request
@capcom6 capcom6 force-pushed the codex/add-message-content-to-get-/messages-response branch from a207a1e to 4bad1eb Compare April 3, 2026 07:42
@capcom6 capcom6 added the ready label Apr 9, 2026
Copy link
Copy Markdown

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/assets/api/swagger.json (1)

397-405: ⚠️ Potential issue | 🔴 Critical

Remove type: object from allOf properties referencing scalar schemas.

The properties at the specified lines use allOf to reference scalar enum schemas (smsgateway.ProcessingState, smsgateway.MessagePriority, smsgateway.WebhookEvent), which are defined as type: string or type: integer. Adding "type": "object" creates a schema contradiction—the examples show scalar values ("Pending", 0, "sms:received"), not objects. This will cause validation and code generation issues.

Suggested fix
          "state": {
            "allOf": [
              {
                "$ref": "#/components/schemas/smsgateway.ProcessingState"
              }
            ],
            "description": "State",
            "example": "Pending",
-           "type": "object"
          }
          "priority": {
            "allOf": [
              {
                "$ref": "#/components/schemas/smsgateway.MessagePriority"
              }
            ],
            "description": "Priority, messages with values greater than `99` will bypass limits and delays",
            "example": 0,
-           "type": "object"
          }

Apply the same removal to lines 794-802, 874-882, and 1094-1102.

Also applies to: 634-642, 794-802, 874-882, 1094-1102

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/assets/api/swagger.json` around lines 397 - 405, The OpenAPI
properties like "state" that use allOf to reference scalar enum schemas (e.g.,
smsgateway.ProcessingState, smsgateway.MessagePriority, smsgateway.WebhookEvent)
must not declare "type": "object" — remove the "type": "object" entries from
those allOf property blocks (including the ones referencing the examples
"Pending", 0, "sms:received") so the schema remains a scalar (string/integer)
and matches the referenced enum; apply the same removal for all occurrences
referencing those schemas (also present in the other allOf blocks for the same
enums).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/assets/api/swagger.json`:
- Around line 1279-1302: The JWTAuth security scheme in the OpenAPI spec was
changed to a generic apiKey and no longer documents Bearer semantics, and the
/auth/token/refresh operation reuses JWTAuth without specifying how the refresh
token is supplied; either restore JWTAuth to a Bearer HTTP scheme (HTTP type
with scheme "bearer" and bearerFormat "JWT") so Authorization: Bearer <token> is
documented, or add a distinct security scheme or explicit requestBody/parameter
for the refresh token on /auth/token/refresh (e.g., a RefreshToken scheme or a
body parameter named refresh_token) so clients know where to send the refresh
token; update the swagger.json entries for "JWTAuth" and the /auth/token/refresh
operation accordingly (refer to symbols JWTAuth and /auth/token/refresh).

---

Outside diff comments:
In `@app/src/main/assets/api/swagger.json`:
- Around line 397-405: The OpenAPI properties like "state" that use allOf to
reference scalar enum schemas (e.g., smsgateway.ProcessingState,
smsgateway.MessagePriority, smsgateway.WebhookEvent) must not declare "type":
"object" — remove the "type": "object" entries from those allOf property blocks
(including the ones referencing the examples "Pending", 0, "sms:received") so
the schema remains a scalar (string/integer) and matches the referenced enum;
apply the same removal for all occurrences referencing those schemas (also
present in the other allOf blocks for the same enums).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f27f3c50-5faf-408f-95ff-a696f0d4a4ab

📥 Commits

Reviewing files that changed from the base of the PR and between 4bad1eb and f703d38.

📒 Files selected for processing (1)
  • app/src/main/assets/api/swagger.json

Comment thread app/src/main/assets/api/swagger.json
@capcom6 capcom6 force-pushed the codex/add-message-content-to-get-/messages-response branch from f703d38 to 215a6dc Compare April 10, 2026 01:39
Copy link
Copy Markdown

@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.

♻️ Duplicate comments (2)
app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt (1)

326-342: ⚠️ Potential issue | 🟠 Major

Wrap content parsing to prevent single malformed message from failing entire response.

When includeContent=true, message.textContent and message.dataContent call gson.fromJson() internally. If any message has corrupted/malformed JSON content, the exception will propagate and fail the entire GET /messages response. Since these fields are optional, isolate parsing failures per item.

🛡️ Proposed fix
-            textMessage = when (includeContent) {
-                true -> message.textContent?.let {
-                    TextMessage(it.text)
-                }
-
-                else -> null
-            },
-            dataMessage = when (includeContent) {
-                true -> message.dataContent?.let {
-                    DataMessage(
-                        data = it.data,
-                        port = it.port.toInt()
-                    )
-                }
-
-                else -> null
-            },
+            textMessage = if (includeContent) {
+                runCatching { message.textContent }
+                    .getOrNull()
+                    ?.let { TextMessage(it.text) }
+            } else null,
+            dataMessage = if (includeContent) {
+                runCatching { message.dataContent }
+                    .getOrNull()
+                    ?.let { DataMessage(data = it.data, port = it.port.toInt()) }
+            } else null,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt`
around lines 326 - 342, In MessagesRoutes.kt, when includeContent is true you
must guard the per-message parsing of message.textContent and
message.dataContent (which call gson.fromJson) so a single malformed JSON
doesn't fail the whole GET /messages response; wrap the parsing logic used to
create TextMessage(...) and DataMessage(...) in try/catch blocks, catch JSON
parsing exceptions from gson.fromJson, log the error with message
identifier/context, and return null for textMessage or dataMessage on failure so
the rest of the items still return; update the branches that set textMessage and
dataMessage to use these safe-parsing wrappers.
app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt (1)

89-93: ⚠️ Potential issue | 🔴 Critical

Gson lacks native UShort support — deserialization of MessageContent.Data.port will fail.

The dataContent getter at line 91 calls gson.fromJson(content, MessageContent.Data::class.java), but MessageContent.Data has a port: UShort field. The plain Gson() instance at line 100 has no custom TypeAdapter for UShort, so deserialization will fail at runtime.

Register a UShort type adapter:

🛠️ Proposed fix
-        private val gson = Gson()
+        private val gson = GsonBuilder()
+            .registerTypeAdapter(UShort::class.java, object : JsonDeserializer<UShort>, JsonSerializer<UShort> {
+                override fun deserialize(json: JsonElement, typeOfT: Type, context: JsonDeserializationContext): UShort {
+                    return json.asInt.toUShort()
+                }
+                override fun serialize(src: UShort, typeOfSrc: Type, context: JsonSerializationContext): JsonElement {
+                    return JsonPrimitive(src.toInt())
+                }
+            })
+            .create()

Add these imports:

import com.google.gson.GsonBuilder
import com.google.gson.JsonDeserializer
import com.google.gson.JsonSerializer
import com.google.gson.JsonDeserializationContext
import com.google.gson.JsonSerializationContext
import com.google.gson.JsonElement
import com.google.gson.JsonPrimitive
import java.lang.reflect.Type

Also applies to: 100-100

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt` around lines
89 - 93, The dataContent getter uses gson.fromJson to parse MessageContent.Data
which contains a port: UShort, but the gson instance (gson) has no UShort
TypeAdapter so deserialization will fail; register a Gson
TypeAdapter/serializer/deserializer for kotlin.UShort on the gson used (the gson
property/instance) so UShort values are converted to/from JSON (e.g., serialize
as number/string and deserialize back to UShort), then rebuild the gson used by
the dataContent getter to use that adapter (update the gson construction where
the gson instance is created).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt`:
- Around line 89-93: The dataContent getter uses gson.fromJson to parse
MessageContent.Data which contains a port: UShort, but the gson instance (gson)
has no UShort TypeAdapter so deserialization will fail; register a Gson
TypeAdapter/serializer/deserializer for kotlin.UShort on the gson used (the gson
property/instance) so UShort values are converted to/from JSON (e.g., serialize
as number/string and deserialize back to UShort), then rebuild the gson used by
the dataContent getter to use that adapter (update the gson construction where
the gson instance is created).

In
`@app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt`:
- Around line 326-342: In MessagesRoutes.kt, when includeContent is true you
must guard the per-message parsing of message.textContent and
message.dataContent (which call gson.fromJson) so a single malformed JSON
doesn't fail the whole GET /messages response; wrap the parsing logic used to
create TextMessage(...) and DataMessage(...) in try/catch blocks, catch JSON
parsing exceptions from gson.fromJson, log the error with message
identifier/context, and return null for textMessage or dataMessage on failure so
the rest of the items still return; update the branches that set textMessage and
dataMessage to use these safe-parsing wrappers.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7f0aeea5-386a-4699-b71e-756265d378e7

📥 Commits

Reviewing files that changed from the base of the PR and between f703d38 and 215a6dc.

📒 Files selected for processing (13)
  • app/src/main/assets/api/swagger.json
  • app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/GetMessagesResponse.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/PostMessageResponse.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/DataMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/HashedMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/PostMessageRequest.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/TextMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesRepository.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/exceptions/ConflictException.kt
💤 Files with no reviewable changes (2)
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/PostMessageResponse.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/GetMessagesResponse.kt
✅ Files skipped from review due to trivial changes (5)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/exceptions/ConflictException.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/TextMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/HashedMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/DataMessage.kt
  • app/src/main/assets/api/swagger.json
🚧 Files skipped from review as they are similar to previous changes (4)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesRepository.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/PostMessageRequest.kt

Copy link
Copy Markdown

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/assets/api/swagger.json (1)

397-406: ⚠️ Potential issue | 🟠 Major

Incorrect type: object for enum reference will break code generators.

The state field references smsgateway.ProcessingState (a string enum) via allOf, but declares "type": "object". This contradicts the referenced schema's "type": "string" and can cause code generators to emit incorrect types.

The same issue appears in:

  • Line 642: Message.priority (should be integer, not object)
  • Line 802: MessageState.state (should be string, not object)
  • Line 882: RecipientState.state (should be string, not object)
  • Line 1101: Webhook.event (should be string, not object)

Remove the "type": "object" from these fields or change to match the referenced enum's type.

🛠️ Proposed fix for GetMessageResponse.state (apply similar fix to other affected fields)
           "state": {
             "allOf": [
               {
                 "$ref": "#/components/schemas/smsgateway.ProcessingState"
               }
             ],
             "description": "State",
-            "example": "Pending",
-            "type": "object"
+            "example": "Pending"
           },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/assets/api/swagger.json` around lines 397 - 406, The referenced
schema entries (e.g., GetMessageResponse.state, Message.priority,
MessageState.state, RecipientState.state, Webhook.event) declare "type":
"object" while using allOf to $ref enum schemas (like
smsgateway.ProcessingState) whose type is string or integer; remove the
incorrect "type": "object" (or replace it with the correct primitive type
matching the referenced schema, e.g., "type": "string" for
smsgateway.ProcessingState or "type": "integer" for priority) so the allOf/$ref
and declared type are consistent and code generators produce correct types.
🧹 Nitpick comments (1)
app/src/main/assets/api/swagger.json (1)

349-422: Clarify hashedMessage inclusion behavior.

The descriptions for textMessage and dataMessage state they're present "only when includeContent=true", but hashedMessage description says "if isHashed is true" without mentioning includeContent. Is hashedMessage always returned when isHashed=true, regardless of includeContent? If so, document this explicitly. If not, align the description with the other fields.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/assets/api/swagger.json` around lines 349 - 422, The swagger
schema is ambiguous about when smsgateway.HashedMessage is returned: update the
description for the hashedMessage property to explicitly state whether it is
gated by includeContent or returned whenever isHashed=true to match
textMessage/dataMessage behavior; specifically edit the hashedMessage
description to either "Present only when `includeContent=true` and
`isHashed=true`" or "Returned when `isHashed=true` regardless of
`includeContent`" (choose the correct behavior), ensuring consistency with the
textMessage and dataMessage descriptions and referencing the hashedMessage,
textMessage, dataMessage, includeContent and isHashed symbols so reviewers can
locate the change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/assets/api/swagger.json`:
- Around line 1074-1077: The OpenAPI spec lists "refresh_token" in TokenResponse
but the backend data class TokenResponse (TokenResponse.kt) does not include
that field; either remove "refresh_token" from
app/src/main/assets/api/swagger.json or add a corresponding property to the
TokenResponse data class and ensure serialization names match ("refresh_token"
vs refreshToken). Locate the TokenResponse class and the TokenResponse schema in
swagger.json, then either delete the "refresh_token" entry from the JSON schema
or add a String? refreshToken (with appropriate
`@JsonProperty`("refresh_token")/serialization annotation and any nullable
handling) and update any creation/mapper code that constructs TokenResponse so
the server returns the field consistently.

---

Outside diff comments:
In `@app/src/main/assets/api/swagger.json`:
- Around line 397-406: The referenced schema entries (e.g.,
GetMessageResponse.state, Message.priority, MessageState.state,
RecipientState.state, Webhook.event) declare "type": "object" while using allOf
to $ref enum schemas (like smsgateway.ProcessingState) whose type is string or
integer; remove the incorrect "type": "object" (or replace it with the correct
primitive type matching the referenced schema, e.g., "type": "string" for
smsgateway.ProcessingState or "type": "integer" for priority) so the allOf/$ref
and declared type are consistent and code generators produce correct types.

---

Nitpick comments:
In `@app/src/main/assets/api/swagger.json`:
- Around line 349-422: The swagger schema is ambiguous about when
smsgateway.HashedMessage is returned: update the description for the
hashedMessage property to explicitly state whether it is gated by includeContent
or returned whenever isHashed=true to match textMessage/dataMessage behavior;
specifically edit the hashedMessage description to either "Present only when
`includeContent=true` and `isHashed=true`" or "Returned when `isHashed=true`
regardless of `includeContent`" (choose the correct behavior), ensuring
consistency with the textMessage and dataMessage descriptions and referencing
the hashedMessage, textMessage, dataMessage, includeContent and isHashed symbols
so reviewers can locate the change.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3c013ef2-3ed0-4cfb-ab51-2f16eddab223

📥 Commits

Reviewing files that changed from the base of the PR and between 215a6dc and fdac3a4.

📒 Files selected for processing (1)
  • app/src/main/assets/api/swagger.json

Comment thread app/src/main/assets/api/swagger.json
@capcom6 capcom6 force-pushed the codex/add-message-content-to-get-/messages-response branch from fdac3a4 to 75cf7aa Compare April 11, 2026 09:42
Copy link
Copy Markdown

@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

♻️ Duplicate comments (1)
app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt (1)

89-92: ⚠️ Potential issue | 🔴 Critical

MessageContent.Data.port deserialization is unsafe with plain Gson.

dataContent (Line 89-Line 92) uses the gson instance from Line 100 (Gson()), but MessageContent.Data.port is UShort. This can fail at runtime when reading Data messages.

#!/bin/bash
# Verify whether UShort Gson adapters exist and how gson is initialized for Message deserialization.

rg -n "UShort|TypeAdapter|registerTypeAdapter|GsonBuilder\\(|Gson\\(" --type=kt -C2
sed -n '80,110p' app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt

Also applies to: 100-100

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt` around lines
89 - 92, The current dataContent getter uses the plain gson instance (Gson())
which cannot safely deserialize MessageContent.Data.port of type UShort; create
and use a GsonBuilder-backed gson that registers a custom
TypeAdapter/JsonSerializer/JsonDeserializer for kotlin.UShort (or its boxed
class) that converts numeric JSON values into UShort and handles nulls/invalid
values, replace the simple Gson() assignment with this GsonBuilder
configuration, and ensure the Message.dataContent getter continues to use that
gson so MessageContent.Data.port is deserialized safely.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt`:
- Around line 93-98: The pre-check using getMessage(...) before calling
messages.enqueue(...) is TOCTOU-racy and can let two concurrent requests slip
through; remove the pre-check and make conflict detection atomic by either
relying on messages.enqueue(...) to fail deterministically or by catching the
low-level DB unique-constraint exception thrown by messages.enqueue(...) and
rethrowing ConflictException(); update the MessagesService.kt flow so calls to
messages.enqueue(request) are wrapped to translate DB constraint errors into
ConflictException (reference getMessage, messages.enqueue, and
ConflictException).

---

Duplicate comments:
In `@app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt`:
- Around line 89-92: The current dataContent getter uses the plain gson instance
(Gson()) which cannot safely deserialize MessageContent.Data.port of type
UShort; create and use a GsonBuilder-backed gson that registers a custom
TypeAdapter/JsonSerializer/JsonDeserializer for kotlin.UShort (or its boxed
class) that converts numeric JSON values into UShort and handles nulls/invalid
values, replace the simple Gson() assignment with this GsonBuilder
configuration, and ensure the Message.dataContent getter continues to use that
gson so MessageContent.Data.port is deserialized safely.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 68cd3e95-d63d-4a60-b422-eec7710ddf34

📥 Commits

Reviewing files that changed from the base of the PR and between fdac3a4 and 75cf7aa.

📒 Files selected for processing (13)
  • app/src/main/assets/api/swagger.json
  • app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/GetMessagesResponse.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/PostMessageResponse.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/DataMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/HashedMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/PostMessageRequest.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/TextMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesRepository.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/exceptions/ConflictException.kt
💤 Files with no reviewable changes (2)
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/PostMessageResponse.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/GetMessagesResponse.kt
✅ Files skipped from review due to trivial changes (5)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/exceptions/ConflictException.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/TextMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/HashedMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/DataMessage.kt
  • app/src/main/assets/api/swagger.json
🚧 Files skipped from review as they are similar to previous changes (3)
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/PostMessageRequest.kt

Comment thread app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt Outdated
@capcom6 capcom6 force-pushed the codex/add-message-content-to-get-/messages-response branch from fca9066 to 188853e Compare April 14, 2026 00:59
Copy link
Copy Markdown

@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.

♻️ Duplicate comments (2)
app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt (1)

89-91: ⚠️ Potential issue | 🔴 Critical

Don’t rely on plain Gson() to round-trip Kotlin UShort.

MessageContent.Data.port is a Kotlin UShort, while Gson’s current docs describe built-in special handling around Java primitives/common types and exact-type custom adapters when you need something else. This means this new dataContent path should be verified rather than assumed; if it is not adapter-backed here, the first data-message read can fail while building the new response payloads. (google.github.io)

#!/bin/bash
set -euo pipefail

echo "MessageContent.Data definition:"
sed -n '1,40p' app/src/main/java/me/capcom/smsgateway/domain/MessageContent.kt

echo
echo "Message entity JSON accessors:"
sed -n '80,110p' app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt

echo
echo "Search for any UShort Gson adapter or configured GsonBuilder usage:"
rg -nP --type=kt 'UShortTypeAdapter|registerTypeAdapter|GsonBuilder\(|TypeAdapter<\s*UShort'

Expected: MessageContent.Data.port is UShort, this file still uses private val gson = Gson(), and this path is not obviously wired through a UShort adapter. If that is what you see, switch this accessor path to the app’s configured GsonBuilder or register an explicit adapter here.

Also applies to: 95-100

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt` around lines
89 - 91, The dataContent getter uses a plain Gson instance (private val gson =
Gson()) to deserialize MessageContent.Data which has a UShort field
(MessageContent.Data.port); replace this with the app's configured Gson (the
shared GsonBuilder instance) or create/register a UShort TypeAdapter and use
that Gson for the dataContent getter (also update the similar accessor around
lines 95-100) so UShort round-tripping is handled correctly rather than relying
on the default Gson().
app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt (1)

326-342: ⚠️ Potential issue | 🟠 Major

Don’t let one bad payload abort the whole response.

message.textContent / message.dataContent can throw here, and this helper is used by the paged list plus the always-include GET /messages/{id} path. Because these fields are optional, degrade just that row to null instead of turning the entire response into a 500.

💡 Minimal guard
-            textMessage = when (includeContent) {
-                true -> message.textContent?.let {
-                    TextMessage(it.text)
-                }
-
-                else -> null
-            },
-            dataMessage = when (includeContent) {
-                true -> message.dataContent?.let {
-                    DataMessage(
-                        data = it.data,
-                        port = it.port.toInt()
-                    )
-                }
-
-                else -> null
-            },
+            textMessage = if (includeContent) {
+                try {
+                    message.textContent?.let { TextMessage(it.text) }
+                } catch (_: RuntimeException) {
+                    null
+                }
+            } else {
+                null
+            },
+            dataMessage = if (includeContent) {
+                try {
+                    message.dataContent?.let {
+                        DataMessage(
+                            data = it.data,
+                            port = it.port.toInt()
+                        )
+                    }
+                } catch (_: RuntimeException) {
+                    null
+                }
+            } else {
+                null
+            },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt`
around lines 326 - 342, In MessagesRoutes.kt where the response row builds
textMessage and dataMessage (the when(includeContent) blocks that create
TextMessage and DataMessage from message.textContent and message.dataContent),
guard the optional payload access so a thrown exception degrades just that field
to null instead of bubbling to a 500; wrap each message.textContent /
message.dataContent access in a small try-catch (or use runCatching { …
}.getOrNull()) and on failure return null for that field, keeping the rest of
the row and the overall paged list / GET /messages/{id} response intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt`:
- Around line 89-91: The dataContent getter uses a plain Gson instance (private
val gson = Gson()) to deserialize MessageContent.Data which has a UShort field
(MessageContent.Data.port); replace this with the app's configured Gson (the
shared GsonBuilder instance) or create/register a UShort TypeAdapter and use
that Gson for the dataContent getter (also update the similar accessor around
lines 95-100) so UShort round-tripping is handled correctly rather than relying
on the default Gson().

In
`@app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt`:
- Around line 326-342: In MessagesRoutes.kt where the response row builds
textMessage and dataMessage (the when(includeContent) blocks that create
TextMessage and DataMessage from message.textContent and message.dataContent),
guard the optional payload access so a thrown exception degrades just that field
to null instead of bubbling to a 500; wrap each message.textContent /
message.dataContent access in a small try-catch (or use runCatching { …
}.getOrNull()) and on failure return null for that field, keeping the rest of
the row and the overall paged list / GET /messages/{id} response intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2d8aae70-7f03-4d12-b5fa-249388574595

📥 Commits

Reviewing files that changed from the base of the PR and between fca9066 and 188853e.

📒 Files selected for processing (13)
  • app/src/main/assets/api/swagger.json
  • app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/GetMessagesResponse.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/PostMessageResponse.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/DataMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/HashedMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/PostMessageRequest.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/TextMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesRepository.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/exceptions/ConflictException.kt
💤 Files with no reviewable changes (2)
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/PostMessageResponse.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/GetMessagesResponse.kt
✅ Files skipped from review due to trivial changes (4)
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/TextMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/HashedMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/exceptions/ConflictException.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/DataMessage.kt
🚧 Files skipped from review as they are similar to previous changes (3)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesRepository.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/Message.kt
  • app/src/main/assets/api/swagger.json

@capcom6 capcom6 force-pushed the codex/add-message-content-to-get-/messages-response branch from 188853e to aa13121 Compare April 15, 2026 01:21
@github-actions github-actions Bot removed the ready label Apr 15, 2026
Copy link
Copy Markdown

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/src/main/assets/api/swagger.json (1)

397-405: ⚠️ Potential issue | 🟠 Major

Remove type: "object" from scalar $ref wrappers.

These properties reference scalar enum schemas—smsgateway.ProcessingState (string values), smsgateway.MessagePriority (integer values), and smsgateway.WebhookEvent (string values)—but are wrapped in allOf with type: "object", creating a contradictory constraint. Validators and code generators cannot reconcile requiring an object type with accepting only scalar enum values. Remove the type: "object" line from these properties.

Occurs at lines 397-405, 635-643, 794-803, 874-882, and 1094-1102.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/assets/api/swagger.json` around lines 397 - 405, Several
properties (e.g., the "state" property wrapping smsgateway.ProcessingState, and
similar wrappers for smsgateway.MessagePriority and smsgateway.WebhookEvent) use
allOf to $ref scalar enum schemas but incorrectly include type: "object"; remove
the type: "object" entry from those allOf wrappers so the referenced scalar enum
types are not constrained to object, leaving the $ref, description and example
intact; locate the wrappers referencing smsgateway.ProcessingState,
smsgateway.MessagePriority, and smsgateway.WebhookEvent and delete only the
"type": "object" line in each.
♻️ Duplicate comments (3)
app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt (2)

83-93: ⚠️ Potential issue | 🟠 Major

Guard these computed accessors against bad stored payloads.

MessagesRoutes.toDomain() now reads these properties on both the list and detail endpoints. If any row has content that does not match the declared type, fromJson will throw here and turn the whole response into a 500. Catch parse failures here and return null/fallback per record instead of letting one bad row break the endpoint.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt` around lines
83 - 93, The computed accessors textContent and dataContent currently call
gson.fromJson(...) directly and will throw on malformed content; wrap each
gson.fromJson call in a try-catch that catches JSON parse exceptions (e.g.,
JsonSyntaxException/JsonParseException/RuntimeException) and returns null on
failure so a single bad payload doesn't raise a 500; modify the getters for
textContent and dataContent to perform parsing inside the try block and return
null in the catch, leaving other behavior unchanged.

89-100: ⚠️ Potential issue | 🔴 Critical

Use a configured Gson for MessageContent.Data.

MessageContent.Data.port is UShort, but this companion still uses a bare Gson(). Gson does not deserialize Kotlin unsigned types out of the box, so dataContent will fail at runtime for stored data messages until a UShort adapter or equivalent configured builder is used.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt` around lines
89 - 100, The current private gson in the Message companion uses a plain Gson
which cannot deserialize Kotlin unsigned types (so Message.dataContent ->
MessageContent.Data with UShort port will fail); replace the bare Gson() with
the app's configured Gson instance or build a Gson via GsonBuilder that
registers a UShort type adapter/serializer (or reuse an existing Gson provider)
and assign it to the companion object's gson so Message.dataContent correctly
deserializes MessageContent.Data.port; update the companion's private val gson
accordingly (referencing the companion object, gson, dataContent and
MessageContent.Data symbols).
app/src/main/assets/api/swagger.json (1)

1279-1284: ⚠️ Potential issue | 🟠 Major

Document how clients supply the refresh token.

The operation says it refreshes "with specified refresh token", but there is no request body, parameter, or distinct security scheme—just the same JWTAuth header used by normal authenticated calls. As written, clients cannot tell whether this endpoint expects an access token or a refresh token in Authorization.

Also applies to: 1488-1547

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/src/main/assets/api/swagger.json` around lines 1279 - 1284, The OpenAPI
entry for JWTAuth (name "Authorization", type "apiKey") doesn't explain how the
refresh endpoint receives the refresh token; update the refresh operation to
explicitly accept a refresh token either by (a) adding a distinct security
scheme such as "RefreshTokenAuth" (in header or cookie) and reference it in the
refresh operation's security requirement, or (b) adding a request parameter/body
parameter named "refresh_token" (string) to the refresh operation and clarifying
in its description that the Authorization header still expects the access token
while the refresh_token parameter carries the refresh token; ensure the
operation's description and schema reference "JWTAuth" and the new
"RefreshTokenAuth" or "refresh_token" param so clients know which token goes
where.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@app/src/main/assets/api/swagger.json`:
- Around line 349-357: The description for the dataMessage schema overstates the
includeContent requirement: update the "dataMessage" schema description (and the
analogous second block around lines ~414-421) to say that the object is present
for messages of type "data" and that inclusion depends on the endpoint (for list
endpoints it's present only when includeContent=true, whereas single-message
endpoints such as GET /messages/{id} always include content per
MessagesRoutes.kt). Change the phrasing to remove the absolute "Present only
when `includeContent=true`" and clearly state the endpoint-specific behavior so
the schema is accurate for both list and single-message responses.
- Around line 216-219: The OpenAPI schema requires Base64 but the server
(MessagesRoutes.kt handling POST /messages, around the dataMessage.data
handling) only checks for non-empty data; either align server to schema or relax
the schema—add a server-side Base64 validation in MessagesRoutes.kt: validate
dataMessage.data against the same regex
(^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$) and return a
400 with an explicit error when it fails, or alternatively remove the pattern
(and minLength/maxLength) from the swagger schema so the contract matches the
existing non-empty check.

---

Outside diff comments:
In `@app/src/main/assets/api/swagger.json`:
- Around line 397-405: Several properties (e.g., the "state" property wrapping
smsgateway.ProcessingState, and similar wrappers for smsgateway.MessagePriority
and smsgateway.WebhookEvent) use allOf to $ref scalar enum schemas but
incorrectly include type: "object"; remove the type: "object" entry from those
allOf wrappers so the referenced scalar enum types are not constrained to
object, leaving the $ref, description and example intact; locate the wrappers
referencing smsgateway.ProcessingState, smsgateway.MessagePriority, and
smsgateway.WebhookEvent and delete only the "type": "object" line in each.

---

Duplicate comments:
In `@app/src/main/assets/api/swagger.json`:
- Around line 1279-1284: The OpenAPI entry for JWTAuth (name "Authorization",
type "apiKey") doesn't explain how the refresh endpoint receives the refresh
token; update the refresh operation to explicitly accept a refresh token either
by (a) adding a distinct security scheme such as "RefreshTokenAuth" (in header
or cookie) and reference it in the refresh operation's security requirement, or
(b) adding a request parameter/body parameter named "refresh_token" (string) to
the refresh operation and clarifying in its description that the Authorization
header still expects the access token while the refresh_token parameter carries
the refresh token; ensure the operation's description and schema reference
"JWTAuth" and the new "RefreshTokenAuth" or "refresh_token" param so clients
know which token goes where.

In `@app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt`:
- Around line 83-93: The computed accessors textContent and dataContent
currently call gson.fromJson(...) directly and will throw on malformed content;
wrap each gson.fromJson call in a try-catch that catches JSON parse exceptions
(e.g., JsonSyntaxException/JsonParseException/RuntimeException) and returns null
on failure so a single bad payload doesn't raise a 500; modify the getters for
textContent and dataContent to perform parsing inside the try block and return
null in the catch, leaving other behavior unchanged.
- Around line 89-100: The current private gson in the Message companion uses a
plain Gson which cannot deserialize Kotlin unsigned types (so
Message.dataContent -> MessageContent.Data with UShort port will fail); replace
the bare Gson() with the app's configured Gson instance or build a Gson via
GsonBuilder that registers a UShort type adapter/serializer (or reuse an
existing Gson provider) and assign it to the companion object's gson so
Message.dataContent correctly deserializes MessageContent.Data.port; update the
companion's private val gson accordingly (referencing the companion object,
gson, dataContent and MessageContent.Data symbols).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5b82325b-6f69-441e-a1ec-c670ba99dae3

📥 Commits

Reviewing files that changed from the base of the PR and between 188853e and aa13121.

📒 Files selected for processing (13)
  • app/src/main/assets/api/swagger.json
  • app/src/main/java/me/capcom/smsgateway/data/entities/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/GetMessagesResponse.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/PostMessageResponse.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/DataMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/HashedMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/PostMessageRequest.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/TextMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/MessagesRoutes.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesRepository.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/exceptions/ConflictException.kt
💤 Files with no reviewable changes (2)
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/GetMessagesResponse.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/PostMessageResponse.kt
✅ Files skipped from review due to trivial changes (3)
  • app/src/main/java/me/capcom/smsgateway/modules/messages/exceptions/ConflictException.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/DataMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/TextMessage.kt
🚧 Files skipped from review as they are similar to previous changes (5)
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/HashedMessage.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesRepository.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/Message.kt
  • app/src/main/java/me/capcom/smsgateway/modules/messages/MessagesService.kt
  • app/src/main/java/me/capcom/smsgateway/modules/localserver/domain/messages/PostMessageRequest.kt

Comment thread app/src/main/assets/api/swagger.json
Comment thread app/src/main/assets/api/swagger.json
@capcom6 capcom6 merged commit 25b58b3 into master Apr 16, 2026
4 checks passed
@capcom6 capcom6 deleted the codex/add-message-content-to-get-/messages-response branch April 16, 2026 01:42
@coderabbitai coderabbitai Bot mentioned this pull request Apr 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Respond message data via API – GET /messages

1 participant