package chat import ( "strings" "github.com/diamondburned/arikawa/v3/discord" "github.com/diamondburned/ningen/v3/discordmd" "github.com/yuin/goldmark/ast" "github.com/yuin/goldmark/parser" "github.com/yuin/goldmark/text" ) func extractURLs(content string) []string { src := []byte(content) node := parser.NewParser( parser.WithBlockParsers(discordmd.BlockParsers()...), parser.WithInlineParsers(discordmd.InlineParserWithLink()...), ).Parse(text.NewReader(src)) var urls []string ast.Walk(node, func(n ast.Node, entering bool) (ast.WalkStatus, error) { if entering { switch n := n.(type) { case *ast.AutoLink: urls = append(urls, string(n.URL(src))) case *ast.Link: urls = append(urls, string(n.Destination)) } } return ast.WalkContinue, nil }) return urls } func extractEmbedURLs(embeds []discord.Embed) []string { urls := make([]string, 0, len(embeds)*3) for _, embed := range embeds { if embed.URL != "" { urls = append(urls, string(embed.URL)) } if embed.Image != nil && embed.Image.URL != "" { urls = append(urls, string(embed.Image.URL)) } if embed.Video != nil && embed.Video.URL != "" { urls = append(urls, string(embed.Video.URL)) } } return urls } func messageURLs(msg discord.Message) []string { combined := extractURLs(msg.Content) combined = append(combined, extractEmbedURLs(msg.Embeds)...) urls := make([]string, 0, len(combined)) seen := make(map[string]struct{}, len(combined)) for _, u := range combined { u = strings.TrimSpace(u) if u == "" { continue } if _, ok := seen[u]; ok { continue } seen[u] = struct{}{} urls = append(urls, u) } return urls }