From f06a04e0f003c556c9273b2c4660b201d179598e Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Wed, 27 Nov 2024 21:21:29 +0200 Subject: refactoring tags --- internal/entry/entry.go | 19 ++---- internal/entry/entry_test.go | 10 ++-- internal/entry/sharetags.go | 42 -------------- internal/entry/sharetags_test.go | 117 ------------------------------------- internal/queue/inlinetags.go | 81 -------------------------- internal/queue/inlinetags_test.go | 75 ------------------------ internal/queue/queue.go | 8 ++- internal/tags/inline.go | 81 ++++++++++++++++++++++++++ internal/tags/inline_test.go | 75 ++++++++++++++++++++++++ internal/tags/share.go | 46 +++++++++++++++ internal/tags/share_test.go | 118 ++++++++++++++++++++++++++++++++++++++ internal/tags/tags.go | 1 + 12 files changed, 335 insertions(+), 338 deletions(-) delete mode 100644 internal/entry/sharetags.go delete mode 100644 internal/entry/sharetags_test.go delete mode 100644 internal/queue/inlinetags.go delete mode 100644 internal/queue/inlinetags_test.go create mode 100644 internal/tags/inline.go create mode 100644 internal/tags/inline_test.go create mode 100644 internal/tags/share.go create mode 100644 internal/tags/share_test.go create mode 100644 internal/tags/tags.go diff --git a/internal/entry/entry.go b/internal/entry/entry.go index 3e21328..70b8396 100644 --- a/internal/entry/entry.go +++ b/internal/entry/entry.go @@ -9,7 +9,6 @@ import ( "strings" "time" - "codeberg.org/snonux/gos/internal/config" "codeberg.org/snonux/gos/internal/oi" "codeberg.org/snonux/gos/internal/prompt" "codeberg.org/snonux/gos/internal/timestamp" @@ -50,7 +49,7 @@ type Entry struct { Path string Time time.Time State State - tags map[string]struct{} + Tags map[string]struct{} } func (en Entry) String() string { @@ -64,7 +63,7 @@ func (en Entry) String() string { // or for inboxed: /foo.txt // or inboxed with tags: /foo.prio.ask.txt func New(filePath string) (Entry, error) { - en := Entry{Path: filePath, tags: make(map[string]struct{})} + en := Entry{Path: filePath, Tags: make(map[string]struct{})} // We want to get the STAMP! parts := strings.Split(filePath, ".") @@ -147,20 +146,10 @@ func (en *Entry) MarkPosted() error { } func (en Entry) HasTag(tag string) bool { - _, ok := en.tags[tag] + _, ok := en.Tags[tag] return ok } -// Valid tags are: share:foo[,...] -// whereas foo can be a supported platform such as linkedin, mastodon, etc. -// foo can also be prefixed with - to exclude it. See unit tests for examples. -func (en Entry) PlatformExcluded(args config.Args, platformStr string) (bool, error) { - s, err := newShareTags(args, en.tags) - fmt.Println(s) - return slices.Contains(s.excludes, platformStr) || - !slices.Contains(s.includes, platformStr), err -} - func (en Entry) Edit() error { if err := prompt.EditFile(en.Path); err != nil { return err @@ -184,7 +173,7 @@ func (en Entry) FileAction(question string) error { func (en Entry) extractTags(parts []string) { for _, part := range parts { if slices.Contains(validTags, part) || strings.HasPrefix(part, "share:") { - en.tags[part] = struct{}{} + en.Tags[part] = struct{}{} } } } diff --git a/internal/entry/entry_test.go b/internal/entry/entry_test.go index 6a54b05..f9df524 100644 --- a/internal/entry/entry_test.go +++ b/internal/entry/entry_test.go @@ -52,12 +52,12 @@ func TestEntryTags(t *testing.T) { for _, expectedTag := range strings.Split(tagsStr, ".") { if expectedTag == "invalid" { if en.HasTag(expectedTag) { - t.Errorf("didn't expect tag '%s' to be present, but got '%v'", expectedTag, en.tags) + t.Errorf("didn't expect tag '%s' to be present, but got '%v'", expectedTag, en.Tags) } continue } if !en.HasTag(expectedTag) { - t.Errorf("expected tag '%s' to be present, but got '%v'", expectedTag, en.tags) + t.Errorf("expected tag '%s' to be present, but got '%v'", expectedTag, en.Tags) } } } @@ -115,12 +115,12 @@ func TestHasTag(t *testing.T) { if err != nil { t.Error(err) } - if len(expectedTags) != len(en.tags) { - t.Errorf("expected '%d' tags but got '%d'", len(expectedTags), len(en.tags)) + if len(expectedTags) != len(en.Tags) { + t.Errorf("expected '%d' tags but got '%d'", len(expectedTags), len(en.Tags)) } for _, tag := range expectedTags { if !en.HasTag(tag) { - t.Errorf("expected tag '%s' but got '%s'", tag, en.tags) + t.Errorf("expected tag '%s' but got '%s'", tag, en.Tags) } } } diff --git a/internal/entry/sharetags.go b/internal/entry/sharetags.go deleted file mode 100644 index 3075e2f..0000000 --- a/internal/entry/sharetags.go +++ /dev/null @@ -1,42 +0,0 @@ -package entry - -import ( - "slices" - "strings" - - "codeberg.org/snonux/gos/internal/config" -) - -// TODO: Own package only dealing with tags, and put all tag code in there. -type shareTags struct { - includes []string // The platforms to include - excludes []string // The platforms to exclude -} - -func newShareTags(args config.Args, tags map[string]struct{}) (shareTags, error) { - var s shareTags - - for tag := range tags { - if !strings.HasPrefix(tag, "share:") { - continue - } - for _, t := range strings.Split(tag[6:], ":") { - if strings.HasPrefix(t, "-") { - s.excludes = append(s.excludes, strings.ToLower(t[1:])) - } else { - s.includes = append(s.includes, strings.ToLower(t)) - } - } - } - - if len(s.includes) == 0 { - for platformStr := range args.Platforms { - if slices.Contains(s.excludes, strings.ToLower(platformStr)) { - continue - } - s.includes = append(s.includes, strings.ToLower(platformStr)) - } - } - - return s, nil -} diff --git a/internal/entry/sharetags_test.go b/internal/entry/sharetags_test.go deleted file mode 100644 index 73ba8db..0000000 --- a/internal/entry/sharetags_test.go +++ /dev/null @@ -1,117 +0,0 @@ -package entry - -import ( - "slices" - "strings" - "testing" - - "codeberg.org/snonux/gos/internal/config" -) - -func TestShareTagsPositive(t *testing.T) { - args := config.Args{Platforms: map[string]int{ - "mastodon": 100, - "linkedin": 100, - }} - testTable := map[string]shareTags{ - "./foo/bar.without.tags.txt.20240101-010101.queued": { - includes: []string{"mastodon", "linkedin"}, - }, - "./foo/bar.share:linkeDin.txt.20240101-010101.queued": { - includes: []string{"linkedin"}, - }, - "./foo/bar.share:-LinkedIn.txt.20240101-010101.queued": { - includes: []string{"mastodon"}, - excludes: []string{"linkedin"}, - }, - "./foo/bar.share:linkedin:mastOdon.txt.20240101-010101.queued": { - includes: []string{"linkedin", "mastodon"}, - }, - "./foo/bar.share:linkediN:-mastodon:XCOM.txt.20240101-010101.queued": { - includes: []string{"linkedin", "xcom"}, - excludes: []string{"mastodon"}, - }, - "./foo/bar/ql-e7657e8a1ab573f84ad0dbc55199e937.share:-mastodon.txt.20241018-105524.queued": { - includes: []string{"linkedin"}, - excludes: []string{"mastodon"}, - }, - } - - for filePath, expectedResult := range testTable { - t.Run(filePath, func(t *testing.T) { - shareTags, err := newShareTags(args, filePathTags(filePath)) - if err != nil { - t.Error(err) - } - if !sameElements(shareTags.includes, expectedResult.includes) { - t.Errorf("Expected includes to be %v but got %v with %s", - expectedResult.includes, shareTags.includes, filePath) - } - if !sameElements(shareTags.excludes, expectedResult.excludes) { - t.Errorf("Expected excludes to be %v but got %v with %s", - expectedResult.excludes, shareTags.excludes, filePath) - } - }) - - } -} -func TestShareTagsNegative(t *testing.T) { - args := config.Args{Platforms: map[string]int{ - string("mastodon"): 100, - string("linkedin"): 100, - }} - testTable := map[string]shareTags{ - "./foo/bar.without.tags.txt.20240101-010101.queued": { - includes: []string{"linkedin"}, - }, - "./foo/bar.share:linkedIn.txt.20240101-010101.queued": { - includes: []string{"mastodon"}, - }, - "./foo/bar.share:-liNkedin.txt.20240101-010101.queued": { - includes: []string{"linkedin"}, - }, - "./foo/bar.share:linkedin:mastodon.txt.20240101-010101.queued": { - includes: []string{"oups", "mastodon"}, - }, - "./foo/bar.share:linkedin:-MASTODON:xcom.txt.20240101-010101.queued": { - includes: []string{"linkedin", "xcom"}, - excludes: []string{"mastodon", "xcom"}, - }, - } - - for filePath, unexpectedResult := range testTable { - t.Run(filePath, func(t *testing.T) { - shareTags, err := newShareTags(args, filePathTags(filePath)) - if err != nil { - t.Error(err) - } - if sameElements(shareTags.includes, unexpectedResult.includes) && - sameElements(shareTags.excludes, unexpectedResult.excludes) { - t.Errorf("expected %v not to be the actual result with %s", - unexpectedResult, filePath) - } - }) - - } -} - -// Can't use slices.Equal as order of elements may be different. -func sameElements(a, b []string) bool { - if len(a) != len(b) { - return false - } - for _, elem := range a { - if !slices.Contains(b, elem) { - return false - } - } - return true -} - -func filePathTags(filePath string) map[string]struct{} { - tags := make(map[string]struct{}) - for _, tag := range strings.Split(filePath, ".") { - tags[tag] = struct{}{} - } - return tags -} diff --git a/internal/queue/inlinetags.go b/internal/queue/inlinetags.go deleted file mode 100644 index 82ee844..0000000 --- a/internal/queue/inlinetags.go +++ /dev/null @@ -1,81 +0,0 @@ -package queue - -import ( - "fmt" - "os" - "path/filepath" - "regexp" - "strings" - - "codeberg.org/snonux/gos/internal/colour" - "codeberg.org/snonux/gos/internal/oi" - "codeberg.org/snonux/gos/internal/platforms" -) - -var inlineTagRE = regexp.MustCompile(`^[a-z\.,:]*$`) - -// Extracts the inline tags into the filepath and removes them from the content. -func extractInlineTags(filePath string) (string, error) { - content, err := oi.SlurpAndTrim(filePath) - if err != nil { - return "", err - } - - newFilePath, newContent, err := extractInlineTagsToFilePath(filePath, content) - if err != nil { - return "", err - } - if newFilePath == filePath { - return filePath, nil - } - - colour.Infof("Rewriting path '%s' to '%s' (inline tag extraction)", filePath, newFilePath) - fmt.Print("\n") - if err := oi.WriteFile(newFilePath, newContent); err != nil { - return "", err - } - return newFilePath, os.Remove(filePath) -} - -func extractInlineTagsToFilePath(filePath, content string) (string, string, error) { - tags, newContent, err := extractInlineTagsFromContent(content) - if err != nil { - return filePath, content, err - } - if len(tags) == 0 { - return filePath, content, nil - } - - parts := strings.Split(strings.TrimSuffix(filePath, filepath.Ext(filePath)), ".") - parts = append(parts, tags...) - parts = append(parts, "extracted") - parts = append(parts, "txt") - - newFilePath := strings.Join(parts, ".") - return newFilePath, newContent, nil -} - -func extractInlineTagsFromContent(content string) ([]string, string, error) { - parts := strings.Split(content, " ") - if inlineTagRE.MatchString(parts[0]) { - var tags []string - for _, elem := range strings.Split(parts[0], ".") { - tags = append(tags, strings.Split(elem, ",")...) - } - if len(tags) == 0 { - tags = parts[:1] - } - if len(tags) > 0 { - for i := range len(tags) { - if strings.HasPrefix(tags[i], "share:") { - var err error - if tags[i], err = platforms.ExpandAliases(tags[i]); err != nil { - return []string{}, content, err - } - } - } - return tags, strings.Join(parts[1:], " "), nil - } - } - return []string{}, content, nil -} diff --git a/internal/queue/inlinetags_test.go b/internal/queue/inlinetags_test.go deleted file mode 100644 index a0d71b6..0000000 --- a/internal/queue/inlinetags_test.go +++ /dev/null @@ -1,75 +0,0 @@ -package queue - -import ( - "slices" - "strings" - "testing" -) - -func TestExtractInlineTagsToFilePath(t *testing.T) { - const filePath = "./gosdir/foo.golang.rox.txt" - - table := map[string]string{ - "foo,bar,baz blablablabla...": "./gosdir/foo.golang.rox.foo.bar.baz.extracted.txt", - "foo.bar.baz blablablabla...": "./gosdir/foo.golang.rox.foo.bar.baz.extracted.txt", - "foo.bar,baz blablablabla...": "./gosdir/foo.golang.rox.foo.bar.baz.extracted.txt", - "foo,bar.baz blablablabla...": "./gosdir/foo.golang.rox.foo.bar.baz.extracted.txt", - "share:li,foo this is the main content": "./gosdir/foo.golang.rox.share:linkedin.foo.extracted.txt", - "share:li:ma this is the main content": "./gosdir/foo.golang.rox.share:linkedin:mastodon.extracted.txt", - "share:li:ma,now this is the main content": "./gosdir/foo.golang.rox.share:linkedin:mastodon.now.extracted.txt", - } - - for content, expectedFilePath := range table { - t.Run(content, func(t *testing.T) { - newFilePath, _, err := extractInlineTagsToFilePath(filePath, content) - if err != nil { - t.Error(err) - } - if newFilePath != expectedFilePath { - t.Errorf("expected file path '%s' but got '%s'", expectedFilePath, newFilePath) - } - }) - } -} - -func TestExtractInlineTagsFromContent(t *testing.T) { - table := map[string][]string{ - "foo,bar,baz blablablabla...": {"foo", "bar", "baz"}, - "foo.bar.baz blablablabla...": {"foo", "bar", "baz"}, - "foo.bar,baz blablablabla...": {"foo", "bar", "baz"}, - "foo,bar.baz blablablabla...": {"foo", "bar", "baz"}, - "share:li this is the main content": {"share:linkedin"}, - "share:li,foo this is the main content": {"share:linkedin", "foo"}, - "shar()e:li,foo this is the main content": {}, - } - - for input, expectedTags := range table { - t.Run(input, func(t *testing.T) { - tags, contentWithoutTags, err := extractInlineTagsFromContent(input) - if err != nil { - t.Error(err) - } - if len(tags) != len(expectedTags) { - t.Errorf("expected %d inline tags (%v) but got %d (%v)", - len(expectedTags), expectedTags, len(tags), tags) - } - for _, expectedTag := range expectedTags { - if !slices.Contains(tags, expectedTag) { - t.Errorf("expected '%s' to be an inline tag but got '%v'", - expectedTag, tags) - } - } - - expectedMainContent := input - parts := strings.Split(input, " ") - if inlineTagRE.MatchString(parts[0]) { - expectedMainContent = strings.Join(parts[1:], " ") - } - - if contentWithoutTags != expectedMainContent { - t.Errorf("expected the main content to be '%s' but got '%s'", - expectedMainContent, contentWithoutTags) - } - }) - } -} diff --git a/internal/queue/queue.go b/internal/queue/queue.go index 832b877..80f6dcd 100644 --- a/internal/queue/queue.go +++ b/internal/queue/queue.go @@ -12,6 +12,7 @@ import ( "codeberg.org/snonux/gos/internal/entry" "codeberg.org/snonux/gos/internal/oi" "codeberg.org/snonux/gos/internal/platforms" + "codeberg.org/snonux/gos/internal/tags" "codeberg.org/snonux/gos/internal/timestamp" ) @@ -36,7 +37,7 @@ func queueEntries(args config.Args) error { } for filePath := range ch { - if filePath, err = extractInlineTags(filePath); err != nil { + if filePath, err = tags.InlineExtract(filePath); err != nil { return err } en, err := entry.New(filePath) @@ -82,11 +83,12 @@ func queuePlatforms(args config.Args) error { if err != nil { return err } - excluded, err := en.PlatformExcluded(args, platform.String()) + // func NewShare(args config.Args, tags map[string]struct{}) (Share, error) { + share, err := tags.NewShare(args, en.Tags) if err != nil { return err } - if excluded { + if share.Excluded(platform.String()) { colour.Infoln("Not queueing entry", en, "to platform", platform, "as it is excluded") continue } diff --git a/internal/tags/inline.go b/internal/tags/inline.go new file mode 100644 index 0000000..51277a5 --- /dev/null +++ b/internal/tags/inline.go @@ -0,0 +1,81 @@ +package tags + +import ( + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + + "codeberg.org/snonux/gos/internal/colour" + "codeberg.org/snonux/gos/internal/oi" + "codeberg.org/snonux/gos/internal/platforms" +) + +var inlineTagRE = regexp.MustCompile(`^[a-z\.,:]*$`) + +// Extracts the inline tags into the filepath and removes them from the content. +func InlineExtract(filePath string) (string, error) { + content, err := oi.SlurpAndTrim(filePath) + if err != nil { + return "", err + } + + newFilePath, newContent, err := inlineExtractTagsToFilePath(filePath, content) + if err != nil { + return "", err + } + if newFilePath == filePath { + return filePath, nil + } + + colour.Infof("Rewriting path '%s' to '%s' (inline tag extraction)", filePath, newFilePath) + fmt.Print("\n") + if err := oi.WriteFile(newFilePath, newContent); err != nil { + return "", err + } + return newFilePath, os.Remove(filePath) +} + +func inlineExtractTagsToFilePath(filePath, content string) (string, string, error) { + tags, newContent, err := inlineExtractTagsFromContent(content) + if err != nil { + return filePath, content, err + } + if len(tags) == 0 { + return filePath, content, nil + } + + parts := strings.Split(strings.TrimSuffix(filePath, filepath.Ext(filePath)), ".") + parts = append(parts, tags...) + parts = append(parts, "extracted") + parts = append(parts, "txt") + + newFilePath := strings.Join(parts, ".") + return newFilePath, newContent, nil +} + +func inlineExtractTagsFromContent(content string) ([]string, string, error) { + parts := strings.Split(content, " ") + if inlineTagRE.MatchString(parts[0]) { + var tags []string + for _, elem := range strings.Split(parts[0], ".") { + tags = append(tags, strings.Split(elem, ",")...) + } + if len(tags) == 0 { + tags = parts[:1] + } + if len(tags) > 0 { + for i := range len(tags) { + if strings.HasPrefix(tags[i], "share:") { + var err error + if tags[i], err = platforms.ExpandAliases(tags[i]); err != nil { + return []string{}, content, err + } + } + } + return tags, strings.Join(parts[1:], " "), nil + } + } + return []string{}, content, nil +} diff --git a/internal/tags/inline_test.go b/internal/tags/inline_test.go new file mode 100644 index 0000000..dab8b74 --- /dev/null +++ b/internal/tags/inline_test.go @@ -0,0 +1,75 @@ +package tags + +import ( + "slices" + "strings" + "testing" +) + +func TestInlineExtractTagsToFilePath(t *testing.T) { + const filePath = "./gosdir/foo.golang.rox.txt" + + table := map[string]string{ + "foo,bar,baz blablablabla...": "./gosdir/foo.golang.rox.foo.bar.baz.extracted.txt", + "foo.bar.baz blablablabla...": "./gosdir/foo.golang.rox.foo.bar.baz.extracted.txt", + "foo.bar,baz blablablabla...": "./gosdir/foo.golang.rox.foo.bar.baz.extracted.txt", + "foo,bar.baz blablablabla...": "./gosdir/foo.golang.rox.foo.bar.baz.extracted.txt", + "share:li,foo this is the main content": "./gosdir/foo.golang.rox.share:linkedin.foo.extracted.txt", + "share:li:ma this is the main content": "./gosdir/foo.golang.rox.share:linkedin:mastodon.extracted.txt", + "share:li:ma,now this is the main content": "./gosdir/foo.golang.rox.share:linkedin:mastodon.now.extracted.txt", + } + + for content, expectedFilePath := range table { + t.Run(content, func(t *testing.T) { + newFilePath, _, err := inlineExtractTagsToFilePath(filePath, content) + if err != nil { + t.Error(err) + } + if newFilePath != expectedFilePath { + t.Errorf("expected file path '%s' but got '%s'", expectedFilePath, newFilePath) + } + }) + } +} + +func TestInlineExtractTagsFromContent(t *testing.T) { + table := map[string][]string{ + "foo,bar,baz blablablabla...": {"foo", "bar", "baz"}, + "foo.bar.baz blablablabla...": {"foo", "bar", "baz"}, + "foo.bar,baz blablablabla...": {"foo", "bar", "baz"}, + "foo,bar.baz blablablabla...": {"foo", "bar", "baz"}, + "share:li this is the main content": {"share:linkedin"}, + "share:li,foo this is the main content": {"share:linkedin", "foo"}, + "shar()e:li,foo this is the main content": {}, + } + + for input, expectedTags := range table { + t.Run(input, func(t *testing.T) { + tags, contentWithoutTags, err := inlineExtractTagsFromContent(input) + if err != nil { + t.Error(err) + } + if len(tags) != len(expectedTags) { + t.Errorf("expected %d inline tags (%v) but got %d (%v)", + len(expectedTags), expectedTags, len(tags), tags) + } + for _, expectedTag := range expectedTags { + if !slices.Contains(tags, expectedTag) { + t.Errorf("expected '%s' to be an inline tag but got '%v'", + expectedTag, tags) + } + } + + expectedMainContent := input + parts := strings.Split(input, " ") + if inlineTagRE.MatchString(parts[0]) { + expectedMainContent = strings.Join(parts[1:], " ") + } + + if contentWithoutTags != expectedMainContent { + t.Errorf("expected the main content to be '%s' but got '%s'", + expectedMainContent, contentWithoutTags) + } + }) + } +} diff --git a/internal/tags/share.go b/internal/tags/share.go new file mode 100644 index 0000000..e58661a --- /dev/null +++ b/internal/tags/share.go @@ -0,0 +1,46 @@ +package tags + +import ( + "slices" + "strings" + + "codeberg.org/snonux/gos/internal/config" +) + +// Share tags. +type Share struct { + Includes []string // The platforms to include + Excludes []string // The platforms to exclude +} + +func NewShare(args config.Args, tags map[string]struct{}) (Share, error) { + var s Share + + for tag := range tags { + if !strings.HasPrefix(tag, "share:") { + continue + } + for _, t := range strings.Split(tag[6:], ":") { + if strings.HasPrefix(t, "-") { + s.Excludes = append(s.Excludes, strings.ToLower(t[1:])) + } else { + s.Includes = append(s.Includes, strings.ToLower(t)) + } + } + } + + if len(s.Includes) == 0 { + for platformStr := range args.Platforms { + if slices.Contains(s.Excludes, strings.ToLower(platformStr)) { + continue + } + s.Includes = append(s.Includes, strings.ToLower(platformStr)) + } + } + + return s, nil +} + +func (s Share) Excluded(platformStr string) bool { + return slices.Contains(s.Excludes, platformStr) || !slices.Contains(s.Includes, platformStr) +} diff --git a/internal/tags/share_test.go b/internal/tags/share_test.go new file mode 100644 index 0000000..f018593 --- /dev/null +++ b/internal/tags/share_test.go @@ -0,0 +1,118 @@ +package tags + +import ( + "slices" + "strings" + "testing" + + "codeberg.org/snonux/gos/internal/config" +) + +func TestSharePositive(t *testing.T) { + args := config.Args{Platforms: map[string]int{ + "mastodon": 100, + "linkedin": 100, + }} + testTable := map[string]Share{ + "./foo/bar.without.tags.txt.20240101-010101.queued": { + Includes: []string{"mastodon", "linkedin"}, + }, + "./foo/bar.share:linkeDin.txt.20240101-010101.queued": { + Includes: []string{"linkedin"}, + }, + "./foo/bar.share:-LinkedIn.txt.20240101-010101.queued": { + Includes: []string{"mastodon"}, + Excludes: []string{"linkedin"}, + }, + "./foo/bar.share:linkedin:mastOdon.txt.20240101-010101.queued": { + Includes: []string{"linkedin", "mastodon"}, + }, + "./foo/bar.share:linkediN:-mastodon:XCOM.txt.20240101-010101.queued": { + Includes: []string{"linkedin", "xcom"}, + Excludes: []string{"mastodon"}, + }, + "./foo/bar/ql-e7657e8a1ab573f84ad0dbc55199e937.share:-mastodon.txt.20241018-105524.queued": { + Includes: []string{"linkedin"}, + Excludes: []string{"mastodon"}, + }, + } + + for filePath, expectedResult := range testTable { + t.Run(filePath, func(t *testing.T) { + shareTags, err := NewShare(args, filePathTags(filePath)) + if err != nil { + t.Error(err) + } + if !sameElements(shareTags.Includes, expectedResult.Includes) { + t.Errorf("Expected includes to be %v but got %v with %s", + expectedResult.Includes, shareTags.Includes, filePath) + } + if !sameElements(shareTags.Excludes, expectedResult.Excludes) { + t.Errorf("Expected excludes to be %v but got %v with %s", + expectedResult.Excludes, shareTags.Excludes, filePath) + } + }) + + } +} + +func TestShareNegative(t *testing.T) { + args := config.Args{Platforms: map[string]int{ + string("mastodon"): 100, + string("linkedin"): 100, + }} + testTable := map[string]Share{ + "./foo/bar.without.tags.txt.20240101-010101.queued": { + Includes: []string{"linkedin"}, + }, + "./foo/bar.share:linkedIn.txt.20240101-010101.queued": { + Includes: []string{"mastodon"}, + }, + "./foo/bar.share:-liNkedin.txt.20240101-010101.queued": { + Includes: []string{"linkedin"}, + }, + "./foo/bar.share:linkedin:mastodon.txt.20240101-010101.queued": { + Includes: []string{"oups", "mastodon"}, + }, + "./foo/bar.share:linkedin:-MASTODON:xcom.txt.20240101-010101.queued": { + Includes: []string{"linkedin", "xcom"}, + Excludes: []string{"mastodon", "xcom"}, + }, + } + + for filePath, unexpectedResult := range testTable { + t.Run(filePath, func(t *testing.T) { + shareTags, err := NewShare(args, filePathTags(filePath)) + if err != nil { + t.Error(err) + } + if sameElements(shareTags.Includes, unexpectedResult.Includes) && + sameElements(shareTags.Excludes, unexpectedResult.Excludes) { + t.Errorf("expected %v not to be the actual result with %s", + unexpectedResult, filePath) + } + }) + + } +} + +// Can't use slices.Equal as order of elements may be different. +func sameElements(a, b []string) bool { + if len(a) != len(b) { + return false + } + for _, elem := range a { + if !slices.Contains(b, elem) { + return false + } + } + return true +} + +func filePathTags(filePath string) map[string]struct{} { + tags := make(map[string]struct{}) + for _, tag := range strings.Split(filePath, ".") { + tags[tag] = struct{}{} + } + return tags +} diff --git a/internal/tags/tags.go b/internal/tags/tags.go new file mode 100644 index 0000000..2eee961 --- /dev/null +++ b/internal/tags/tags.go @@ -0,0 +1 @@ +package tags -- cgit v1.2.3