/**
 *
 * Wechaty Puppet gRPC Protocol Buffers
 *  https://github.com/wechaty/grpc/
 *  Huan LI <zixia@zixia.net>
 *  Apr 2018
 *  License: Apache-2.0
 *
 * Google Protocol Buffers
 *  Style Guide - https://developers.google.com/protocol-buffers/docs/style
 *
 */
syntax = "proto3";
package wechaty;

import "google/api/annotations.proto";
import "protoc-gen-openapiv2/options/annotations.proto";

import "wechaty/puppet/base.proto";
import "wechaty/puppet/call.proto";
import "wechaty/puppet/contact.proto";
import "wechaty/puppet/download-upload.proto";
import "wechaty/puppet/event.proto";
import "wechaty/puppet/friendship.proto";
import "wechaty/puppet/message.proto";
import "wechaty/puppet/room-invitation.proto";
import "wechaty/puppet/room-member.proto";
import "wechaty/puppet/room.proto";
import "wechaty/puppet/tag.proto";
import "wechaty/puppet/conversation.proto";
import "wechaty/puppet/post.proto";
import "wechaty/puppet/moment.proto";
import "wechaty/puppet/verify-code.proto";
import "wechaty/puppet/wecom.proto";

option java_package="io.github.wechaty.grpc";
option go_package="github.com/wechaty/go-grpc/wechaty";

option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_swagger) = {
  info: {
      title: "Wechaty Puppet Service OpenAPI Specification"
      description: "Wechaty is a Conversational RPA SDK for chatbot makers. With only 6 lines of code, you can create a bot on the most popular IMs like WeChat, Whatsapp, WeCom, Gitter, etc.\n\nWechaty Puppet Service is the RESTful API for Wechaty API, which is build on top of the Wechaty Puppet Abstraction and the gRPC proto definition."
      license: {
        name: "Apache-2.0"
        url: "http://www.apache.org/licenses/LICENSE-2.0.html"
      }
      contact: {
          name: "Wechaty"
          url: "https://github.com/wechaty/openapi"
          email: "wechaty@chatie.io"
      }
      version: "0.0.0"  // MUST be 0.0.0 at here: will be synced with the Git Repo when generating.
  }
  // schemes: [HTTP,HTTPS,WS,WSS]
  consumes: "application/json"
  produces: "application/json"
  responses: {
      key: "default"
      value: {
          description: ""
          schema: {
              json_schema: {
                  ref: ".google.rpc.Status"
              }
          }
      }
  }
};

service Puppet {
  /**
   *
   * Base
   *
   */
  rpc Start (puppet.StartRequest)  returns (puppet.StartResponse) {
    option (google.api.http) = {
      put: "/start"
    };
  }
  rpc Stop (puppet.StopRequest)    returns (puppet.StopResponse) {
    option (google.api.http) = {
      put: "/stop"
    };
  }

  rpc Logout (puppet.LogoutRequest)      returns (puppet.LogoutResponse) {
    option (google.api.http) = {
      put: "/logout"
    };
  }
  rpc Ding (puppet.DingRequest)          returns (puppet.DingResponse) {
    option (google.api.http) = {
      post: "/ding"
      body: "*"
    };
  }
  rpc CurrentUser (puppet.CurrentUserRequest) returns (puppet.CurrentUserResponse) {
    option (google.api.http) = {
      get: "/currentUser"
    };
  }
  rpc Version (puppet.VersionRequest)    returns (puppet.VersionResponse) {
    option (google.api.http) = {
      get: "/version"
    };
  }
  rpc EnterVerifyCode (puppet.EnterVerifyCodeRequest)    returns (puppet.EnterVerifyCodeResponse) {
    option (google.api.http) = {
      post: "/enter_verify_code"
    };
  }
  rpc CancelVerifyCode (puppet.CancelVerifyCodeRequest)    returns (puppet.CancelVerifyCodeResponse) {
    option (google.api.http) = {
      post: "/cancel_verify_code"
    };
  }
  rpc RefreshQRCode (puppet.RefreshQRCodeRequest)    returns (puppet.RefreshQRCodeRequest) {
    option (google.api.http) = {
      post: "/refresh_qr_code"
    };
  }

  /**
   *
   * Event - Server Stream
   *
   */
  rpc Event (puppet.EventRequest)  returns (stream puppet.EventResponse) {
    option (google.api.http) = {
      get: "/events"
    };
  }

  rpc DirtyPayload (puppet.DirtyPayloadRequest) returns (puppet.DirtyPayloadResponse) {
    option (google.api.http) = {
      additional_bindings {
        put: "/message/{id}/dirty/{type=PAYLOAD_TYPE_MESSAGE}"
      }
      additional_bindings {
        put: "/contacts/{id}/dirty/{type=PAYLOAD_TYPE_CONTACT}"
      }
      additional_bindings {
        put: "/rooms/{id}/dirty/{type=PAYLOAD_TYPE_ROOM}"
      }
      additional_bindings {
        put: "/rooms/{id}/dirty/members/{type=PAYLOAD_TYPE_ROOM_MEMBER}"
      }
      additional_bindings {
        put: "/friendships/{id}/dirty/{type=PAYLOAD_TYPE_FRIENDSHIP}"
      }
    };
  }

  /**
   *
   * Contact Self
   *
   */
  rpc ContactSelfQRCode (puppet.ContactSelfQRCodeRequest) returns (puppet.ContactSelfQRCodeResponse) {
    option (google.api.http) = {
      get: "/contacts/self/qrcode"
    };

  }
  rpc ContactSelfName (puppet.ContactSelfNameRequest) returns (puppet.ContactSelfNameResponse) {
    option (google.api.http) = {
      put: "/contacts/self/name/{name}"
    };
  }
  rpc ContactSelfRealName (puppet.ContactSelfRealNameRequest) returns (puppet.ContactSelfRealNameResponse) {
    option (google.api.http) = {
      put: "/contacts/self/realName/{real_name}"
    };
  }
  rpc ContactSelfAka (puppet.ContactSelfAkaRequest) returns (puppet.ContactSelfAkaResponse) {
    option (google.api.http) = {
      put: "/contacts/self/aka/{aka}"
    };
  }
  rpc ContactSelfSignature (puppet.ContactSelfSignatureRequest) returns (puppet.ContactSelfSignatureResponse) {
    option (google.api.http) = {
      put: "/contacts/self/signature"
      body: "*"
    };
  }
  rpc ContactSelfRoomAlias (puppet.ContactSelfRoomAliasRequest) returns (puppet.ContactSelfRoomAliasResponse) {
    option (google.api.http) = {
      put: "/contact/room/{room_id}/alias/{alias}"
    };
  }

  /**
   *
   * Contact
   *
   */
  rpc ContactPayload (puppet.ContactPayloadRequest)  returns (puppet.ContactPayloadResponse) {
    option (google.api.http) = {
      get: "/contacts/{id}"
    };

    option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
      summary: 'Get a contact payload';
      operation_id: 'contactPayload';
      tags: "contact";
      responses: {
        key: "200"
          value: {
          description: "Contact payload";
        }
      }
    };
  }

  rpc BatchContactPayload (puppet.BatchContactPayloadRequest) returns (puppet.BatchContactPayloadResponse) {
    option (google.api.http) = {
      post: "/contacts/batch-payload"
      body: "*"
    };
  }

  rpc ContactAlias (puppet.ContactAliasRequest) returns (puppet.ContactAliasResponse) {
    option (google.api.http) = {
      put: "/contacts/{id}/alias"
      body: "*"
    };
  }
  rpc ContactAvatar (puppet.ContactAvatarRequest) returns (puppet.ContactAvatarResponse) {
    option (google.api.http) = {
      get: "/contacts/{id}/avatar" // TODO: Huan(202002) disable the avatar query parameters
      // additional_bindings {
      //   put: "/contacts/{id}/avatar"
      //   body: "*"
      // }
    };
  }
  rpc ContactPhone (puppet.ContactPhoneRequest) returns (puppet.ContactPhoneResponse) {
    option (google.api.http) = {
      put: "/contacts/{contact_id}/phone"
      body: "*"
    };

  }
  rpc ContactCorporationRemark (puppet.ContactCorporationRemarkRequest) returns (puppet.ContactCorporationRemarkResponse) {
    option (google.api.http) = {
      put: "/contacts/{contact_id}/corporation-remark"
      body: "*"
    };
  }
  rpc ContactDescription (puppet.ContactDescriptionRequest) returns (puppet.ContactDescriptionResponse) {
    option (google.api.http) = {
      put: "/contacts/{contact_id}/description"
      body: "*"
    };
  }
  rpc ContactDelete (puppet.ContactDeleteRequest) returns (puppet.ContactDeleteResponse) {
    option (google.api.http) = {
      put: "/contacts/{contact_id}/delete"
      body: "*"
    };
  }

  /**
   * Huan(202002): consider changing response to a stream in the future for better performance
   */
  rpc ContactList (puppet.ContactListRequest) returns (puppet.ContactListResponse) {
    option (google.api.http) = {
      get: "/contacts"
    };
  }

  rpc ContactPayloadModify (puppet.ContactPayloadModifyRequest) returns (puppet.ContactPayloadModifyResponse) {
    option (google.api.http) = {
      put: "/contacts/{id}/payload-modify"
      body: "*"
    };
  }

  /**
   *
   * Friendship
   *
   */
  rpc FriendshipPayload (puppet.FriendshipPayloadRequest)  returns (puppet.FriendshipPayloadResponse) {
    option (google.api.http) = {
      get: "/friendship/{id}"
    };
  }

  rpc FriendshipSearchPhone (puppet.FriendshipSearchPhoneRequest) returns (puppet.FriendshipSearchPhoneResponse) {
    option (google.api.http) = {
      get: "/friendship/search/phone/{phone}"
    };
  }
  /**
   * Huan(202203): https://github.com/wechaty/puppet/issues/181
   * @deprecated use FriendshipSearchHandle instead, will be removed in v3.0
   */
  rpc FriendshipSearchWeixin (puppet.FriendshipSearchHandleRequest) returns (puppet.FriendshipSearchHandleResponse) {}
  rpc FriendshipSearchHandle (puppet.FriendshipSearchHandleRequest) returns (puppet.FriendshipSearchHandleResponse) {
    option (google.api.http) = {
      /**
       * (Huan(20220329): use `weixin` for now, until we upgrade to v2.0
       *  the `wechaty-grpc@1.0.0` will use the latest v1.x automatically when running `npm install`
       *    which will causing a breaking change.
       *  @link https://github.com/wechaty/getting-started/issues/254
       *
       * TODO: rename `weixin` to `handle` in v2.0.0
       */
      get: "/friendship/search/handle/{weixin}"
    };
  }

  rpc FriendshipAdd (puppet.FriendshipAddRequest) returns (puppet.FriendshipAddResponse) {
    option (google.api.http) = {
      put: "/friendship/add/{contact_id}"
      body: "*"
    };
  }
  rpc FriendshipAccept (puppet.FriendshipAcceptRequest) returns (puppet.FriendshipAcceptResponse) {
    option (google.api.http) = {
      put: "/friendship/accept/{id}"
    };
  }

  /**
   *
   * Conversation
   *
   */
  rpc ConversationRead (puppet.ConversationReadRequest) returns (puppet.ConversationReadResponse) {
    option (google.api.http) = {
      put: "/conversation/{conversation_id}/read"
      body: "*"
    };
  }

  /**
   *
   * Message
   *
   */

  rpc MessageFile (puppet.MessageFileRequest) returns (puppet.MessageFileResponse) {
  }

  rpc MessageImage (puppet.MessageImageRequest) returns (puppet.MessageImageResponse) {
  }

  rpc MessageVoice (puppet.MessageVoiceRequest) returns (puppet.MessageVoiceResponse) {
  }

  rpc MessageVoiceText (puppet.MessageVoiceTextRequest) returns (puppet.MessageVoiceTextResponse) {
  }

  rpc MessageSendFile (puppet.MessageSendFileRequest) returns (puppet.MessageSendFileResponse) {
  }

  rpc MessagePayload (puppet.MessagePayloadRequest)  returns (puppet.MessagePayloadResponse) {
    option (google.api.http) = {
      get: "/message/{id}"
    };
  }

  rpc MessageContact (puppet.MessageContactRequest) returns (puppet.MessageContactResponse) {
    option (google.api.http) = {
      get: "/message/{id}/contact"
    };
  }
  rpc MessageMiniProgram (puppet.MessageMiniProgramRequest) returns (puppet.MessageMiniProgramResponse) {
    option (google.api.http) = {
      get: "/message/{id}/mini-program"
    };
  }
  rpc MessageUrl (puppet.MessageUrlRequest) returns (puppet.MessageUrlResponse) {
    option (google.api.http) = {
      get: "/message/{id}/url-link"
    };
  }
  rpc MessageChannel (puppet.MessageChannelRequest) returns (puppet.MessageChannelResponse) {
    option (google.api.http) = {
      get: "/message/{id}/channel"
    };
  }
  rpc MessageChannelCard (puppet.MessageChannelCardRequest) returns (puppet.MessageChannelCardResponse) {
    option (google.api.http) = {
      get: "/message/{id}/channel-card"
    };
  }
  rpc MessageCallRecord (puppet.MessageCallRecordRequest) returns (puppet.MessageCallRecordResponse) {
    option (google.api.http) = {
      get: "/message/{id}/call-record"
    };
  }
  rpc CallInvite (puppet.CallInviteRequest) returns (puppet.CallInviteResponse) {
    option (google.api.http) = {
      post: "/call/invite"
      body: "*"
    };
  }
  rpc CallAdd (puppet.CallAddRequest) returns (puppet.CallAddResponse) {
    option (google.api.http) = {
      post: "/call/{call_id}/add"
      body: "*"
    };
  }
  rpc CallAccept (puppet.CallAcceptRequest) returns (puppet.CallAcceptResponse) {
    option (google.api.http) = {
      post: "/call/{call_id}/accept"
      body: "*"
    };
  }
  rpc CallReject (puppet.CallRejectRequest) returns (puppet.CallRejectResponse) {
    option (google.api.http) = {
      post: "/call/{call_id}/reject"
      body: "*"
    };
  }
  rpc CallCancel (puppet.CallCancelRequest) returns (puppet.CallCancelResponse) {
    option (google.api.http) = {
      post: "/call/{call_id}/cancel"
      body: "*"
    };
  }
  rpc CallHangup (puppet.CallHangupRequest) returns (puppet.CallHangupResponse) {
    option (google.api.http) = {
      post: "/call/{call_id}/hangup"
      body: "*"
    };
  }
  // POST：签发可能在网关侧预分配媒体会话（有副作用），非幂等读取。
  rpc CallMediaEndpoint (puppet.CallMediaEndpointRequest) returns (puppet.CallMediaEndpointResponse) {
    option (google.api.http) = {
      post: "/call/{call_id}/media-endpoint"
      body: "*"
    };
  }
  rpc CallPayload (puppet.CallPayloadRequest) returns (puppet.CallPayloadResponse) {
    option (google.api.http) = {
      get: "/call/{id}"
    };
  }
  rpc MessageChatHistory (puppet.MessageChatHistoryRequest) returns (puppet.MessageChatHistoryResponse) {
    option (google.api.http) = {
      get: "/message/{id}/chat-history"
    };
  }
  rpc MessageRecall (puppet.MessageRecallRequest) returns (puppet.MessageRecallResponse) {
    option (google.api.http) = {
      put: "/message/{id}/recall"
    };
  }
  rpc MessageForward (puppet.MessageForwardRequest) returns (puppet.MessageForwardResponse) {
    option (google.api.http) = {
      post: "/messages/{message_id}/forward/{conversation_id}"
      additional_bindings {
        post: "/conversations/{conversation_id}/forward/{message_id}"
      }
    };
  }
  rpc MessageLocation (puppet.MessageLocationRequest) returns (puppet.MessageLocationResponse) {
    option (google.api.http) = {
      get: "/message/{id}/location"
    };
  }

  rpc MessageSendContact (puppet.MessageSendContactRequest) returns (puppet.MessageSendContactResponse) {
    option (google.api.http) = {
      post: "/conversations/{conversation_id}/contact"
      body: "*"
    };
  }
  rpc MessageSendText (puppet.MessageSendTextRequest) returns (puppet.MessageSendTextResponse) {
    option (google.api.http) = {
      post: "/conversations/{conversation_id}/text"
      body: "*"
    };
  }
  rpc MessageBatchSendText (puppet.MessageBatchSendTextRequest) returns (puppet.MessageBatchSendTextResponse) {
    option (google.api.http) = {
      post: "/conversations:batchSendText"
      body: "*"
    };
  }
  rpc MessageBatchSendFile (puppet.MessageBatchSendFileRequest) returns (puppet.MessageBatchSendFileResponse) {
    option (google.api.http) = {
      post: "/conversations:batchSendFile"
      body: "*"
    };
  }
  rpc MessageBatchForward (puppet.MessageBatchForwardRequest) returns (puppet.MessageBatchForwardResponse) {
    option (google.api.http) = {
      post: "/conversations:batchForward"
      body: "*"
    };
  }
  rpc MessageBatchSendContact (puppet.MessageBatchSendContactRequest) returns (puppet.MessageBatchSendContactResponse) {
    option (google.api.http) = {
      post: "/conversations:batchSendContact"
      body: "*"
    };
  }
  rpc MessageBatchSendUrl (puppet.MessageBatchSendUrlRequest) returns (puppet.MessageBatchSendUrlResponse) {
    option (google.api.http) = {
      post: "/conversations:batchSendUrl"
      body: "*"
    };
  }
  rpc MessageBatchSendMiniProgram (puppet.MessageBatchSendMiniProgramRequest) returns (puppet.MessageBatchSendMiniProgramResponse) {
    option (google.api.http) = {
      post: "/conversations:batchSendMiniProgram"
      body: "*"
    };
  }
  rpc MessageBatchSendLocation (puppet.MessageBatchSendLocationRequest) returns (puppet.MessageBatchSendLocationResponse) {
    option (google.api.http) = {
      post: "/conversations:batchSendLocation"
      body: "*"
    };
  }
  rpc MessageBatchSendChannel (puppet.MessageBatchSendChannelRequest) returns (puppet.MessageBatchSendChannelResponse) {
    option (google.api.http) = {
      post: "/conversations:batchSendChannel"
      body: "*"
    };
  }
  rpc MessageBatchSendChannelCard (puppet.MessageBatchSendChannelCardRequest) returns (puppet.MessageBatchSendChannelCardResponse) {
    option (google.api.http) = {
      post: "/conversations:batchSendChannelCard"
      body: "*"
    };
  }
  rpc MessageSendMiniProgram (puppet.MessageSendMiniProgramRequest) returns (puppet.MessageSendMiniProgramResponse) {
    option (google.api.http) = {
      post: "/conversations/{conversation_id}/mini-program"
      body: "*"
    };
  }
  rpc MessageSendUrl (puppet.MessageSendUrlRequest) returns (puppet.MessageSendUrlResponse) {
    option (google.api.http) = {
      post: "/conversations/{conversation_id}/url-link"
      body: "*"
    };
  }
  rpc MessageSendLocation (puppet.MessageSendLocationRequest) returns (puppet.MessageSendLocationResponse) {
    option (google.api.http) = {
      post: "/conversations/{conversation_id}/location"
      body: "*"
    };
  }
  rpc MessageSendChannel (puppet.MessageSendChannelRequest) returns (puppet.MessageSendChannelResponse) {
    option (google.api.http) = {
      post: "/conversations/{conversation_id}/channel"
      body: "*"
    };
  }
  rpc MessageSendChannelCard (puppet.MessageSendChannelCardRequest) returns (puppet.MessageSendChannelCardResponse) {
    option (google.api.http) = {
      post: "/conversations/{conversation_id}/channel-card"
      body: "*"
    };
  }
  rpc MessageSendPost (puppet.MessageSendPostRequest) returns (puppet.MessageSendPostResponse) {
    option (google.api.http) = {
      post: "/conversations/{conversation_id}/post"
      body: "*"
    };
  }
  rpc MessagePreview (puppet.MessagePreviewRequest) returns (puppet.MessagePreviewResponse) {
    option (google.api.http) = {
      get: "/message/{id}/preview"
    };
  }

  rpc GetMessageBroadcastTarget (puppet.GetMessageBroadcastTargetRequest) returns (puppet.GetMessageBroadcastTargetResponse) {
    option (google.api.http) = {
      get: "/message/broadcast/target"
    };
  }

  rpc CreateMessageBroadcast (puppet.CreateMessageBroadcastRequest) returns (puppet.CreateMessageBroadcastResponse) {
    option (google.api.http) = {
      post: "/message/broadcast/create"
      body: "*"
    };
  }

  rpc GetMessageBroadcastStatus (puppet.GetMessageBroadcastStatusRequest) returns (puppet.GetMessageBroadcastStatusResponse) {
    option (google.api.http) = {
      get: "/message/broadcast/{id}"
    };
  }


  /**
   *
   * Room
   *
   */
  rpc RoomPayload (puppet.RoomPayloadRequest) returns (puppet.RoomPayloadResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}"
    };
  }

  rpc BatchRoomPayload (puppet.BatchRoomPayloadRequest) returns (puppet.BatchRoomPayloadResponse) {
    option (google.api.http) = {
      post: "/rooms/batch-payload"
      body: "*"
    };
  }

  rpc RoomList (puppet.RoomListRequest) returns (puppet.RoomListResponse) {
    option (google.api.http) = {
      get: "/rooms"
    };
  }

  rpc RoomAdd (puppet.RoomAddRequest) returns (puppet.RoomAddResponse) {
    option (google.api.http) = {
      put: "/rooms/{id}/add/{contact_id}"
    };
  }
  rpc RoomAvatar (puppet.RoomAvatarRequest) returns (puppet.RoomAvatarResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}/avatar"
    };
  }
  rpc RoomCreate (puppet.RoomCreateRequest) returns (puppet.RoomCreateResponse) {
    option (google.api.http) = {
      post: "/rooms"
      body: "*"
    };
  }
  rpc RoomDel (puppet.RoomDelRequest) returns (puppet.RoomDelResponse) {
    option (google.api.http) = {
      delete: "/rooms/{id}/member/{contact_id}"
    };
  }
  rpc RoomQuit (puppet.RoomQuitRequest) returns (puppet.RoomQuitResponse) {
    option (google.api.http) = {
      delete: "/rooms/{id}"
    };
  }

  rpc RoomTopic (puppet.RoomTopicRequest) returns (puppet.RoomTopicResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}/topic"
    };
  }

  rpc RoomRemark (puppet.RoomRemarkRequest) returns (puppet.RoomRemarkResponse) {
    option (google.api.http) = {
      put: "/rooms/{id}/remark"
    };
  }

  rpc RoomQRCode (puppet.RoomQRCodeRequest) returns (puppet.RoomQRCodeResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}/qrcode"
    };
  }
  rpc RoomParseDynamicQRCode (puppet.RoomParseDynamicQRCodeRequest) returns (puppet.RoomParseDynamicQRCodeResponse) {
    option (google.api.http) = {
      get: "/rooms/{url}/parse-dynamic-qrcode"
    };
  }

  rpc RoomAnnounce (puppet.RoomAnnounceRequest) returns (puppet.RoomAnnounceResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}/announcement"  // TODO: disable other get parameters
      additional_bindings {
        put: "/rooms/{id}/announcement"
        body: "*"
      }
    };
  }

  rpc RoomOwnerTransfer (puppet.RoomOwnerTransferRequest) returns (puppet.RoomOwnerTransferResponse) {
    option (google.api.http) = {
      post: "/rooms/{id}/transfer/{contact_id}"
    };
  }

  rpc RoomPermission (puppet.RoomPermissionRequest) returns (puppet.RoomPermissionResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}/permission"
    };
  }

  rpc RoomAddAdmins (puppet.RoomAdminsRequest) returns (puppet.RoomAdminsResponse) {
    option (google.api.http) = {
      put: "/rooms/{id}/add/admins/{contact_ids}"
    };
  }

  rpc RoomDelAdmins (puppet.RoomAdminsRequest) returns (puppet.RoomAdminsResponse) {
    option (google.api.http) = {
      delete: "/rooms/{id}/del/admins/{contact_ids}"
    };
  }

  rpc RoomDismiss (puppet.RoomDismissRequest) returns (puppet.RoomDismissResponse) {
    option (google.api.http) = {
      delete: "/rooms/{id}"
    };
  }

  rpc RoomAddV2 (puppet.RoomAddV2Request) returns (puppet.RoomAddV2Response) {
    option (google.api.http) = {
      put: "/rooms/{id}/addV2"
    };
  }

  rpc RoomDelV2 (puppet.RoomDelV2Request) returns (puppet.RoomDelV2Response) {
    option (google.api.http) = {
      delete: "/rooms/{id}/delV2"
    };
  }

  /**
   *
   * Room Member
   *
   */
  rpc RoomMemberPayload (puppet.RoomMemberPayloadRequest) returns (puppet.RoomMemberPayloadResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}/members/{member_id}"
    };
  }

  rpc RoomMemberList (puppet.RoomMemberListRequest) returns (puppet.RoomMemberListResponse) {
    option (google.api.http) = {
      get: "/rooms/{id}/members"
    };
  }

  rpc BatchRoomMemberPayload (puppet.BatchRoomMemberPayloadRequest) returns (puppet.BatchRoomMemberPayloadResponse) {
    option (google.api.http) = {
      post: "/rooms/{id}/members/batch-payload"
      body: "*"
    };
  }

  /**
   *
   * Room Invitation
   *
   */
  rpc RoomInvitationPayload (puppet.RoomInvitationPayloadRequest)  returns (puppet.RoomInvitationPayloadResponse) {
    option (google.api.http) = {
      get: "/room-invitations/{id}"
    };
  }
  rpc RoomInvitationAccept (puppet.RoomInvitationAcceptRequest) returns (puppet.RoomInvitationAcceptResponse) {
    option (google.api.http) = {
      put: "/room-invitations/{id}/accept"
    };
  }
  rpc RoomInvitationAcceptByQRCode (puppet.RoomInvitationAcceptByQRCodeRequest) returns (puppet.RoomInvitationAcceptByQRCodeResponse) {
    option (google.api.http) = {
      put: "/room-invitations/{qrcode}/accept-by-qrcode"
    };
  }

  /**
   *
   * Tag
   *
   */

  rpc TagContactTagAdd (puppet.TagContactTagAddRequest) returns (puppet.TagContactTagAddResponse) {
    option (google.api.http) = {
      post: "/tag/addContactTag"
      body: "*"
    };
  }

  rpc TagContactTagRemove (puppet.TagContactTagRemoveRequest) returns (puppet.TagContactTagRemoveResponse) {
    option (google.api.http) = {
      post: "/tag/removeContactTag"
      body: "*"
    };
  }

  rpc TagGroupAdd (puppet.TagGroupAddRequest) returns (puppet.TagGroupAddResponse) {
    option (google.api.http) = {
      post: "/tagGroup/add"
      body: "*"
    };
  }

  rpc TagGroupDelete (puppet.TagGroupDeleteRequest) returns (puppet.TagGroupDeleteResponse) {
    option (google.api.http) = {
      post: "/tagGroup/delete"
      body: "*"
    };
  }

  rpc TagGroupPayload (puppet.TagGroupPayloadRequest) returns (puppet.TagGroupPayloadResponse) {
    option (google.api.http) = {
      post: "/tagGroup/payload"
      body: "*"
    };
  }

  rpc TagTagAdd (puppet.TagTagAddRequest) returns (puppet.TagTagAddResponse) {
    option (google.api.http) = {
      post: "/tag/add"
      body: "*"
    };
  }

  rpc TagTagDelete (puppet.TagTagDeleteRequest) returns (puppet.TagTagDeleteResponse) {
    option (google.api.http) = {
      post: "/tag/delete"
      body: "*"
    };
  }

  rpc TagTagModify (puppet.TagTagModifyRequest) returns (puppet.TagTagModifyResponse) {
    option (google.api.http) = {
      post: "/tag/modify"
      body: "*"
    };
  }

  rpc TagPayload (puppet.TagPayloadRequest) returns (puppet.TagPayloadResponse) {
    option (google.api.http) = {
      post: "/tag/payload"
      body: "*"
    };
  }

  rpc TagGroupList (puppet.TagGroupListRequest) returns (puppet.TagGroupListResponse) {
    option (google.api.http) = {
      get: "/tagGroup/list"
    };
  }

  rpc TagGroupTagList (puppet.TagGroupTagListRequest) returns (puppet.TagGroupTagListResponse) {
    option (google.api.http) = {
      get: "/tag/groups/{tag_group_id}/tags"
    };
  }

  rpc TagTagList (puppet.TagTagListRequest) returns (puppet.TagTagListResponse) {
    option (google.api.http) = {
      get: "/tag/list"
    };
  }

  rpc TagContactTagList (puppet.TagContactTagListRequest) returns (puppet.TagContactTagListResponse) {
    option (google.api.http) = {
      get: "/contacts/{contact_id}/tag/tags"
    };
  }

  rpc TagTagContactList (puppet.TagTagContactListRequest) returns (puppet.TagTagContactListResponse) {
    option (google.api.http) = {
      get: "/tag/{tag_id}/contacts"
    };
  }

  /**
   *
   * Moment & Post
   *
   */

  rpc momentPublish (puppet.MomentPublishRequest) returns (puppet.MomentPublishResponse) {
    option (google.api.http) = {
      post: "/moment/publish"
      body: "*"
    };
  }

  rpc MomentUnpublish (puppet.MomentUnpublishRequest) returns (puppet.MomentUnpublishResponse) {
    option (google.api.http) = {
      delete: "/moment/{moment_id}"
    };
  }


  rpc postTap (puppet.PostTapRequest) returns (puppet.PostTapResponse) {
    option (google.api.http) = {
      post: "/post/like"
      body: "*"
    };
  }

  rpc momentSignature (puppet.MomentSignatureRequest) returns (puppet.MomentSignatureResponse) {
    option (google.api.http) = {
      post: "/moment/signature"
      body: "*"
    };
  }

  rpc momentCoverage (puppet.MomentCoverageRequest) returns (puppet.MomentCoverageResponse) {
    option (google.api.http) = {
      post: "/moment/coverage"
      body: "*"
    };
  }

  rpc postPayload (puppet.PostPayloadRequest) returns (puppet.PostPayloadResponse) {
    option (google.api.http) = {
      post: "/post/payload"
      body: "*"
    };
  }

  rpc postPayloadSayable (puppet.PostPayloadSayableRequest) returns (puppet.PostPayloadSayableResponse) {
    option (google.api.http) = {
      post: "/post/sayable"
      body: "*"
    };
  }


  /**
   *
   * Moment & Post With Correct Name
   *
   */

  rpc MomentVisibleList (puppet.MomentVisibleListRequest) returns (puppet.MomentVisibleListResponse) {
    option (google.api.http) = {
      get: "/moment/visibleList"
    };
  }

  /**
   * Wecom
   */

  rpc GetContactExternalUserId (puppet.GetContactExternalUserIdRequest) returns (puppet.GetContactExternalUserIdResponse) {
    option (google.api.http) = {
      post: "/contact/externalUserId"
      body: "*"
    };
  }

  rpc GetRoomAntiSpamStrategyList (puppet.GetRoomAntiSpamStrategyListRequest) returns (puppet.GetRoomAntiSpamStrategyListResponse) {
    option (google.api.http) = {
      get: "/wecom/roomAntiSpamStrategyList"
    };
  }

  rpc GetRoomAntiSpamStrategyEffectRoomList (puppet.GetRoomAntiSpamStrategyEffectRoomListRequest) returns (puppet.GetRoomAntiSpamStrategyEffectRoomListResponse) {
    option (google.api.http) = {
      get: "/wecom/roomAntiSpamStrategy/{strategy_id}/rooms"
    };
  }

  rpc ApplyRoomAntiSpamStrategy (puppet.ApplyRoomAntiSpamStrategyRequest) returns (puppet.ApplyRoomAntiSpamStrategyResponse) {
    option (google.api.http) = {
      post: "/wecom/roomAntiSpamStrategy/apply",
      body: "*"
    };
  }

  rpc GetCorpMessageInterceptionStrategies (puppet.GetCorpMessageInterceptionStrategiesRequest) returns (puppet.GetCorpMessageInterceptionStrategiesResponse) {
    option (google.api.http) = {
      get: "/wecom/corpMessageInterceptionStrategyList"
    };
  }

  /**
   * File/Blob download & upload
   */
  rpc Download (puppet.DownloadRequest) returns (stream puppet.DownloadResponse) {
    option (google.api.http) = {
      get: "/download/{id}"
    };
  }
  rpc Upload (stream puppet.UploadRequest) returns (puppet.UploadResponse) {
    option (google.api.http) = {
      post: "/upload"
      body: "*"
    };
  }

}
