Skip to content

Commit 90f4d7b

Browse files
committed
WIP
1 parent ad424a6 commit 90f4d7b

14 files changed

+2294
-3
lines changed

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ require (
99
github.com/slack-go/slack v0.6.3
1010
github.com/urfave/cli/v2 v2.1.1
1111
gopkg.in/yaml.v2 v2.2.8
12+
mvdan.cc/xurls/v2 v2.5.0
1213
)
1314

1415
require (

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,5 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
5454
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
5555
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
5656
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
57+
mvdan.cc/xurls/v2 v2.5.0 h1:lyBNOm8Wo71UknhUs4QTFUNNMyxy2JEIaKKo0RWOh+8=
58+
mvdan.cc/xurls/v2 v2.5.0/go.mod h1:yQgaGQ1rFtJUzkmKiHYSSfuQxqfYmd//X6PxvholpeE=

isolated/slack_test.go

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package isolated
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"testing"
7+
8+
"github.com/slack-go/slack"
9+
)
10+
11+
func TestTest(t *testing.T) {
12+
obj := slack.NewTextBlockObject("plain_text", "here is a url: golang.org", false, false)
13+
block := slack.NewSectionBlock(obj, nil, nil)
14+
msg := slack.NewBlockMessage(block)
15+
16+
b, err := json.MarshalIndent(msg, "", " ")
17+
if err != nil {
18+
t.Fatal(err)
19+
}
20+
21+
fmt.Println(string(b))
22+
23+
}

slack.go

+90-3
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,20 @@ import (
44
"context"
55
"errors"
66
"fmt"
7+
"net/url"
78
"strings"
89
"time"
910

11+
"github.com/PagerDuty/go-pagerduty"
1012
"github.com/google/go-cmp/cmp"
1113
"github.com/google/go-cmp/cmp/cmpopts"
1214
"github.com/matryer/try"
13-
14-
"github.com/PagerDuty/go-pagerduty"
15-
1615
"github.com/slack-go/slack"
16+
"mvdan.cc/xurls/v2"
1717
)
1818

19+
var rxRelaxed = xurls.Relaxed()
20+
1921
type slackUsers []slackUser
2022

2123
func (users slackUsers) findByPDUser(pdUser pagerduty.User) *slackUser {
@@ -276,6 +278,91 @@ func (metaClient *slackMetaClient) updateTopic(ctx context.Context, channelID st
276278
return nil
277279
}
278280

281+
func escapeText(txt string) (string, error) {
282+
obj := slack.NewTextBlockObject("mrkdown", "foobarbar", false, false)
283+
block := slack.NewSectionBlock(obj, nil, nil)
284+
msg := slack.NewBlockMessage(block)
285+
msg.
286+
287+
remainingTxt := escapeAmpersands(txt)
288+
289+
for {
290+
idxPair := rxRelaxed.FindStringIndex(remainingTxt)
291+
if idxPair == nil {
292+
break
293+
}
294+
295+
startIdx := idxPair[0]
296+
if startIdx > 0 && startIdx != '<' && startIdx != '|' {
297+
continue
298+
}
299+
300+
rxRelaxed.ReplaceAllString()
301+
302+
match := remainingTxt[startIdx:indexPair[1]]
303+
parsedURL, err := url.Parse(match)
304+
if err != nil {
305+
return "", fmt.Errorf("failed to parse URL %q: %s", match, err)
306+
}
307+
if parsedURL.Scheme == "" {
308+
strings.ReplaceAll(txt, match, fmt.Sprintf("<http://%s|%s>", match, match))
309+
} else {
310+
strings.ReplaceAll(txt, match, fmt.Sprintf("<http://%s|%s>", match, match))
311+
}
312+
}
313+
314+
}
315+
316+
func escapeAmpersands(txt string) string {
317+
parts := strings.Split(txt, "&")
318+
if len(parts) == 1 {
319+
return txt
320+
}
321+
322+
const ampSuffix = "amp;"
323+
324+
var b strings.Builder
325+
for i, part := range parts {
326+
b.WriteString(part)
327+
if i == len(parts)-1 {
328+
break
329+
}
330+
b.WriteRune('&')
331+
nextIdx := i + 1
332+
if strings.HasPrefix(parts[nextIdx], ampSuffix) {
333+
b.WriteString(ampSuffix)
334+
parts[nextIdx] = strings.TrimPrefix(parts[nextIdx], ampSuffix)
335+
}
336+
}
337+
338+
return b.String()
339+
}
340+
341+
func isEncodedURL(txt string, pair []int) bool {
342+
left := pair[0] - 1
343+
if left == 0 {
344+
return false
345+
}
346+
right := pair[1] + 1
347+
if right == len(txt)-1 {
348+
return false
349+
}
350+
return txt[left] == '<' && txt[right] == '>'
351+
}
352+
353+
func textMatchesAt(txt string, i int, substr string) bool {
354+
if len(txt) < i {
355+
return false
356+
}
357+
358+
suffix := txt[i:]
359+
lenSubstr := len(substr)
360+
if len(suffix) < lenSubstr {
361+
return false
362+
}
363+
return suffix[:lenSubstr] == substr
364+
}
365+
279366
func createSlackUser(apiUser slack.User) slackUser {
280367
return slackUser{
281368
id: apiUser.ID,

vendor/modules.txt

+3
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,6 @@ golang.org/x/xerrors/internal
4848
# gopkg.in/yaml.v2 v2.2.8
4949
## explicit
5050
gopkg.in/yaml.v2
51+
# mvdan.cc/xurls/v2 v2.5.0
52+
## explicit; go 1.19
53+
mvdan.cc/xurls/v2
+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# To prevent CRLF breakages on Windows for fragile files, like testdata.
2+
* -text

vendor/mvdan.cc/xurls/v2/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
cmd/xurls/xurls
2+
generate/tldsgen/tldsgen
3+
generate/regexgen/regexgen

vendor/mvdan.cc/xurls/v2/LICENSE

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Copyright (c) 2015, Daniel Martí. All rights reserved.
2+
3+
Redistribution and use in source and binary forms, with or without
4+
modification, are permitted provided that the following conditions are
5+
met:
6+
7+
* Redistributions of source code must retain the above copyright
8+
notice, this list of conditions and the following disclaimer.
9+
* Redistributions in binary form must reproduce the above
10+
copyright notice, this list of conditions and the following disclaimer
11+
in the documentation and/or other materials provided with the
12+
distribution.
13+
* Neither the name of the copyright holder nor the names of its
14+
contributors may be used to endorse or promote products derived from
15+
this software without specific prior written permission.
16+
17+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

vendor/mvdan.cc/xurls/v2/README.md

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
# xurls
2+
3+
[![Go Reference](https://pkg.go.dev/badge/mvdan.cc/xurls/v2.svg)](https://pkg.go.dev/mvdan.cc/xurls/v2)
4+
5+
Extract urls from text using regular expressions. Requires Go 1.19 or later.
6+
7+
```go
8+
import "mvdan.cc/xurls/v2"
9+
10+
func main() {
11+
rxRelaxed := xurls.Relaxed()
12+
rxRelaxed.FindString("Do gophers live in golang.org?") // "golang.org"
13+
rxRelaxed.FindString("This string does not have a URL") // ""
14+
15+
rxStrict := xurls.Strict()
16+
rxStrict.FindAllString("must have scheme: http://foo.com/.", -1) // []string{"http://foo.com/"}
17+
rxStrict.FindAllString("no scheme, no match: foo.com", -1) // []string{}
18+
}
19+
```
20+
21+
Since API is centered around [regexp.Regexp](https://golang.org/pkg/regexp/#Regexp),
22+
many other methods are available, such as finding the [byte indexes](https://golang.org/pkg/regexp/#Regexp.FindAllIndex)
23+
for all matches.
24+
25+
The regular expressions are compiled when the API is first called.
26+
Any subsequent calls will use the same regular expression pointers.
27+
28+
#### cmd/xurls
29+
30+
To install the tool globally:
31+
32+
go install mvdan.cc/xurls/v2/cmd/xurls@latest
33+
34+
```shell
35+
$ echo "Do gophers live in http://golang.org?" | xurls
36+
http://golang.org
37+
```

0 commit comments

Comments
 (0)