@@ -4,12 +4,12 @@ import (
44 "bytes"
55 "errors"
66 "regexp"
7- "strings"
87
98 "github.com/requilence/integram"
109)
1110
1211var m = integram.HTMLRichText {}
12+ var markdownRichText = integram.MarkdownRichText {}
1313
1414type Config struct {
1515 integram.BotConfig
@@ -20,16 +20,17 @@ type webhook struct {
2020 Mrkdwn bool
2121 Channel string
2222 Attachments []struct {
23- Pretext string `json:"pretext"`
24- Fallback string `json:"fallback"`
25- AuthorName string `json:"author_name"`
26- AuthorLink string `json:"author_link"`
27- Title string `json:"title"`
28- TitleLink string `json:"title_link"`
29- Text string `json:"text"`
30- ImageURL string `json:"image_url"`
31- ThumbURL string `json:"thumb_url"`
32- Ts int `json:"ts"`
23+ Pretext string `json:"pretext"`
24+ Fallback string `json:"fallback"`
25+ AuthorName string `json:"author_name"`
26+ AuthorLink string `json:"author_link"`
27+ Title string `json:"title"`
28+ TitleLink string `json:"title_link"`
29+ Text string `json:"text"`
30+ MrkdwnIn []string `json:"mrkdwn_in"`
31+ ImageURL string `json:"image_url"`
32+ ThumbURL string `json:"thumb_url"`
33+ Ts int `json:"ts"`
3334 } `json:"attachments"`
3435}
3536
@@ -63,48 +64,62 @@ func update(c *integram.Context) error {
6364 return nil
6465}
6566
66- func escapeTags (text string ) string {
67- return strings .Replace (strings .Replace (text , "<" , "<" , - 1 ), ">" , ">" , - 1 )
68- }
69-
70- func convertToMarkdown (text string ) string {
71- // Escape URL links if outside code blocks.
72- // Message format is documented at https://api.slack.com/docs/message-formatting)
73- // References to a Slack channel (@), user (#) or variable (!) are kept as-is
74- linkOrCodeBlockRegexp := regexp .MustCompile ("```.+```|`[^`\n ]+`|<([^@#!\n ][^|>\n ]*)(|[^>\n ]+)?>" )
75-
76- submatches := linkOrCodeBlockRegexp .FindAllStringSubmatchIndex (text , - 1 )
67+ func convertLinks (text string , regex * regexp.Regexp , encodeEntities func (string ) string , linkFormat func (string , string ) string ) string {
68+ if encodeEntities == nil {
69+ encodeEntities = func (text string ) string {
70+ return text
71+ }
72+ }
73+ submatches := regex .FindAllStringSubmatchIndex (text , - 1 )
7774 if submatches == nil {
78- return escapeTags (text )
75+ return encodeEntities (text )
7976 }
8077
8178 convertedBuffer := new (bytes.Buffer )
8279 convertedBuffer .Grow (len (text ))
8380 currentPosition := 0
8481 for _ , submatch := range submatches {
8582 if submatch [0 ] > 0 {
86- convertedBuffer .WriteString (escapeTags (text [currentPosition :submatch [0 ]]))
83+ convertedBuffer .WriteString (encodeEntities (text [currentPosition :submatch [0 ]]))
8784 }
8885 if submatch [2 ] < 0 {
8986 // Code block, copy as-is
90- convertedBuffer .WriteString (text [submatch [0 ]:submatch [1 ]])
87+ convertedBuffer .WriteString (encodeEntities ( text [submatch [0 ]:submatch [1 ]]) )
9188 } else {
92- // URL link, convert to Markdown
89+ // URL link, convert
9390 url := text [submatch [2 ]:submatch [3 ]]
9491 displayText := url
9592 if submatch [4 ] > 0 && submatch [4 ] != submatch [5 ] {
9693 displayText = text [submatch [4 ] + 1 :submatch [5 ]]
9794 }
98- convertedBuffer .WriteString ("[" + displayText + "](" + url + ")" )
95+ convertedBuffer .WriteString (linkFormat ( displayText , url ) )
9996 }
10097 currentPosition = submatch [1 ]
10198 }
10299 if currentPosition < len (text ) {
103- convertedBuffer .WriteString (escapeTags (text [currentPosition :]))
100+ convertedBuffer .WriteString (encodeEntities (text [currentPosition :]))
104101 }
105102 return convertedBuffer .String ()
106103}
107104
105+ func convertLinksToMarkdown (text string ) string {
106+ // Escape URL links if outside code blocks.
107+ // Message format is documented at https://api.slack.com/docs/message-formatting)
108+ // References to a Slack channel (@), user (#) or variable (!) are kept as-is
109+ linkOrCodeBlockRegexp := regexp .MustCompile ("```.+```|`[^`\n ]+`|<([^@#! \n ][^|> \n ]*)(|[^>\n ]+)?>" )
110+ return convertLinks (text , linkOrCodeBlockRegexp , nil , markdownRichText .URL );
111+ }
112+
113+ func convertLinksToHtml (text string ) string {
114+ linkOrCodeBlockRegexp := regexp .MustCompile ("<code>.*</code>|<pre>.*</pre>|<([^@#! \n ][^|> \n ]*)(|[^>\n ]+)?>" )
115+ return convertLinks (text , linkOrCodeBlockRegexp , nil , m .URL );
116+ }
117+
118+ func convertPlainWithLinksToHTML (text string ) string {
119+ linkRegexp := regexp .MustCompile ("<([^@#! \n ][^|> \n ]*)(|[^>\n ]+)?>" )
120+ return convertLinks (text , linkRegexp , m .EncodeEntities , m .URL );
121+ }
122+
108123func webhookHandler (c * integram.Context , wc * integram.WebhookContext ) (err error ) {
109124
110125 wh := webhook {Mrkdwn : true }
@@ -114,10 +129,6 @@ func webhookHandler(c *integram.Context, wc *integram.WebhookContext) (err error
114129 return
115130 }
116131
117- if wh .Mrkdwn {
118- wh .Text = convertToMarkdown (wh .Text );
119- }
120-
121132 if len (wh .Attachments ) > 0 {
122133 if wh .Text != "" {
123134 wh .Text += "\n "
@@ -130,6 +141,7 @@ func webhookHandler(c *integram.Context, wc *integram.WebhookContext) (err error
130141 }
131142
132143 haveAttachmentWithText := false
144+ haveMrkdwnAttachment := false
133145 for i , attachment := range wh .Attachments {
134146 if i > 0 {
135147 text += "\n "
@@ -148,19 +160,32 @@ func webhookHandler(c *integram.Context, wc *integram.WebhookContext) (err error
148160 }
149161
150162 haveAttachmentWithText = true
163+ for _ , field := range attachment .MrkdwnIn {
164+ if field == "pretext" {
165+ haveMrkdwnAttachment = true
166+ }
167+ }
151168
152169 text += attachment .Pretext
153170 }
154171
155172 if haveAttachmentWithText {
156- return c .NewMessage ().SetText (convertToMarkdown (text )).EnableMarkdown ().Send ()
173+ m := c .NewMessage ().EnableAntiFlood ()
174+ if haveMrkdwnAttachment {
175+ m .SetText (convertLinksToMarkdown (text )).EnableMarkdown ()
176+ } else {
177+ m .SetText (convertLinksToHtml (text )).EnableHTML ()
178+ }
179+ return m .Send ()
157180 }
158181 }
159182
160183 if wh .Text != "" {
161- m := c .NewMessage ().SetText ( wh . Text + " " + wh . Channel )
184+ m := c .NewMessage ().EnableAntiFlood ( )
162185 if wh .Mrkdwn {
163- m .EnableMarkdown ()
186+ m .SetText (convertLinksToMarkdown (wh .Text + " " + wh .Channel )).EnableMarkdown ()
187+ } else {
188+ m .SetText (convertPlainWithLinksToHTML (wh .Text + " " + wh .Channel )).EnableHTML ()
164189 }
165190 return m .Send ()
166191 }
0 commit comments