/
msg_richtext.go
194 lines (162 loc) · 4.56 KB
/
msg_richtext.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
package feishu_bot_api
import (
"bytes"
"encoding/json"
"fmt"
)
var _ Message = (*richTextMessage)(nil)
type richTextMessage []*RichTextBuilder
func (m richTextMessage) Apply(body *MessageBody) error {
raw, err := m.marshal()
if err != nil {
return fmt.Errorf("rich text message: %w", err)
}
body.MsgType = "post"
body.Content = &MessageBodyContent{
Post: &raw,
}
return nil
}
func (m richTextMessage) marshal() (json.RawMessage, error) {
var buf bytes.Buffer
buf.Grow(len(m) * 48)
buf.WriteString("{")
nnm := make(richTextMessage, 0, len(m))
for i := range m {
if m[i] == nil {
continue
}
nnm = append(nnm, m[i])
}
commas := len(nnm)
for _, rtb := range nnm {
commas--
if rtb == nil {
continue
}
bs, err := json.Marshal(rtb.body)
if err != nil {
return nil, fmt.Errorf("marshal(%s): %w", rtb.language, err)
}
s := fmt.Sprintf(`"%s":%s`, _quoteEscaper.Replace(string(rtb.language)), bs)
if commas > 0 {
s += ","
}
buf.WriteString(s)
}
buf.WriteString("}")
return buf.Bytes(), nil
}
// --------------------------------------------------------------------------------
type (
RichTextBuilder struct {
language Language
body richTextBody
}
richTextBody struct {
Title string `json:"title,omitempty"`
Content []richTextParagraph `json:"content,omitempty"`
}
richTextParagraph []richTextLabel
richTextLabel struct {
Tag string `json:"tag"`
Text string `json:"text,omitempty"`
// 仅 文本标签(text) 使用;表示是否 unescape 解码。默认值为 false,未用到 unescape 时可以不填
UnEscape *bool `json:"un_escape,omitempty"`
// 仅 超链接标签(a) 使用;链接地址,需要确保链接地址的合法性,否则消息会发送失败
Href string `json:"href,omitempty"`
// 仅 @ 标签(at) 使用
UserID string `json:"user_id,omitempty"`
// 仅 @ 标签(at) 使用
UserName string `json:"user_name,omitempty"`
// 仅 图片标签(img) 使用;图片的唯一标识。可通过 上传图片 接口获取 image_key
// https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/image/create
ImageKey string `json:"image_key,omitempty"`
}
)
func NewRichText(language Language, title string) *RichTextBuilder {
rtb := &RichTextBuilder{
language: language,
body: richTextBody{
Title: title,
Content: make([]richTextParagraph, 0, 1),
},
}
return rtb
}
// Text 文本标签
//
// unEscape 表示是否 unescape 解码,未用到 unescape 时传入 false
func (rtb *RichTextBuilder) Text(text string, unEscape bool) *RichTextBuilder {
lbl := richTextLabel{
Tag: "text",
Text: text,
UnEscape: &unEscape,
}
paragraph := rtb.lastParagraph()
paragraph = append(paragraph, lbl)
rtb.updateLastParagraph(paragraph)
return rtb
}
// Hyperlink 超链接标签
func (rtb *RichTextBuilder) Hyperlink(text, href string) *RichTextBuilder {
lbl := richTextLabel{
Tag: "a",
Text: text,
Href: href,
}
paragraph := rtb.lastParagraph()
paragraph = append(paragraph, lbl)
rtb.updateLastParagraph(paragraph)
return rtb
}
// At @ 标签
//
// id: 用户的 Open ID 或 User ID
//
// @ 单个用户时,id 字段必须是有效值(仅支持 @ 自定义机器人所在群的群成员)
// @ 所有人时,填 all (也可以使用 RichTextBuilder.AtEveryone)
func (rtb *RichTextBuilder) At(id, name string) *RichTextBuilder {
lbl := richTextLabel{
Tag: "at",
UserID: id,
UserName: name,
}
paragraph := rtb.lastParagraph()
paragraph = append(paragraph, lbl)
rtb.updateLastParagraph(paragraph)
return rtb
}
func (rtb *RichTextBuilder) AtEveryone() *RichTextBuilder {
lbl := richTextLabel{
Tag: "at",
UserID: "all",
}
paragraph := rtb.lastParagraph()
paragraph = append(paragraph, lbl)
rtb.updateLastParagraph(paragraph)
return rtb
}
// Image 图片标签
//
// 图片的唯一标识。可通过 上传图片 接口获取
// https://open.feishu.cn/document/uAjLw4CM/ukTMukTMukTM/reference/im-v1/image/create
func (rtb *RichTextBuilder) Image(imgKey string) *RichTextBuilder {
lbl := richTextLabel{
Tag: "img",
ImageKey: imgKey,
}
paragraph := rtb.lastParagraph()
paragraph = append(paragraph, lbl)
rtb.updateLastParagraph(paragraph)
return rtb
}
func (rtb *RichTextBuilder) lastParagraph() richTextParagraph {
if len(rtb.body.Content) == 0 {
rtb.body.Content = append(rtb.body.Content, make(richTextParagraph, 0, 4))
}
return rtb.body.Content[len(rtb.body.Content)-1]
}
func (rtb *RichTextBuilder) updateLastParagraph(paragraph richTextParagraph) {
rtb.body.Content[len(rtb.body.Content)-1] = paragraph
}