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  )