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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed

- `POST /sessions/{sessionId}/chats/unread` publishes its own `MarkChatUnreadDto` rather than sharing `MarkChatReadDto`. The body is unchanged (`chatId` alone), but a generated client sees the schema under a new name.
- ⚠️ **Breaking (Go and Java clients).** `subscribePresence` takes its own `SubscribePresenceRequest` rather than the shared `MarkChatRequest`, which now serves `markUnread` alone. Swap the type at the call site; the wire body is unchanged. `SubscribePresenceDto` had no contract-gate coverage while one type stood for two routes.

### Fixed

Expand Down
12 changes: 8 additions & 4 deletions scripts/check-contract-shapes.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ const MAPPINGS = {
JoinGroupRequest: 'JoinGroupDto',
MarkChatReadRequest: 'MarkChatReadDto',
MarkChatRequest: 'MarkChatUnreadDto',
SubscribePresenceRequest: 'SubscribePresenceDto',
MessageListResponse: 'MessageListResponseDto',
MessageRecord: 'MessageListItemDto',
MessageResponse: 'MessageResponseDto',
Expand Down Expand Up @@ -165,11 +166,11 @@ const MAPPINGS = {
* these floors as pairs are added makes the shrink loud.
*/
const MINIMUM_MAPPED = {
'sdk/javascript/src/types.ts': 79,
'sdk/javascript/src/types.ts': 80,
'dashboard/src/services/api.ts': 20,
'sdk/python/openwa/types.py': 74,
'sdk/go': 75,
'sdk/java': 79,
'sdk/python/openwa/types.py': 75,
'sdk/go': 76,
'sdk/java': 80,
};

/** Known drift, deliberately not gated yet — each line is a to-adjudicate follow-up. */
Expand Down Expand Up @@ -233,6 +234,7 @@ const PYTHON_MAPPING = {
JoinGroupRequest: 'JoinGroupDto',
MarkChatReadRequest: 'MarkChatReadDto',
MarkChatRequest: 'MarkChatUnreadDto',
SubscribePresenceRequest: 'SubscribePresenceDto',
MessageListResponse: 'MessageListResponseDto',
MessageRecord: 'MessageListItemDto',
MessageResponse: 'MessageResponseDto',
Expand Down Expand Up @@ -311,6 +313,7 @@ const GO_MAPPING = {
JoinGroupRequest: 'JoinGroupDto',
MarkChatReadRequest: 'MarkChatReadDto',
MarkChatRequest: 'MarkChatUnreadDto',
SubscribePresenceRequest: 'SubscribePresenceDto',
MessageListResponse: 'MessageListResponseDto',
MessageRecord: 'MessageListItemDto',
MessageResponse: 'MessageResponseDto',
Expand Down Expand Up @@ -393,6 +396,7 @@ const JAVA_MAPPING = {
JoinGroupRequest: 'JoinGroupDto',
MarkChatReadRequest: 'MarkChatReadDto',
MarkChatRequest: 'MarkChatUnreadDto',
SubscribePresenceRequest: 'SubscribePresenceDto',
MessageListResponse: 'MessageListResponseDto',
MessageRecord: 'MessageListItemDto',
MessageResponse: 'MessageResponseDto',
Expand Down
2 changes: 1 addition & 1 deletion sdk/go/chats.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func (s *ChatsService) List(ctx context.Context, sessionID string, query *ListCh
// The subscription belongs to the connection and does NOT survive a restart or an automatic
// reconnect, so re-issue it when the session comes back. Subscribe per chat: WhatsApp emits an
// update on every transition, so a broad subscription is a firehose. whatsapp-web.js answers 501.
func (s *ChatsService) SubscribePresence(ctx context.Context, sessionID string, body MarkChatRequest) (*SuccessResult, error) {
func (s *ChatsService) SubscribePresence(ctx context.Context, sessionID string, body SubscribePresenceRequest) (*SuccessResult, error) {
var out SuccessResult
err := s.client.do(ctx, "POST", "/api/sessions/"+pathEscape(sessionID)+"/presence/subscribe", nil, body, &out)
return &out, err
Expand Down
2 changes: 1 addition & 1 deletion sdk/go/routing_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ func TestRouting(t *testing.T) {

{"Chats.List", func(c *Client) { c.Chats.List(ctx, "s1", nil) }, "GET", "/api/sessions/s1/chats"},
{"Chats.MarkRead", func(c *Client) { c.Chats.MarkRead(ctx, "s1", MarkChatReadRequest{}) }, "POST", "/api/sessions/s1/chats/read"},
{"Chats.SubscribePresence", func(c *Client) { c.Chats.SubscribePresence(ctx, "s1", MarkChatRequest{}) }, "POST", "/api/sessions/s1/presence/subscribe"},
{"Chats.SubscribePresence", func(c *Client) { c.Chats.SubscribePresence(ctx, "s1", SubscribePresenceRequest{}) }, "POST", "/api/sessions/s1/presence/subscribe"},
{"Channels.Create", func(c *Client) { c.Channels.Create(ctx, "s1", CreateChannelRequest{}) }, "POST", "/api/sessions/s1/channels"},
{"Channels.Delete", func(c *Client) { c.Channels.Delete(ctx, "s1", "ch1") }, "POST", "/api/sessions/s1/channels/ch1/delete"},
{"Channels.Mute", func(c *Client) { c.Channels.Mute(ctx, "s1", "ch1", MuteChannelRequest{}) }, "POST", "/api/sessions/s1/channels/ch1/mute"},
Expand Down
7 changes: 6 additions & 1 deletion sdk/go/types_chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,16 @@ type SetOwnPresenceRequest struct {
Available bool `json:"available"`
}

// MarkChatRequest marks a chat unread, or subscribes to its presence.
// MarkChatRequest marks a chat unread.
type MarkChatRequest struct {
ChatID string `json:"chatId"`
}

// SubscribePresenceRequest subscribes to a chat's presence.
type SubscribePresenceRequest struct {
ChatID string `json:"chatId"`
}

// MarkChatReadRequest marks a chat read, optionally naming the messages to acknowledge.
type MarkChatReadRequest struct {
ChatID string `json:"chatId"`
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.rmyndharis.openwa.model;

/** Request body for marking a chat unread, or subscribing to its presence. */
/** Request body for marking a chat unread. */
public record MarkChatRequest(String chatId) {
public static Builder builder() {
return new Builder();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.rmyndharis.openwa.model;

/** Request body for subscribing to a chat's presence. */
public record SubscribePresenceRequest(String chatId) {
public static Builder builder() {
return new Builder();
}

public static final class Builder {
private String chatId;

/** WhatsApp chat id (JID), e.g. {@code 628123456789@c.us}. */
public Builder chatId(String v) {
this.chatId = v;
return this;
}

public SubscribePresenceRequest build() {
return new SubscribePresenceRequest(chatId);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.rmyndharis.openwa.model.ListChatsQuery;
import com.rmyndharis.openwa.model.MarkChatReadRequest;
import com.rmyndharis.openwa.model.MarkChatRequest;
import com.rmyndharis.openwa.model.SubscribePresenceRequest;
import com.rmyndharis.openwa.model.MuteChatRequest;
import com.rmyndharis.openwa.model.PinChatRequest;
import com.rmyndharis.openwa.model.SendChatStateRequest;
Expand Down Expand Up @@ -50,7 +51,7 @@ public List<ChatSummary> list(String sessionId, ListChatsQuery query) {
* reconnect, so re-issue it when the session comes back. Subscribe per chat: WhatsApp emits an
* update on every transition. whatsapp-web.js answers {@code 501}.
*/
public SuccessResult subscribePresence(String sessionId, MarkChatRequest body) {
public SuccessResult subscribePresence(String sessionId, SubscribePresenceRequest body) {
return client.request(
HttpMethod.POST,
"/api/sessions/" + encodeSegment(sessionId) + "/presence/subscribe",
Expand Down
3 changes: 2 additions & 1 deletion sdk/javascript/src/resources/chats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import type {
DeleteChatRequest,
MarkChatRequest,
MarkChatReadRequest,
SubscribePresenceRequest,
ChatPresence,
SendChatStateRequest,
SuccessResult,
Expand Down Expand Up @@ -48,7 +49,7 @@ export class ChatsResource {
* reconnect, so re-issue it when the session comes back. Subscribe per chat: WhatsApp emits an
* update on every transition, so a broad subscription is a firehose. whatsapp-web.js answers 501.
*/
subscribePresence(sessionId: string, body: MarkChatRequest): Promise<SuccessResult> {
subscribePresence(sessionId: string, body: SubscribePresenceRequest): Promise<SuccessResult> {
return this.client.request<SuccessResult>({
method: 'POST',
path: `/api/sessions/${encodeSegment(sessionId)}/presence/subscribe`,
Expand Down
7 changes: 6 additions & 1 deletion sdk/javascript/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -968,11 +968,16 @@ export interface TransferChannelOwnershipRequest {
newOwnerId: Jid;
}

/** Body for {@link ChatsResource.markUnread} and {@link ChatsResource.subscribePresence}. */
/** Body for {@link ChatsResource.markUnread}. */
export interface MarkChatRequest {
chatId: Jid;
}

/** Body for {@link ChatsResource.subscribePresence}. */
export interface SubscribePresenceRequest {
chatId: Jid;
}

/** Body for {@link ChatsResource.markRead}. */
export interface MarkChatReadRequest extends MarkChatRequest {
/**
Expand Down
3 changes: 2 additions & 1 deletion sdk/python/openwa/resources/chats.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
DeleteChatRequest,
MarkChatReadRequest,
MarkChatRequest,
SubscribePresenceRequest,
SendChatStateRequest,
SuccessResult,
)
Expand All @@ -38,7 +39,7 @@ def __init__(self, http: "HttpExecutor") -> None:
def list(self, session_id: str, query: ListChatsQuery | None = None) -> list[ChatSummary]:
return self._http.request("GET", f"/api/sessions/{quote_segment(session_id)}/chats", query=query)

def subscribe_presence(self, session_id: str, body: MarkChatRequest) -> SuccessResult:
def subscribe_presence(self, session_id: str, body: SubscribePresenceRequest) -> SuccessResult:
"""Subscribe to a chat's presence; updates arrive as presence.update events.

Presence cannot be fetched from either engine, only received. The subscription belongs to
Expand Down
7 changes: 6 additions & 1 deletion sdk/python/openwa/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -882,7 +882,12 @@ class ChatSummary(TypedDict):


class MarkChatRequest(TypedDict):
# Body for mark_unread and subscribe_presence, both of which take the chat id alone.
# Body for mark_unread.
chatId: Jid


class SubscribePresenceRequest(TypedDict):
# Body for subscribe_presence.
chatId: Jid


Expand Down
Loading