swagger: "2.0"
info:
  title: HY Room Service API
  version: "1.0.0"
  description: |
    room-service 当前只暴露内部 gRPC + protobuf 接口，没有 HTTP JSON router。
    本文件用 OpenAPI 2.0 记录 gRPC 合约，`paths` 使用 gRPC full method 作为文档路径，不代表真实 HTTP endpoint。
    腾讯云 IM 房间系统消息是 room-service 的外发消息契约，记录在 definitions 中。
host: localhost:13001
basePath: /
schemes:
  - http
consumes:
  - application/grpc+proto
produces:
  - application/grpc+proto
tags:
  - name: room-command
    description: RoomCommandService，改变房间状态的命令接口。
  - name: room-query
    description: RoomQueryService，不改变 Room Cell 状态的读模型查询。
  - name: room-guard
    description: RoomGuardService，腾讯云 IM 入群和发言前的同步守卫。
  - name: health
    description: 标准 grpc.health.v1.Health。
responses:
  GRPCError:
    description: gRPC status error；稳定业务原因放在 google.rpc.ErrorInfo.reason。
    schema:
      $ref: "#/definitions/GRPCError"
paths:
  /hyapp.room.v1.RoomCommandService/CreateRoom:
    post:
      tags:
        - room-command
      summary: 创建房间
      operationId: roomCreateRoom
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/CreateRoom
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/CreateRoomRequest"
      responses:
        "200":
          description: 创建成功；CreateRoom 会确保腾讯云 IM 群组存在后再提交房间状态；同一个 actor 只能作为 owner 创建一个房间，重复创建返回 Conflict。
          schema:
            $ref: "#/definitions/CreateRoomResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/UpdateRoomProfile:
    post:
      tags:
        - room-command
      summary: 修改房间资料和座位数
      operationId: roomUpdateRoomProfile
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/UpdateRoomProfile
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/UpdateRoomProfileRequest"
      responses:
        "200":
          description: 修改成功；资料、座位数、snapshot、command log 和 outbox 已经通过 Room Cell 提交。
          schema:
            $ref: "#/definitions/UpdateRoomProfileResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/JoinRoom:
    post:
      tags:
        - room-command
      summary: 加入房间业务 presence
      operationId: roomJoinRoom
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/JoinRoom
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/JoinRoomRequest"
      responses:
        "200":
          description: 加入成功；只维护 room-service presence，不创建腾讯云 IM 连接。
          schema:
            $ref: "#/definitions/JoinRoomResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/LeaveRoom:
    post:
      tags:
        - room-command
      summary: 离开房间业务 presence
      operationId: roomLeaveRoom
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/LeaveRoom
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/LeaveRoomRequest"
      responses:
        "200":
          description: 离房成功；若用户在麦上会释放麦位。
          schema:
            $ref: "#/definitions/LeaveRoomResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/MicUp:
    post:
      tags:
        - room-command
      summary: 上麦
      operationId: roomMicUp
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/MicUp
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/MicUpRequest"
      responses:
        "200":
          description: 上麦成功。
          schema:
            $ref: "#/definitions/MicUpResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/MicDown:
    post:
      tags:
        - room-command
      summary: 下麦
      operationId: roomMicDown
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/MicDown
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/MicDownRequest"
      responses:
        "200":
          description: 下麦成功。
          schema:
            $ref: "#/definitions/MicDownResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/ChangeMicSeat:
    post:
      tags:
        - room-command
      summary: 调整麦位
      operationId: roomChangeMicSeat
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/ChangeMicSeat
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/ChangeMicSeatRequest"
      responses:
        "200":
          description: 调整成功。
          schema:
            $ref: "#/definitions/ChangeMicSeatResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/ConfirmMicPublishing:
    post:
      tags:
        - room-command
      summary: 确认 RTC 音频发布成功
      operationId: roomConfirmMicPublishing
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/ConfirmMicPublishing
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/ConfirmMicPublishingRequest"
      responses:
        "200":
          description: 当前 mic_session 确认成功；旧 session、旧 room_version 或旧 event_time 会被安全忽略。
          schema:
            $ref: "#/definitions/ConfirmMicPublishingResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/SetMicSeatLock:
    post:
      tags:
        - room-command
      summary: 锁定或解锁麦位
      operationId: roomSetMicSeatLock
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/SetMicSeatLock
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/SetMicSeatLockRequest"
      responses:
        "200":
          description: 锁麦状态修改成功。
          schema:
            $ref: "#/definitions/SetMicSeatLockResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/SetChatEnabled:
    post:
      tags:
        - room-command
      summary: 开启或关闭公屏
      operationId: roomSetChatEnabled
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/SetChatEnabled
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/SetChatEnabledRequest"
      responses:
        "200":
          description: 公屏开关修改成功；结果会影响 CheckSpeakPermission。
          schema:
            $ref: "#/definitions/SetChatEnabledResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/SetRoomAdmin:
    post:
      tags:
        - room-command
      summary: 添加或移除房间管理员
      operationId: roomSetRoomAdmin
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/SetRoomAdmin
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/SetRoomAdminRequest"
      responses:
        "200":
          description: 管理员集合修改成功。
          schema:
            $ref: "#/definitions/SetRoomAdminResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/MuteUser:
    post:
      tags:
        - room-command
      summary: 设置房间内禁言
      operationId: roomMuteUser
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/MuteUser
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/MuteUserRequest"
      responses:
        "200":
          description: 禁言状态修改成功；结果会影响 CheckSpeakPermission。
          schema:
            $ref: "#/definitions/MuteUserResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/KickUser:
    post:
      tags:
        - room-command
      summary: 踢出房间用户
      operationId: roomKickUser
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/KickUser
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/KickUserRequest"
      responses:
        "200":
          description: 踢人成功；结果会影响 VerifyRoomPresence 和 CheckSpeakPermission。
          schema:
            $ref: "#/definitions/KickUserResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/UnbanUser:
    post:
      tags:
        - room-command
      summary: 解除房间 ban
      operationId: roomUnbanUser
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/UnbanUser
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/UnbanUserRequest"
      responses:
        "200":
          description: 解封成功；不会自动恢复 presence、麦位或管理员身份。
          schema:
            $ref: "#/definitions/UnbanUserResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomCommandService/SendGift:
    post:
      tags:
        - room-command
      summary: 发送礼物
      operationId: roomSendGift
      x-grpc-full-method: /hyapp.room.v1.RoomCommandService/SendGift
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/SendGiftRequest"
      responses:
        "200":
          description: 扣费成功并落入房间状态。
          schema:
            $ref: "#/definitions/SendGiftResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomGuardService/CheckSpeakPermission:
    post:
      tags:
        - room-guard
      summary: 发言前守卫
      operationId: roomCheckSpeakPermission
      x-grpc-full-method: /hyapp.room.v1.RoomGuardService/CheckSpeakPermission
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/CheckSpeakPermissionRequest"
      responses:
        "200":
          description: 返回是否允许用户在房间发言。
          schema:
            $ref: "#/definitions/CheckSpeakPermissionResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomGuardService/VerifyRoomPresence:
    post:
      tags:
        - room-guard
      summary: 入群前 presence 守卫
      operationId: roomVerifyRoomPresence
      x-grpc-full-method: /hyapp.room.v1.RoomGuardService/VerifyRoomPresence
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/VerifyRoomPresenceRequest"
      responses:
        "200":
          description: 返回用户业务上是否仍在房间内。
          schema:
            $ref: "#/definitions/VerifyRoomPresenceResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomQueryService/GetCurrentRoom:
    post:
      tags:
        - room-query
      summary: 查询用户当前可恢复房间
      operationId: roomGetCurrentRoom
      description: 启动、回前台和网络恢复时使用；只读 room_user_presence 投影并用 Room Cell 快照二次校验，不会隐式 JoinRoom 或刷新 presence。
      x-grpc-full-method: /hyapp.room.v1.RoomQueryService/GetCurrentRoom
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/GetCurrentRoomRequest"
      responses:
        "200":
          description: 返回是否存在可恢复房间，以及是否需要重新入 IM 群和重新签 RTC token。
          schema:
            $ref: "#/definitions/GetCurrentRoomResponse"
        default:
          $ref: "#/responses/GRPCError"
  /hyapp.room.v1.RoomQueryService/GetRoomSnapshot:
    post:
      tags:
        - room-query
      summary: 查询房间完整快照
      operationId: roomGetRoomSnapshot
      description: 房间页主动同步使用；只读 Room Cell/snapshot，不刷新 presence，不隐式 JoinRoom，viewer 必须仍在该房间。
      x-grpc-full-method: /hyapp.room.v1.RoomQueryService/GetRoomSnapshot
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/GetRoomSnapshotRequest"
      responses:
        "200":
          description: 返回当前完整房间快照。
          schema:
            $ref: "#/definitions/GetRoomSnapshotResponse"
        default:
          $ref: "#/responses/GRPCError"
  /grpc.health.v1.Health/Check:
    post:
      tags:
        - health
      summary: 标准 gRPC health check
      operationId: roomHealthCheck
      x-grpc-full-method: /grpc.health.v1.Health/Check
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/HealthCheckRequest"
      responses:
        "200":
          description: 返回 SERVING 或 NOT_SERVING；未知 service 返回 gRPC NotFound。
          schema:
            $ref: "#/definitions/HealthCheckResponse"
        default:
          $ref: "#/responses/GRPCError"
  /grpc.health.v1.Health/Watch:
    post:
      tags:
        - health
      summary: 标准 gRPC health watch
      operationId: roomHealthWatch
      x-grpc-full-method: /grpc.health.v1.Health/Watch
      x-server-streaming: true
      parameters:
        - name: body
          in: body
          required: true
          schema:
            $ref: "#/definitions/HealthCheckRequest"
      responses:
        "200":
          description: 服务端流式推送健康状态变化。
          schema:
            $ref: "#/definitions/HealthCheckResponse"
        default:
          $ref: "#/responses/GRPCError"
definitions:
  RequestMeta:
    type: object
    required:
      - request_id
      - command_id
      - actor_user_id
      - room_id
    properties:
      request_id:
        type: string
        description: 后端生成的链路追踪 ID，不参与幂等。
      command_id:
        type: string
        description: 客户端按用户写动作生成的幂等命令 ID，同一动作重试必须复用。
      actor_user_id:
        type: integer
        format: int64
      room_id:
        type: string
        pattern: "^[A-Za-z0-9_-]{1,48}$"
        maxLength: 48
        description: 命令所属房间 ID；CreateRoom 时必须同时满足腾讯 IM GroupID 和 RTC strRoomId 限制。
      gateway_node_id:
        type: string
      session_id:
        type: string
      sent_at_ms:
        type: integer
        format: int64
  CommandResult:
    type: object
    properties:
      applied:
        type: boolean
      room_version:
        type: integer
        format: int64
      server_time_ms:
        type: integer
        format: int64
  RoomUser:
    type: object
    properties:
      user_id:
        type: integer
        format: int64
      role:
        type: string
      joined_at_ms:
        type: integer
        format: int64
      last_seen_at_ms:
        type: integer
        format: int64
  SeatState:
    type: object
    properties:
      seat_no:
        type: integer
        format: int32
      user_id:
        type: integer
        format: int64
      locked:
        type: boolean
      publish_state:
        type: string
        enum:
          - pending_publish
          - publishing
          - idle
        description: pending_publish 表示业务占麦成功但 RTC 尚未确认发流；publishing 表示已确认发布音频；空麦可为空或 idle。
      mic_session_id:
        type: string
        description: 单次上麦发流会话 ID；客户端确认和 RTC webhook 必须原样带回。
      publish_deadline_ms:
        type: integer
        format: int64
        description: pending_publish 必须完成确认的截止时间；超时会自动下麦。
      mic_session_room_version:
        type: integer
        format: int64
        description: 创建当前 mic_session 的房间版本，用于丢弃旧版本 RTC 事件。
      last_publish_event_time_ms:
        type: integer
        format: int64
        description: 当前麦位已接受的最新发布事件时间。
  RankItem:
    type: object
    properties:
      user_id:
        type: integer
        format: int64
      score:
        type: integer
        format: int64
      gift_value:
        type: integer
        format: int64
      updated_at_ms:
        type: integer
        format: int64
  RoomSnapshot:
    type: object
    properties:
      room_id:
        type: string
      owner_user_id:
        type: integer
        format: int64
      mode:
        type: string
      status:
        type: string
      chat_enabled:
        type: boolean
      mic_seats:
        type: array
        items:
          $ref: "#/definitions/SeatState"
      online_users:
        type: array
        items:
          $ref: "#/definitions/RoomUser"
      admin_user_ids:
        type: array
        items:
          type: integer
          format: int64
      ban_user_ids:
        type: array
        items:
          type: integer
          format: int64
      mute_user_ids:
        type: array
        items:
          type: integer
          format: int64
      gift_rank:
        type: array
        items:
          $ref: "#/definitions/RankItem"
      room_ext:
        type: object
        description: 扩展字段集合；创建房间展示资料固定使用 `title`、`cover_url`、`description`。
        additionalProperties:
          type: string
      heat:
        type: integer
        format: int64
      version:
        type: integer
        format: int64
  CreateRoomRequest:
    type: object
    description: 同一个 `meta.actor_user_id` 只能作为 owner 创建一个房间；owner/host 不接受外部字段自报。
    required:
      - meta
      - mode
      - room_name
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      seat_count:
        type: integer
        format: int32
        minimum: 0
        description: 麦位数量；0 或省略时使用后台默认值，正数必须命中后台启用座位数。
      mode:
        type: string
        minLength: 1
        description: 房间模式，不能为空；当前 room-service 保存并通过快照透出。
      room_name:
        type: string
        minLength: 1
        maxLength: 128
        description: 房间展示名称，room-service 写入 `RoomSnapshot.room_ext["title"]`。
      room_avatar:
        type: string
        maxLength: 512
        description: 房间头像；为空时写入默认系统头像 `hyapp://room/default-avatar`。
      room_description:
        type: string
        maxLength: 512
        description: 房间简介；写入 `RoomSnapshot.room_ext["description"]`，不参与房间状态决策。
  CreateRoomResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      room:
        $ref: "#/definitions/RoomSnapshot"
  UpdateRoomProfileRequest:
    type: object
    required:
      - meta
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      room_name:
        type: string
        maxLength: 128
        description: proto3 optional；传入时更新 RoomExt title。
      room_avatar:
        type: string
        maxLength: 512
        description: proto3 optional；传空字符串时恢复系统默认头像。
      room_description:
        type: string
        maxLength: 512
        description: proto3 optional；允许传空字符串清空简介。
      seat_count:
        type: integer
        format: int32
        enum:
          - 10
          - 15
          - 20
          - 25
          - 30
        description: proto3 optional；必须是后台启用座位数，缩容要求被删除麦位空闲且未锁。
  UpdateRoomProfileResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      room:
        $ref: "#/definitions/RoomSnapshot"
  JoinRoomRequest:
    type: object
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      role:
        type: string
  JoinRoomResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      user:
        $ref: "#/definitions/RoomUser"
      room:
        $ref: "#/definitions/RoomSnapshot"
  LeaveRoomRequest:
    type: object
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
  LeaveRoomResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      room:
        $ref: "#/definitions/RoomSnapshot"
  MicUpRequest:
    type: object
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      seat_no:
        type: integer
        format: int32
  MicUpResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      seat_no:
        type: integer
        format: int32
      room:
        $ref: "#/definitions/RoomSnapshot"
      mic_session_id:
        type: string
      publish_deadline_ms:
        type: integer
        format: int64
  MicDownRequest:
    type: object
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      target_user_id:
        type: integer
        format: int64
      reason:
        type: string
        description: 主动下麦可为空；系统自动下麦会使用 publish_timeout 等稳定原因。
  MicDownResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      seat_no:
        type: integer
        format: int32
      room:
        $ref: "#/definitions/RoomSnapshot"
  ConfirmMicPublishingRequest:
    type: object
    required:
      - meta
      - mic_session_id
      - room_version
      - event_time_ms
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      target_user_id:
        type: integer
        format: int64
        description: 为空时默认确认 actor_user_id；RTC webhook 编排可显式指定目标用户。
      mic_session_id:
        type: string
      room_version:
        type: integer
        format: int64
        description: 客户端传 MicUp 返回或快照中的 room_version；旧版本事件不会覆盖新会话。
      event_time_ms:
        type: integer
        format: int64
        description: 客户端 SDK 或 RTC webhook 事件发生时间；只接受当前会话更新的事件。
      source:
        type: string
        description: 例如 client 或 rtc_webhook。
  ConfirmMicPublishingResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      seat_no:
        type: integer
        format: int32
      room:
        $ref: "#/definitions/RoomSnapshot"
  ChangeMicSeatRequest:
    type: object
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      target_user_id:
        type: integer
        format: int64
      seat_no:
        type: integer
        format: int32
  ChangeMicSeatResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      room:
        $ref: "#/definitions/RoomSnapshot"
  SetMicSeatLockRequest:
    type: object
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      seat_no:
        type: integer
        format: int32
      locked:
        type: boolean
  SetMicSeatLockResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      room:
        $ref: "#/definitions/RoomSnapshot"
  SetChatEnabledRequest:
    type: object
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      enabled:
        type: boolean
  SetChatEnabledResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      room:
        $ref: "#/definitions/RoomSnapshot"
  SetRoomAdminRequest:
    type: object
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      target_user_id:
        type: integer
        format: int64
      enabled:
        type: boolean
  SetRoomAdminResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      room:
        $ref: "#/definitions/RoomSnapshot"
  MuteUserRequest:
    type: object
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      target_user_id:
        type: integer
        format: int64
      muted:
        type: boolean
  MuteUserResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      room:
        $ref: "#/definitions/RoomSnapshot"
  KickUserRequest:
    type: object
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      target_user_id:
        type: integer
        format: int64
  KickUserResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      room:
        $ref: "#/definitions/RoomSnapshot"
  UnbanUserRequest:
    type: object
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      target_user_id:
        type: integer
        format: int64
  UnbanUserResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      room:
        $ref: "#/definitions/RoomSnapshot"
  SendGiftRequest:
    type: object
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      target_user_id:
        type: integer
        format: int64
      gift_id:
        type: string
      gift_count:
        type: integer
        format: int32
  SendGiftResponse:
    type: object
    properties:
      result:
        $ref: "#/definitions/CommandResult"
      billing_receipt_id:
        type: string
      room_heat:
        type: integer
        format: int64
      gift_rank:
        type: array
        items:
          $ref: "#/definitions/RankItem"
      room:
        $ref: "#/definitions/RoomSnapshot"
  CheckSpeakPermissionRequest:
    type: object
    properties:
      room_id:
        type: string
      user_id:
        type: integer
        format: int64
  CheckSpeakPermissionResponse:
    type: object
    properties:
      allowed:
        type: boolean
      reason:
        type: string
        enum:
          - room_not_found
          - not_in_room
          - user_banned
          - user_muted
          - chat_disabled
      room_version:
        type: integer
        format: int64
  VerifyRoomPresenceRequest:
    type: object
    properties:
      room_id:
        type: string
      user_id:
        type: integer
        format: int64
      session_id:
        type: string
      request_id:
        type: string
        description: 外部守卫调用的追踪 ID；不作为幂等键。
  VerifyRoomPresenceResponse:
    type: object
    properties:
      present:
        type: boolean
      reason:
        type: string
        enum:
          - room_not_found
          - not_in_room
          - user_banned
      room_version:
        type: integer
        format: int64
  GetCurrentRoomRequest:
    type: object
    required:
      - meta
      - user_id
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      user_id:
        type: integer
        format: int64
        description: 由 gateway 从 token user_id 注入，客户端不能自报。
  GetCurrentRoomResponse:
    type: object
    properties:
      has_current_room:
        type: boolean
      room_id:
        type: string
      room_version:
        type: integer
        format: int64
      role:
        type: string
        description: 用户在房间快照中的角色。
      mic_session_id:
        type: string
        description: 用户当前在麦时返回；客户端确认发流必须带回该 session。
      publish_state:
        type: string
        enum:
          - pending_publish
          - publishing
          - idle
      need_join_im_group:
        type: boolean
        description: true 表示客户端应重新确保加入腾讯云 IM 群。
      need_rtc_token:
        type: boolean
        description: true 表示用户处于 pending_publish/publishing，需要重新获取 RTC token。
      server_time_ms:
        type: integer
        format: int64
  GetRoomSnapshotRequest:
    type: object
    required:
      - meta
      - room_id
      - viewer_user_id
    properties:
      meta:
        $ref: "#/definitions/RequestMeta"
      room_id:
        type: string
        pattern: "^[A-Za-z0-9_-]{1,48}$"
        maxLength: 48
      viewer_user_id:
        type: integer
        format: int64
        description: 由 gateway 从 token user_id 注入，客户端不能自报。
  GetRoomSnapshotResponse:
    type: object
    properties:
      room:
        $ref: "#/definitions/RoomSnapshot"
      server_time_ms:
        type: integer
        format: int64
  RoomSystemMessage:
    type: object
    properties:
      event_id:
        type: string
      room_id:
        type: string
      event_type:
        type: string
        enum:
          - room_created
          - room_user_joined
          - room_user_left
          - room_mic_changed
          - room_mic_seat_locked
          - room_chat_enabled_changed
          - room_admin_changed
          - room_user_muted
          - room_user_kicked
          - room_user_unbanned
          - room_gift_sent
          - room_heat_changed
          - room_rank_changed
      actor_user_id:
        type: integer
        format: int64
      target_user_id:
        type: integer
        format: int64
      seat_no:
        type: integer
        format: int32
      gift_value:
        type: integer
        format: int64
      room_heat:
        type: integer
        format: int64
      room_version:
        type: integer
        format: int64
      text:
        type: string
      attributes:
        type: object
        additionalProperties:
          type: string
    description: room-service 发送到腾讯云 IM 的 `TIMCustomElem.Data` 和 `CloudCustomData` 稳定载荷。
  TencentTIMCustomElem:
    type: object
    properties:
      MsgType:
        type: string
        enum:
          - TIMCustomElem
      MsgContent:
        type: object
        properties:
          Data:
            $ref: "#/definitions/RoomSystemMessage"
          Desc:
            type: string
            description: 与 `RoomSystemMessage.event_type` 一致。
          Ext:
            type: string
            enum:
              - room_system_message
          Sound:
            type: string
    description: 腾讯云 IM 群系统消息元素结构。
  HealthCheckRequest:
    type: object
    properties:
      service:
        type: string
        description: 空字符串或 `room-service`。
  HealthCheckResponse:
    type: object
    properties:
      status:
        type: integer
        format: int32
        enum:
          - 0
          - 1
          - 2
          - 3
        x-enum-names:
          - UNKNOWN
          - SERVING
          - NOT_SERVING
          - SERVICE_UNKNOWN
  GRPCError:
    type: object
    properties:
      grpc_code:
        type: string
        enum:
          - InvalidArgument
          - NotFound
          - FailedPrecondition
          - Unauthenticated
          - PermissionDenied
          - Unavailable
          - AlreadyExists
          - Internal
          - Aborted
      reason:
        type: string
      message:
        type: string
      error_info_domain:
        type: string
        enum:
          - hyapp
