threads.proto 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. syntax = "proto3";
  2. package chatto.api.v1;
  3. import "buf/validate/validate.proto";
  4. import "chatto/api/v1/message_types.proto";
  5. import "chatto/api/v1/pagination.proto";
  6. import "chatto/api/v1/read_state.proto";
  7. import "chatto/api/v1/room_timeline.proto";
  8. import "chatto/api/v1/rooms.proto";
  9. // Selects threads by the author of their root message, not their replies.
  10. enum ThreadRootAuthorFilter {
  11. // Include all root authors.
  12. THREAD_ROOT_AUTHOR_FILTER_UNSPECIFIED = 0;
  13. // Include only roots authored by the authenticated viewer.
  14. THREAD_ROOT_AUTHOR_FILTER_VIEWER = 1;
  15. // Include only roots authored by other users.
  16. THREAD_ROOT_AUTHOR_FILTER_OTHERS = 2;
  17. }
  18. // Current follow state for one thread and viewer.
  19. message ThreadFollowState {
  20. // Room containing the thread.
  21. string room_id = 1;
  22. // Event ID of the root message for the thread.
  23. string thread_root_event_id = 2;
  24. // True when the current user follows the thread.
  25. bool following = 3;
  26. }
  27. // Request to follow one message thread.
  28. message FollowThreadRequest {
  29. // Required. Room containing the thread.
  30. string room_id = 1 [(buf.validate.field).string.min_len = 1];
  31. // Required. Event ID of the root message for the thread.
  32. string thread_root_event_id = 2 [(buf.validate.field).string.min_len = 1];
  33. }
  34. // Result of following a thread.
  35. message FollowThreadResponse {
  36. reserved 1;
  37. reserved "following";
  38. // Current follow state after the operation.
  39. ThreadFollowState state = 2;
  40. }
  41. // Request to stop following one message thread.
  42. message UnfollowThreadRequest {
  43. // Required. Room containing the thread.
  44. string room_id = 1 [(buf.validate.field).string.min_len = 1];
  45. // Required. Event ID of the root message for the thread.
  46. string thread_root_event_id = 2 [(buf.validate.field).string.min_len = 1];
  47. }
  48. // Result of unfollowing a thread.
  49. message UnfollowThreadResponse {
  50. reserved 1;
  51. reserved "following";
  52. // Current follow state after the operation.
  53. ThreadFollowState state = 2;
  54. }
  55. // One followed thread for the current user.
  56. message FollowedThread {
  57. reserved 1 to 3, 5 to 7;
  58. reserved "room_id", "room_name", "thread_root_event_id", "reply_count", "last_reply_at", "has_unread";
  59. // Renderable root message, when the root is still visible.
  60. Message root_message = 4;
  61. // Room containing the thread.
  62. RoomSummary room = 8;
  63. // Aggregated thread state.
  64. ThreadSummary thread = 9;
  65. // Most recent visible reply, when the thread has one.
  66. Message latest_reply = 10;
  67. // User IDs used to derive a direct-message conversation label. Empty for
  68. // channel rooms.
  69. repeated string direct_message_participant_user_ids = 11;
  70. }
  71. // Request for a page of followed threads for the current user.
  72. message ListFollowedThreadsRequest {
  73. reserved 1, 2;
  74. reserved "limit", "offset";
  75. // Defaults to 20 results when absent or limit is zero. Maximum: 100.
  76. PageRequest page = 3;
  77. // Include followed direct-message threads. Defaults to false so older
  78. // clients retain the channel-only result shape.
  79. bool include_direct_message_threads = 4;
  80. // Return only threads with replies that the viewer has not read. The page
  81. // total then counts only these threads. Older servers ignore this field and
  82. // return all followed threads.
  83. bool unread_only = 5;
  84. // Filter root authors before pagination and total counts. Threads whose
  85. // root author is unavailable are omitted when a filter is selected.
  86. ThreadRootAuthorFilter root_author_filter = 6 [(buf.validate.field).enum.defined_only = true];
  87. }
  88. // Response containing one followed-thread page.
  89. message ListFollowedThreadsResponse {
  90. reserved 2, 3;
  91. reserved "total_count", "has_more";
  92. // Followed threads in newest-activity-first order.
  93. repeated FollowedThread threads = 1;
  94. // Hot-path related entities needed to render this feed page without
  95. // per-thread hydration.
  96. RoomTimelineIncludes includes = 4;
  97. // Page metadata.
  98. PageInfo page = 5;
  99. }
  100. // Manages thread follow state for the current user.
  101. service ThreadService {
  102. // Reads the current viewer's stored marker without changing it. Requires the
  103. // same membership and read access as MarkThreadAsRead. Missing resources
  104. // return NOT_FOUND; inaccessible resources return PERMISSION_DENIED.
  105. rpc GetThreadReadState(GetThreadReadStateRequest) returns (GetThreadReadStateResponse);
  106. // Reads up to 100 states under the same authorization as GetThreadReadState.
  107. // Missing and inaccessible resources are omitted; duplicates use first-seen order.
  108. rpc BatchGetThreadReadStates(BatchGetThreadReadStatesRequest) returns (BatchGetThreadReadStatesResponse);
  109. // Lists distinct authors of non-retracted replies, excluding erased users.
  110. // The root author is included only if they also replied. Requires the same
  111. // membership and message-read access as GetThreadEvents.
  112. rpc ListThreadParticipants(ListThreadParticipantsRequest) returns (ListThreadParticipantsResponse);
  113. // Returns followed threads in rooms where the current user is a member.
  114. // All threads also require message.read or an active relationship with
  115. // message.read-interactions. Direct-message threads are returned only when
  116. // include_direct_message_threads is true.
  117. // The result includes enough root and latest-reply data for clients to render
  118. // the list without extra per-thread fetches.
  119. // Activity can reorder the live result between offset pages. After a thread
  120. // activity update, clients must restart paging at offset zero.
  121. rpc ListFollowedThreads(ListFollowedThreadsRequest) returns (ListFollowedThreadsResponse);
  122. // Follows a thread for the current user. Room membership plus message.read or
  123. // an active relationship with message.read-interactions are required.
  124. // Followed threads can be surfaced in clients and can participate in thread
  125. // notification behavior.
  126. rpc FollowThread(FollowThreadRequest) returns (FollowThreadResponse);
  127. // Stops following a thread for the current user. Room membership plus
  128. // message.read or an active relationship with message.read-interactions are
  129. // required. The response reports
  130. // the resulting follow state so clients can update local UI immediately.
  131. rpc UnfollowThread(UnfollowThreadRequest) returns (UnfollowThreadResponse);
  132. // Returns one page of events in a message thread. Room membership is
  133. // required. Reads also require message.read or an active relationship with
  134. // message.read-interactions. Initial pages include the thread root message; cursor pages
  135. // return replies in the requested direction.
  136. rpc GetThreadEvents(GetThreadEventsRequest) returns (GetThreadEventsResponse);
  137. // Returns a thread timeline window centered around a specific event. Use this
  138. // to open a reply from a notification or search result in context. Returns
  139. // NOT_FOUND when the thread root or anchor event is missing or hidden.
  140. // Returns PERMISSION_DENIED when room membership is missing, both read modes
  141. // are missing, or an interaction-scoped account has no relationship with the
  142. // thread.
  143. rpc GetThreadEventsAround(GetThreadEventsAroundRequest) returns (GetThreadEventsAroundResponse);
  144. // Marks a thread timeline as read through the supplied event without changing
  145. // the room-level read marker. Room membership plus message.read or an active
  146. // relationship with message.read-interactions are required.
  147. rpc MarkThreadAsRead(MarkThreadAsReadRequest) returns (MarkThreadAsReadResponse);
  148. }
  149. // Request a complete thread participant collection, ordered by user ID ascending.
  150. message ListThreadParticipantsRequest {
  151. // Room containing the thread.
  152. string room_id = 1 [(buf.validate.field).string.min_len = 1];
  153. // Root message ID.
  154. string thread_root_event_id = 2 [(buf.validate.field).string.min_len = 1];
  155. // Defaults to 50 results. Maximum: 100. Zero uses the default.
  156. PageRequest page = 3;
  157. }
  158. // A page of distinct reply authors. An empty thread returns an empty page.
  159. message ListThreadParticipantsResponse {
  160. // User IDs in this page. Use UserService.BatchGetUsers for profiles.
  161. repeated string user_ids = 1;
  162. // Count and continuation for all current participants.
  163. PageInfo page = 2;
  164. }