syntax = "proto3";

message Msg {
  Header header = 1;
  Body body = 2;
  optional Extension extension = 99;
}

enum MsgType {
  HELLO = 0; //握手
  HEART_BEAT = 1; //心跳
  CHAT = 2; //单聊
  GROUP_CHAT = 3; //群聊
  CHAT_READ = 4; // 单聊已读
  GROUP_CHAT_READ = 5; // 群聊已读
  DELIVERED = 6; //已发送
  RESERVE = 7; //原type废弃了,这个坑位保留
  STATUS_REQ = 8; //连接状态查询请求
  STATUS_RES = 9; //连接状态响应
  STATUS_SYNC = 10; //端侧的连接状态同步给云端（比如在线，离开）
  AT = 11; //@消息
  REVOKE = 12; //撤回消息
  DELETE = 13; //删除消息

  SYS_GROUP_CREATE = 21; //系统消息之创建群组
  SYS_GROUP_ADD_MEMBER = 22; //系统消息之添加群组成员
  SYS_GROUP_DEL_MEMBER = 23; //系统消息之移除群组成员
  SYS_GROUP_SET_ADMIN = 24; //设置为管理员角色
  SYS_GROUP_CANCEL_ADMIN = 25; //取消管理员角色
  SYS_GROUP_SET_ALL_MUTED = 26; //设置全员禁言
  SYS_GROUP_CANCEL_ALL_MUTED = 27; //取消全员禁言
  SYS_GROUP_SET_JOIN_APPROVAL = 28; //开启入群验证
  SYS_GROUP_CANCEL_JOIN_APPROVAL = 29; //关闭入群验证
  SYS_GROUP_SET_HISTORY_BROWSE = 30; // 开启新成员浏览历史记录
  SYS_GROUP_CANCEL_HISTORY_BROWSE = 31; // 开启新成员浏览历史记录
  SYS_GROUP_OWNER_TRANSFER = 32; // 群主转移
  SYS_GROUP_UPDATE_MEMBER_MUTED = 33; //设置某个成员禁言
  SYS_GROUP_LEAVE = 34; //离开群组
  SYS_GROUP_DROP = 35; //解散群组
  SYS_GROUP_UPDATE_ANNOUNCEMENT = 36; //更新了群公告
  SYS_GROUP_UPDATE_NAME = 37; //更新了群名称
  SYS_GROUP_UPDATE_AVATAR = 38; //更新了群头像

  CLOSE_BY_READ_IDLE = 50; //超时关闭
  CLOSE_BY_ERROR_MAGIC = 51; //magic不对关闭

  DEFAULT = 99;
}

message Header {
  int32 magic = 1;
  int32 version = 2;
  MsgType msgType = 3;
  bool isExtension = 4;
}

/**
每种消息需要携带的字段规定：M必须，o非必须，-不带
  NO      filed      HELLO  HEART_BEAT  CHAT(up)  CHAT(down)  GROUP_CHAT(up)  GROUP_CHAT(down)  CHAT_READ  GROUP_CHAT_READ  DELIVERED  CLOSE_BY_READ_IDLE  CLOSE_BY_ERROR_MAGIC
+---+--------------+------+-----------+---------|-----------+---------------+-----------------+----------+----------------+----------+-------------------+---------------------+
| 1 | fromId       |   -  |    -      |    M    |     M     |       M       |        M        |     M    |        M       |    -     |       todo        |         todo        |
| 2 | fromClient   |   -  |    -      |    M    |     M     |       M       |        M        |     M    |        M       |    -     |       todo        |         todo        |
| 3 | toId         |   -  |    -      |    M    |     M     |       -       |        M        |     M    |        O       |    -     |       todo        |         todo        |
| 4 | toClient     |   -  |    -      |    -    |     M     |       -       |        M        |     O    |        O       |    -     |       todo        |         todo        |
| 5 | groupId      |   -  |    -      |    -    |     -     |       M       |        M        |     -    |        M       |    -     |       todo        |         todo        |
| 6 | msgId        |   -  |    -      |    -    |     M     |       -       |        M        |     O    |        O       |    M     |       todo        |         todo        |
| 7 | content      |   -  |    -      |    M    |     M     |       M       |        M        |     M    |        M       |    -     |       todo        |         todo        |
| 8 | contentType  |   -  |    -      |    M    |     M     |       M       |        M        |     -    |        -       |    -     |       todo        |         todo        |
| 9 | seq          |   -  |    -      |    M    |     M     |       M       |        M        |     O    |        O       |    M     |       todo        |         todo        |
|10 | sessionId    |   -  |    -      |    M    |     M     |       M       |        M        |     M    |        M       |    M     |       todo        |         todo        |
+---+--------------+------+-----------+---------|-----------+---------------+-----------------+----------+----------------+----------+-------------------+---------------------+
  NO      filed      STATUS_REQ   STATUS_RES   STATUS_SYNC  SYS_GROUP_XXX   AT(up)   AT(down)    REVOKE     DELETE
+---+--------------+------------+------------+-------------+------------+---------+---------+-----------+-----------+
| 1 | fromId       |      M     |      M     |      M      |      -     |    M    |    M    |     M     |     M     |
| 2 | fromClient   |      M     |      M     |      M      |      -     |    M    |    M    |     -     |     -     |
| 3 | toId         |      -     |      -     |      -      |      -     |    -    |    M    |     o     |     M     |
| 4 | toClient     |      -     |      -     |      -      |      -     |    -    |    M    |     -     |     M     |
| 5 | groupId      |      -     |      -     |      -      |      M     |    M    |    M    |     o     |     -     |
| 6 | msgId        |      -     |      -     |      -      |      M     |    -    |    M    |     M     |     M     |
| 7 | content      |      M     |      M     |      M      |      M     |    M    |    M    |     M     |     -     |
| 8 | contentType  |      -     |      -     |      -      |      -     |    -    |    -    |     -     |     -     |
| 9 | seq          |      -     |      -     |      -      |      -     |    M    |    M    |     -     |     -     |
|10 | sessionId    |      -     |      -     |      -      |      M     |    M    |    M    |     M     |     M     |
+---+--------------+------------+------------+-------------+------------+---------+---------+-----------+-----------+
 */
message Body {
  optional string fromId = 1;
  optional string fromClient = 2;
  optional string toId = 3;
  optional string toClient = 4;
  optional string groupId = 5;
  optional int64 msgId = 6; //服务端生成的消息ID，会话内单调递增，可用于消息排序
  optional string content = 7;
  optional int32 contentType = 8;
  optional string seq = 9; //客户端生成的序列号ID，会话内唯一，可用于消息去重
  optional string sessionId = 10; //MsgType=SENDER_SYNC需带上该字段，因为此时fromId和toId都是发送端的账号，无法识别是哪个session
}

message Extension {
  map<string, string> extensionMap = 1;
}
