gitee.com/larksuite/oapi-sdk-go/v3@v3.0.3/service/im/v1/ext_model.go (about) 1 /* 2 * MIT License 3 * 4 * Copyright (c) 2022 Lark Technologies Pte. Ltd. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 7 * 8 * The above copyright notice and this permission notice, shall be included in all copies or substantial portions of the Software. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 11 */ 12 13 package larkim 14 15 import ( 16 "encoding/json" 17 "fmt" 18 "reflect" 19 "strings" 20 21 larkevent "gitee.com/larksuite/oapi-sdk-go/v3/event" 22 ) 23 24 type ChatI18nNames struct { 25 EnUs string `json:"en_us,omitempty"` 26 ZhCn string `json:"zh_cn,omitempty"` 27 } 28 29 type P1AddBotV1Data struct { 30 Type string `json:"type,omitempty"` // 事件类型 31 AppID string `json:"app_id,omitempty"` // 应用 ID 32 ChatI18nNames *ChatI18nNames `json:"chat_i18n_names,omitempty"` // 群名称国际化字段 33 ChatName string `json:"chat_name,omitempty"` // 群名称 34 ChatOwnerEmployeeID string `json:"chat_owner_employee_id,omitempty"` // 群主的employee_id(即“用户ID”。如果群主是机器人则没有这个字段,仅企业自建应用返回) 35 ChatOwnerName string `json:"chat_owner_name,omitempty"` // 群主姓名 36 ChatOwnerOpenID string `json:"chat_owner_open_id,omitempty"` // 群主的open_id 37 OpenChatID string `json:"open_chat_id,omitempty"` // 群聊的id 38 OperatorEmployeeID string `json:"operator_employee_id,omitempty"` // 操作者的emplolyee_id ,仅企业自建应用返回 39 OperatorName string `json:"operator_name,omitempty"` // 操作者姓名 40 OperatorOpenID string `json:"operator_open_id,omitempty"` //操作者的open_id 41 OwnerIsBot bool `json:"owner_is_bot,omitempty"` //群主是否是机器人 42 TenantKey string `json:"tenant_key,omitempty"` // 企业标识 43 } 44 45 type P1AddBotV1 struct { 46 *larkevent.EventReq 47 *larkevent.EventBase 48 Event *P1AddBotV1Data `json:"event"` 49 } 50 51 func (m *P1AddBotV1) RawReq(req *larkevent.EventReq) { 52 m.EventReq = req 53 } 54 55 type P1RemoveBotV1Data struct { 56 Type string `json:"type,omitempty"` // 事件类型 移除机器人:remove_bot 57 AppID string `json:"app_id,omitempty"` // 应用 ID 58 ChatI18nNames *ChatI18nNames `json:"chat_i18n_names,omitempty"` // 群名称国际化字段 59 ChatName string `json:"chat_name,omitempty"` // 群名称 60 ChatOwnerEmployeeID string `json:"chat_owner_employee_id,omitempty"` // 群主的employee_id(即“用户ID”。如果群主是机器人则没有这个字段,仅企业自建应用返回) 61 ChatOwnerName string `json:"chat_owner_name,omitempty"` // 群主姓名 62 ChatOwnerOpenID string `json:"chat_owner_open_id,omitempty"` // 群主的open_id 63 OpenChatID string `json:"open_chat_id,omitempty"` // 群聊的id 64 OperatorEmployeeID string `json:"operator_employee_id,omitempty"` // 操作者姓名 65 OperatorName string `json:"operator_name,omitempty"` // 操作者的emplolyee_id ,仅企业自建应用返回 66 OperatorOpenID string `json:"operator_open_id,omitempty"` //操作者的open_id 67 OwnerIsBot bool `json:"owner_is_bot,omitempty"` //群主是否是机器人 68 TenantKey string `json:"tenant_key,omitempty"` // 企业标识 69 } 70 71 type P1RemoveBotV1 struct { 72 *larkevent.EventReq 73 *larkevent.EventBase 74 Event *P1RemoveBotV1Data `json:"event"` 75 } 76 77 func (m *P1RemoveBotV1) RawReq(req *larkevent.EventReq) { 78 m.EventReq = req 79 } 80 81 type P1P2PChatCreatedV1 struct { 82 *larkevent.EventReq 83 *larkevent.EventBase 84 Event *P1P2PChatCreatedV1Data `json:"event"` 85 } 86 87 type P1P2PChatCreatedV1Data struct { 88 AppID string `json:"app_id,omitempty"` // APP ID 89 ChatID string `json:"chat_id,omitempty"` //机器人和用户的会话id 90 Operator *P1OperatorV1 `json:"operator,omitempty"` // 会话的发起人。可能是用户,也可能是机器人。 91 TenantKey string `json:"tenant_key,omitempty"` // 企业标识 92 Type string `json:"type,omitempty"` // 事件类型 93 User *P1UserV1 `json:"user,omitempty"` // 会话的用户 94 } 95 96 func (m *P1P2PChatCreatedV1) RawReq(req *larkevent.EventReq) { 97 m.EventReq = req 98 } 99 100 type P1OperatorV1 struct { 101 OpenId string `json:"open_id,omitempty"` // 员工对此应用的唯一标识,同一员工对不同应用的open_id不同 102 UserId string `json:"user_id,omitempty"` // 即“用户ID”,仅企业自建应用会返回 103 } 104 105 type P1UserV1 struct { 106 OpenId string `json:"open_id,omitempty"` // 员工对此应用的唯一标识,同一员工对不同应用的open_id不同 107 UserId string `json:"user_id,omitempty"` // 即“用户ID”,仅企业自建应用会返回 108 Name string `json:"name,omitempty"` // 姓名 109 } 110 111 type P1UserInOutChatV1Data struct { 112 Type string `json:"type,omitempty"` // 事件类型,add_user_to_chat/remove_user_from_chat/revoke_add_user_from_chat 113 AppID string `json:"app_id,omitempty"` // APP ID 114 ChatId string `json:"chat_id,omitempty"` // 群聊的id 115 Operator *P1OperatorV1 `json:"operator,omitempty"` // 用户进出群的操作人。用户主动退群的话,operator 就是user自己 116 TenantKey string `json:"tenant_key,omitempty"` // 企业标识 117 Users []*P1UserV1 `json:"users,omitempty"` 118 } 119 120 type P1UserInOutChatV1 struct { 121 *larkevent.EventReq 122 *larkevent.EventBase 123 Event *P1UserInOutChatV1Data `json:"event"` 124 } 125 126 func (m *P1UserInOutChatV1) RawReq(req *larkevent.EventReq) { 127 m.EventReq = req 128 } 129 130 type P1ChatDisbandV1Data struct { 131 Type string `json:"type,omitempty"` // 事件类型 132 AppID string `json:"app_id,omitempty"` // APP ID 133 ChatId string `json:"chat_id,omitempty"` // 群聊的id 134 Operator *P1OperatorV1 `json:"operator,omitempty"` // 解散群的人 135 TenantKey string `json:"tenant_key,omitempty"` // 企业标识 136 } 137 138 type P1ChatDisbandV1 struct { 139 *larkevent.EventReq 140 *larkevent.EventBase 141 Event *P1ChatDisbandV1Data `json:"event"` 142 } 143 144 func (m *P1ChatDisbandV1) RawReq(req *larkevent.EventReq) { 145 m.EventReq = req 146 } 147 148 type P1GroupSettingChangeV1 struct { 149 OwnerOpenId string `json:"owner_open_id,omitempty"` // 当群主发生变化时会有下面2个字段。若群主未发生变化,则不会有这2个字段。 150 OwnerUserId string `json:"owner_user_id,omitempty"` // 当群主发生变化时会有下面2个字段。若群主未发生变化,则不会有这2个字段。 151 AddMemberPermission string `json:"add_member_permission,omitempty"` // 当“仅群主可添加群成员”配置变化时有下面的字段。 152 MessageNotification bool `json:"message_notification,omitempty"` // 当“消息提醒”配置变化时有下面的字段。 153 154 } 155 type P1GroupSettingUpdatedV1Data struct { 156 Type string `json:"type,omitempty"` // 事件类型 157 AppID string `json:"app_id,omitempty"` // 应用ID 158 ChatId string `json:"chat_id,omitempty"` // 群聊ID 159 Operator *P1OperatorV1 `json:"operator,omitempty"` // 配置变化的操作者 160 TenantKey string `json:"tenant_key,omitempty"` // 企业标识 161 BeforeChange *P1GroupSettingChangeV1 `json:"before_change,omitempty"` 162 AfterChange *P1GroupSettingChangeV1 `json:"after_change,omitempty"` 163 } 164 165 type P1GroupSettingUpdatedV1 struct { 166 *larkevent.EventReq 167 *larkevent.EventBase 168 Event *P1GroupSettingUpdatedV1Data `json:"event"` 169 } 170 171 func (m *P1GroupSettingUpdatedV1) RawReq(req *larkevent.EventReq) { 172 m.EventReq = req 173 } 174 175 // protocol v1的 Message_Read 176 type P1MessageReadV1Data struct { 177 MessageIdList []string `json:"message_id_list,omitempty"` // 已读消息列表 178 AppID string `json:"app_id"` // 应用ID 179 OpenAppID string `json:"open_chat_id"` 180 OpenID string `json:"open_id"` 181 TenantKey string `json:"tenant_key"` // 企业标识 182 Type string `json:"type"` // 事件类型 183 } 184 185 type P1MessageReadV1 struct { 186 *larkevent.EventReq 187 *larkevent.EventBase 188 Event *P1MessageReadV1Data `json:"event"` 189 } 190 191 func (m *P1MessageReadV1) RawReq(req *larkevent.EventReq) { 192 m.EventReq = req 193 } 194 195 // protocol v1的 message 196 type P1MessageReceiveV1 struct { 197 *larkevent.EventBase 198 *larkevent.EventReq 199 Event *P1MessageReceiveV1Data `json:"event"` 200 } 201 202 func (m *P1MessageReceiveV1) RawReq(req *larkevent.EventReq) { 203 m.EventReq = req 204 } 205 206 type P1MessageReceiveV1Data struct { 207 Type string `json:"type,omitempty"` // 事件类型 208 AppID string `json:"app_id,omitempty"` // 应用ID 209 TenantKey string `json:"tenant_key,omitempty"` // 企业标识 210 RootID string `json:"root_id,omitempty"` 211 ParentID string `json:"parent_id,omitempty"` 212 OpenChatID string `json:"open_chat_id,omitempty"` //发消息的open_chat_id 213 ChatType string `json:"chat_type,omitempty"` //私聊private,群聊group 214 MsgType string `json:"msg_type,omitempty"` //消息类型 215 OpenID string `json:"open_id,omitempty"` //发消息的用户open_id 216 EmployeeID string `json:"employee_id,omitempty"` // 即“用户ID”,仅企业自建应用会返回 217 UnionID string `json:"union_id,omitempty"` //发消息的用户union_id 218 OpenMessageID string `json:"open_message_id,omitempty"` //消息id 219 IsMention bool `json:"is_mention,omitempty"` 220 Text string `json:"text,omitempty"` // 消息文本,可能包含被@的人/机器人。 221 TextWithoutAtBot string `json:"text_without_at_bot,omitempty"` //消息内容,会过滤掉at你的机器人的内容,当内容只有at机器人,该字段会被过滤。 222 Title string `json:"title,omitempty"` //消息标题 223 ImageKeys []string `json:"image_keys,omitempty"` //富文本里面的图片的keys 224 ImageKey string `json:"image_key,omitempty"` // image_key,获取图片内容请查/ssl:ttdoc/ukTMukTMukTM/uYzN5QjL2cTO04iN3kDN 225 FileKey string `json:"file_key,omitempty"` 226 } 227 228 /** 229 text类型消息结构化 230 */ 231 type MessageText struct { 232 builder strings.Builder 233 } 234 235 func NewTextMsgBuilder() *MessageText { 236 m := &MessageText{} 237 m.builder.WriteString("{\"text\":\"") 238 return m 239 } 240 241 func (t *MessageText) Text(text string) *MessageText { 242 t.builder.WriteString(text) 243 return t 244 } 245 246 func (t *MessageText) TextLine(text string) *MessageText { 247 t.builder.WriteString(text) 248 t.builder.WriteString("\\n") 249 return t 250 } 251 252 func (t *MessageText) Line() *MessageText { 253 t.builder.WriteString("\\n") 254 return t 255 } 256 257 func (t *MessageText) AtUser(userId, name string) *MessageText { 258 t.builder.WriteString("<at user_id=\\\"") 259 t.builder.WriteString(userId) 260 t.builder.WriteString("\\\">") 261 t.builder.WriteString(name) 262 t.builder.WriteString("</at>") 263 return t 264 return t 265 } 266 267 func (t *MessageText) AtAll() *MessageText { 268 t.builder.WriteString("<at user_id=\\\"all\\\">") 269 t.builder.WriteString("</at>") 270 return t 271 } 272 273 func (t *MessageText) Build() string { 274 t.builder.WriteString("\"}") 275 return t.builder.String() 276 } 277 278 /** 279 post类型消息结构化 280 **/ 281 282 func NewMessagePost() *MessagePost { 283 msg := MessagePost{} 284 return &msg 285 } 286 287 func (m *MessagePost) ZhCn(zhCn *MessagePostContent) *MessagePost { 288 m.ZhCN = zhCn 289 return m 290 } 291 292 func (m *MessagePost) EnUs(enUs *MessagePostContent) *MessagePost { 293 m.EnUS = enUs 294 return m 295 } 296 297 func (m *MessagePost) JaJs(jaJp *MessagePostContent) *MessagePost { 298 m.JaJP = jaJp 299 return m 300 } 301 func (m *MessagePost) Build() (string, error) { 302 return m.String() 303 } 304 305 type MessagePost struct { 306 ZhCN *MessagePostContent `json:"zh_cn,omitempty"` 307 EnUS *MessagePostContent `json:"en_us,omitempty"` 308 JaJP *MessagePostContent `json:"ja_jp,omitempty"` 309 } 310 311 func NewMessagePostContent() *MessagePostContent { 312 m := MessagePostContent{} 313 return &m 314 } 315 316 func (m *MessagePostContent) ContentTitle(title string) *MessagePostContent { 317 m.Title = title 318 return m 319 } 320 321 func (m *MessagePostContent) AppendContent(postElements []MessagePostElement) *MessagePostContent { 322 m.Content = append(m.Content, postElements) 323 return m 324 } 325 func (m *MessagePostContent) Build() *MessagePostContent { 326 return m 327 } 328 329 type MessagePostContent struct { 330 Title string `json:"title,omitempty"` 331 Content [][]MessagePostElement `json:"content,omitempty"` 332 } 333 334 func (m *MessagePost) String() (string, error) { 335 bs, err := json.Marshal(m) 336 if err != nil { 337 return "", err 338 } 339 return string(bs), nil 340 } 341 342 type MessagePostElement interface { 343 Tag() string 344 IsPost() 345 MarshalJSON() ([]byte, error) 346 } 347 348 func messagePostElementJson(e MessagePostElement) ([]byte, error) { 349 data, err := structToMap(e) 350 if err != nil { 351 return nil, err 352 } 353 data["tag"] = e.Tag() 354 return json.Marshal(data) 355 } 356 357 type MessagePostText struct { 358 Text string `json:"text,omitempty"` 359 UnEscape bool `json:"un_escape,omitempty"` 360 } 361 362 func (m *MessagePostText) Tag() string { 363 return "text" 364 } 365 366 func (m *MessagePostText) IsPost() { 367 } 368 369 func (m *MessagePostText) MarshalJSON() ([]byte, error) { 370 return messagePostElementJson(m) 371 } 372 373 type MessagePostA struct { 374 Text string `json:"text,omitempty"` 375 Href string `json:"href,omitempty"` 376 UnEscape bool `json:"un_escape,omitempty"` 377 } 378 379 func (m *MessagePostA) Tag() string { 380 return "a" 381 } 382 383 func (m *MessagePostA) IsPost() { 384 } 385 386 func (m *MessagePostA) MarshalJSON() ([]byte, error) { 387 return messagePostElementJson(m) 388 } 389 390 type MessagePostAt struct { 391 UserId string `json:"user_id,omitempty"` 392 UserName string `json:"user_name,omitempty"` 393 } 394 395 func (m *MessagePostAt) Tag() string { 396 return "at" 397 } 398 399 func (m *MessagePostAt) IsPost() { 400 } 401 402 func (m *MessagePostAt) MarshalJSON() ([]byte, error) { 403 return messagePostElementJson(m) 404 } 405 406 /** 407 image类型消息结构化 408 **/ 409 type MessageImage struct { 410 ImageKey string `json:"image_key,omitempty"` 411 } 412 413 func (m *MessageImage) String() (string, error) { 414 bs, err := json.Marshal(m) 415 if err != nil { 416 return "", err 417 } 418 return string(bs), nil 419 } 420 421 /** 422 文件类型消息结构化 423 **/ 424 type MessageFile struct { 425 FileKey string `json:"file_key,omitempty"` 426 } 427 428 func (m *MessageFile) String() (string, error) { 429 bs, err := json.Marshal(m) 430 if err != nil { 431 return "", err 432 } 433 return string(bs), nil 434 } 435 436 /** 437 audio类型消息结构化 438 **/ 439 type MessageAudio struct { 440 FileKey string `json:"file_key,omitempty"` 441 } 442 443 func (m *MessageAudio) String() (string, error) { 444 bs, err := json.Marshal(m) 445 if err != nil { 446 return "", err 447 } 448 return string(bs), nil 449 } 450 451 /** 452 media类型消息结构化 453 **/ 454 type MessageMedia struct { 455 FileKey string `json:"file_key,omitempty"` 456 ImageKey string `json:"image_key,omitempty"` 457 } 458 459 func (m *MessageMedia) String() (string, error) { 460 bs, err := json.Marshal(m) 461 if err != nil { 462 return "", err 463 } 464 return string(bs), nil 465 } 466 467 /** 468 sticker 类型消息结构化 469 **/ 470 type MessageSticker struct { 471 FileKey string `json:"file_key,omitempty"` 472 } 473 474 func (m *MessageSticker) String() (string, error) { 475 bs, err := json.Marshal(m) 476 if err != nil { 477 return "", err 478 } 479 return string(bs), nil 480 } 481 482 /** 483 share_chat 类型消息结构化 484 **/ 485 486 type MessageShareChat struct { 487 ChatId string `json:"chat_id,omitempty"` 488 } 489 490 func (m *MessageShareChat) String() (string, error) { 491 bs, err := json.Marshal(m) 492 if err != nil { 493 return "", err 494 } 495 return string(bs), nil 496 } 497 498 /** 499 share_user 类型消息结构化 500 **/ 501 502 type MessageShareUser struct { 503 UserId string `json:"user_id,omitempty"` 504 } 505 506 func (m *MessageShareUser) String() (string, error) { 507 bs, err := json.Marshal(m) 508 if err != nil { 509 return "", err 510 } 511 return string(bs), nil 512 } 513 514 type jsonTag struct { 515 name string 516 stringFormat bool 517 ignore bool 518 } 519 520 func parseJSONTag(val string) (jsonTag, error) { 521 if val == "-" { 522 return jsonTag{ignore: true}, nil 523 } 524 var tag jsonTag 525 i := strings.Index(val, ",") 526 if i == -1 || val[:i] == "" { 527 return tag, fmt.Errorf("malformed json tag: %s", val) 528 } 529 tag = jsonTag{ 530 name: val[:i], 531 } 532 switch val[i+1:] { 533 case "omitempty": 534 case "omitempty,string": 535 tag.stringFormat = true 536 default: 537 return tag, fmt.Errorf("malformed json tag: %s", val) 538 } 539 return tag, nil 540 } 541 542 func structToMap(val interface{}) (map[string]interface{}, error) { 543 m := make(map[string]interface{}) 544 s := reflect.Indirect(reflect.ValueOf(val)) 545 st := s.Type() 546 for i := 0; i < s.NumField(); i++ { 547 fieldDesc := st.Field(i) 548 fieldVal := s.Field(i) 549 if fieldDesc.Anonymous { 550 embeddedMap, err := structToMap(fieldVal.Interface()) 551 if err != nil { 552 return nil, err 553 } 554 for k, v := range embeddedMap { 555 m[k] = v 556 } 557 continue 558 } 559 jsonTag := fieldDesc.Tag.Get("json") 560 if jsonTag == "" { 561 continue 562 } 563 tag, err := parseJSONTag(jsonTag) 564 if err != nil { 565 return nil, err 566 } 567 if tag.ignore { 568 continue 569 } 570 if fieldDesc.Type.Kind() == reflect.Ptr && fieldVal.IsNil() { 571 continue 572 } 573 // nil maps are treated as empty maps. 574 if fieldDesc.Type.Kind() == reflect.Map && fieldVal.IsNil() { 575 continue 576 } 577 if fieldDesc.Type.Kind() == reflect.Slice && fieldVal.IsNil() { 578 continue 579 } 580 if tag.stringFormat { 581 m[tag.name] = formatAsString(fieldVal, fieldDesc.Type.Kind()) 582 } else { 583 m[tag.name] = fieldVal.Interface() 584 } 585 } 586 return m, nil 587 } 588 589 func formatAsString(v reflect.Value, kind reflect.Kind) string { 590 if kind == reflect.Ptr && !v.IsNil() { 591 v = v.Elem() 592 } 593 return fmt.Sprintf("%v", v.Interface()) 594 } 595 596 /** 597 消息类型,枚举值 598 */ 599 const ( 600 MsgTypeText string = "text" 601 MsgTypePost string = "post" 602 MsgTypeImage string = "image" 603 MsgTypeFile string = "file" 604 MsgTypeAudio string = "audio" 605 MsgTypeMedia string = "media" 606 MsgTypeSticker string = "sticker" 607 MsgTypeInteractive string = "interactive" 608 MsgTypeShareChat string = "share_chat" 609 MsgTypeShareUser string = "share_user" 610 ) 611 612 const ( 613 ChatTypePrivate string = "private" 614 ChatTypePublic string = "public" 615 )