syntax = "proto3"; package chatto.api.v1; import "buf/validate/validate.proto"; import "chatto/api/v1/pagination.proto"; import "chatto/api/v1/presence.proto"; import "chatto/api/v1/users.proto"; import "google/protobuf/timestamp.proto"; // Public user/member row used by user directory, room membership, and mention // surfaces. message DirectoryMember { // Public user fields. User user = 1; // Explicit roles assigned to the user. Member listings include the virtual // `everyone` role for parity with Chatto's permission model. repeated string roles = 2; // Account creation time when known. google.protobuf.Timestamp created_at = 3; } // Request for members of one room. message ListMembersRequest { reserved 3, 4; reserved "limit", "offset"; // Required. Room whose effective members should be listed. Existing members // and room.manage holders may list a channel room; other nonmembers need both // room.list and room.join. string room_id = 1 [(buf.validate.field).string.min_len = 1]; // Optional case-insensitive search against login and display name. string search = 2 [(buf.validate.field).string.max_len = 100]; // Defaults to 250 results when absent or limit is zero. Maximum: 500. PageRequest page = 5; // Optional status filter applied before pagination. Empty means all statuses. // Select ONLINE, AWAY, and DO_NOT_DISTURB for all connected members. // Presence can change between pages; use realtime updates to keep it current. repeated PresenceStatus presence_statuses = 6 [(buf.validate.field).repeated = { max_items: 4 unique: true items: {enum: {defined_only: true, not_in: [0]}} }]; } // Room membership IDs. Resolve profiles with UserService.BatchGetUsers. // Empty searches do not read user profiles. Search results require profile // reads to match names. Both paths use ascending user ID order. message ListMembersResponse { reserved 1, 2, 3; reserved "members", "total_count", "has_more"; // Current member IDs in ascending order. Missing or deleted users are omitted. repeated string user_ids = 5; // Page metadata for the members that match both filters. PageInfo page = 4; } // Request one member of one room by stable user ID. message GetMemberRequest { // Required room ID. string room_id = 1 [(buf.validate.field).string.min_len = 1]; // Required target user ID. string user_id = 2 [(buf.validate.field).string.min_len = 1]; } // Room member response. message GetMemberResponse { // Requested room member. DirectoryMember member = 1; } // Request room member rows for a set of stable user IDs. message BatchGetMembersRequest { // Required room ID. string room_id = 1 [(buf.validate.field).string.min_len = 1]; // Required target user IDs. Unknown IDs and users that are not members of the // room are omitted from the response. repeated string user_ids = 2 [(buf.validate.field).repeated = { min_items: 1 max_items: 100 items: { string: {min_len: 1} } }]; } // Batch room member response. message BatchGetMembersResponse { // Found members. The server preserves first-seen request order and // de-duplicates repeated IDs. repeated DirectoryMember members = 1; }