From a12aab42fcfb05c4b9d53b95087aba9f1234577b Mon Sep 17 00:00:00 2001 From: Seth Hoenig Date: Sat, 20 Jun 2026 07:12:27 -0500 Subject: [PATCH] repo: refactor to be one tool --- Justfile | 12 +-- cmds/nerfs-builds/commands/commands.go | 83 ------------------- cmds/nerfs-builds/wordlist/words.txt | 28 ------- cmds/nerfs/commands/commands.go | 63 ++++++++++++++ .../domains/artifact.go | 0 .../domains/builder.go | 5 +- .../{nerfs-builds => nerfs}/domains/source.go | 0 .../domains/source_test.go | 0 cmds/{nerfs-builds => nerfs}/main.go | 2 +- .../wordlist/artifact.go | 2 +- .../wordlist/artifact_test.go | 0 .../wordlist/builder.go | 5 +- .../wordlist/builder_test.go | 13 ++- .../{nerfs-builds => nerfs}/wordlist/embed.go | 0 cmds/nerfs/wordlist/words.txt | 14 ++++ nerfs.go | 9 +- nerfs_test.go | 39 +++++++++ 17 files changed, 143 insertions(+), 132 deletions(-) delete mode 100644 cmds/nerfs-builds/commands/commands.go delete mode 100644 cmds/nerfs-builds/wordlist/words.txt create mode 100644 cmds/nerfs/commands/commands.go rename cmds/{nerfs-builds => nerfs}/domains/artifact.go (100%) rename cmds/{nerfs-builds => nerfs}/domains/builder.go (89%) rename cmds/{nerfs-builds => nerfs}/domains/source.go (100%) rename cmds/{nerfs-builds => nerfs}/domains/source_test.go (100%) rename cmds/{nerfs-builds => nerfs}/main.go (74%) rename cmds/{nerfs-builds => nerfs}/wordlist/artifact.go (96%) rename cmds/{nerfs-builds => nerfs}/wordlist/artifact_test.go (100%) rename cmds/{nerfs-builds => nerfs}/wordlist/builder.go (87%) rename cmds/{nerfs-builds => nerfs}/wordlist/builder_test.go (75%) rename cmds/{nerfs-builds => nerfs}/wordlist/embed.go (100%) create mode 100644 cmds/nerfs/wordlist/words.txt diff --git a/Justfile b/Justfile index d4d5382..52d9c30 100644 --- a/Justfile +++ b/Justfile @@ -8,19 +8,19 @@ export GOBIN := `echo $PWD/.bin` default: @just --list -# start nerfs-builds artifact builder in demo mode +# start nerfs artifact builder in demo mode run mode: compile - $GOBIN/nerfs-builds {{mode}} + $GOBIN/nerfs {{mode}} -# compile the nerfs-builds executable +# compile the nerfs executable compile: tidy - cd cmds/nerfs-builds && go install + cd cmds/nerfs && go install # tidy up Go modules tidy: go mod tidy -# vet the nerfs-compile source tree +# vet the nerfs source tree vet: go vet ./... @@ -28,7 +28,7 @@ vet: tests: go test -race ./... -# lint the nerfs-compile source tree +# lint the nerfs source tree lint: vet $GOBIN/golangci-lint run --config $scripts/golangci.yaml diff --git a/cmds/nerfs-builds/commands/commands.go b/cmds/nerfs-builds/commands/commands.go deleted file mode 100644 index 70ed0aa..0000000 --- a/cmds/nerfs-builds/commands/commands.go +++ /dev/null @@ -1,83 +0,0 @@ -package commands - -import ( - "fmt" - "os" - "path/filepath" - - "cattlecloud.net/go/babycli" - "cattlecloud.net/nerfs" - "cattlecloud.net/nerfs/cmds/nerfs-builds/domains" - "cattlecloud.net/nerfs/cmds/nerfs-builds/wordlist" -) - -func Invoke(args []string) babycli.Code { - return invoke(args) -} - -func invoke(args []string) babycli.Code { - return babycli.New(&babycli.Configuration{ - Arguments: args, - Version: "v0.0.0-dev", - Top: &babycli.Component{ - Name: "nerfs-builds", - Help: "run the artifact builder(s)", - Description: "Builds an artifact", - Flags: babycli.Flags{}, - Components: babycli.Components{ - { - Name: "wordlist", - Help: "generate the wordlist.txt artifact", - Flags: babycli.Flags{ - { - Type: babycli.StringFlag, - Long: "output", - Require: true, - Short: "o", - Help: "specify output FILE", - Default: &babycli.Default{ - Value: filepath.Join(os.TempDir(), nerfs.WordsFile), - Show: true, - }, - }, - }, - Function: func(c *babycli.Component) babycli.Code { - output := c.GetString("output") - b := wordlist.NewBuilder() - if err := b.Build(output); err != nil { - fmt.Println("build failure:", err) - return babycli.Failure - } - return babycli.Success - }, - }, - { - Name: "domains", - Help: "generate the domains.txt artifact", - Flags: babycli.Flags{ - { - Type: babycli.StringFlag, - Long: "output", - Require: true, - Short: "o", - Help: "specify output FILE", - Default: &babycli.Default{ - Value: filepath.Join(os.TempDir(), nerfs.DomainsFile), - Show: true, - }, - }, - }, - Function: func(c *babycli.Component) babycli.Code { - output := c.GetString("output") - b := domains.NewBuilder() - if err := b.Build(output); err != nil { - fmt.Println("build failure:", err) - return babycli.Failure - } - return babycli.Success - }, - }, - }, - }, - }).Run() -} diff --git a/cmds/nerfs-builds/wordlist/words.txt b/cmds/nerfs-builds/wordlist/words.txt deleted file mode 100644 index 4a751b2..0000000 --- a/cmds/nerfs-builds/wordlist/words.txt +++ /dev/null @@ -1,28 +0,0 @@ -camel jockey -> (?i)\bc[a@]m[e3]l[\s-]*j[o0]ck[e3]y[s$]?\b -carpet muncher -> (?i)\bc[a@]rp[e3]t[\s-]*munch[e3]r[s$]?\b -chink -> (?i)\bch[i1]nk[s$]?\b -clit -> (?i)\bcl[i1]t[s$]?\b -cock sucker -> (?i)\bc[o0]ck[\s-]*[s$]uck[e3]r[s$]?\b -coom -> (?i)\bc[o0]+m[s$]?\b -coomer -> (?i)\bc[o0]+m[e3]r[s$]?\b -coon -> (?i)\bc[o0]+n[s$]?\b -cooch -> (?i)\bc[o0]+ch\b -coochie -> (?i)\bc[o0]+chi[e3][s$]?\b -cum -> (?i)\bcum[s$]?\b -dago -> (?i)\bd[a@]g[o0][s$]?\b -dyke -> (?i)\bd[i1y]k[e3][s$]?\b -fag -> (?i)\bf[a@]g[s$]?\b -faggot -> (?i)\bf[a@]gg[o0]t[s$]?\b -gook -> (?i)\bg[o0]+k[s$]?\b -heeb -> (?i)\bh[e3]b[s$]?\b -jizz -> (?i)\bj[i1]z+\b -kyke -> (?i)\bk[i1y]k[e3][s$]?\b -nigger -> (?i)\bn[i1]g+[e3]r[zs$]?\b -spic -> (?i)\bsp[i1][ck][s$]?\b -tit -> (?i)\bt[i1]t[s$]?\b -titty -> (?i)\bt[i1]tty[s$]?\b -tittyfuck -> (?i)\bt[i1]ttyfuc?k?[s$]?\b -tittyfucker -> (?i)\bt[i1]ttyfuc?k?[e3]r[s$]?\b -wetback -> (?i)\bw[e3]tb[a@]c?k?[s$]?\b -wigger -> (?i)\bw[i1]gg[e3]r[s$]?\b -wop -> (?i)\bw[o0]p[s$]?\b diff --git a/cmds/nerfs/commands/commands.go b/cmds/nerfs/commands/commands.go new file mode 100644 index 0000000..203f67c --- /dev/null +++ b/cmds/nerfs/commands/commands.go @@ -0,0 +1,63 @@ +package commands + +import ( + "fmt" + "os" + + "cattlecloud.net/go/babycli" + "cattlecloud.net/nerfs/cmds/nerfs/domains" + "cattlecloud.net/nerfs/cmds/nerfs/wordlist" +) + +func Invoke(args []string) babycli.Code { + return invoke(args) +} + +func invoke(args []string) babycli.Code { + return babycli.New(&babycli.Configuration{ + Arguments: args, + Version: "v0.0.0", + Top: &babycli.Component{ + Name: "nerfs", + Help: "run the artifact builder(s)", + Description: "Builds an artifact", + Flags: babycli.Flags{}, + Components: babycli.Components{ + { + Name: "build", + Help: "generate the artifact files", + Flags: babycli.Flags{ + { + Type: babycli.StringFlag, + Long: "output", + Require: true, + Short: "o", + Help: "specify output DIR", + Default: &babycli.Default{ + Value: os.TempDir(), + Show: true, + }, + }, + }, + Function: func(c *babycli.Component) babycli.Code { + output := c.GetString("output") + + buildDomains := domains.NewBuilder() + if err := buildDomains.Build(output); err != nil { + fmt.Println("build failure:", err) + return babycli.Failure + } + + buildWords := wordlist.NewBuilder() + if err := buildWords.Build(output); err != nil { + fmt.Println("build failure:", err) + return babycli.Failure + } + + return babycli.Success + }, + }, + }, + }, + }).Run() +} diff --git a/cmds/nerfs-builds/domains/artifact.go b/cmds/nerfs/domains/artifact.go similarity index 100% rename from cmds/nerfs-builds/domains/artifact.go rename to cmds/nerfs/domains/artifact.go diff --git a/cmds/nerfs-builds/domains/builder.go b/cmds/nerfs/domains/builder.go similarity index 89% rename from cmds/nerfs-builds/domains/builder.go rename to cmds/nerfs/domains/builder.go index 39d9e24..f2b9fc4 100644 --- a/cmds/nerfs-builds/domains/builder.go +++ b/cmds/nerfs/domains/builder.go @@ -7,6 +7,7 @@ import ( "cattlecloud.net/go/atomicfs" "cattlecloud.net/go/ulog" + "cattlecloud.net/nerfs" ) var sources = []string{ @@ -30,7 +31,7 @@ func NewBuilder() *Builder { } } -func (b *Builder) Build(destination string) error { +func (b *Builder) Build(directory string) error { start := time.Now() b.log.I.Fmt("starting the build ...") @@ -48,13 +49,13 @@ func (b *Builder) Build(destination string) error { return err } - directory := filepath.Dir(destination) fw := atomicfs.New(atomicfs.Options{ TmpDirectory: directory, TmpExtension: ".temp", Mode: 0o644, }) + destination := filepath.Join(directory, nerfs.DomainsFile) b.log.I.Fmt("writing artifact to %s", destination) if err := fw.WriteFile(destination, buf); err != nil { return err diff --git a/cmds/nerfs-builds/domains/source.go b/cmds/nerfs/domains/source.go similarity index 100% rename from cmds/nerfs-builds/domains/source.go rename to cmds/nerfs/domains/source.go diff --git a/cmds/nerfs-builds/domains/source_test.go b/cmds/nerfs/domains/source_test.go similarity index 100% rename from cmds/nerfs-builds/domains/source_test.go rename to cmds/nerfs/domains/source_test.go diff --git a/cmds/nerfs-builds/main.go b/cmds/nerfs/main.go similarity index 74% rename from cmds/nerfs-builds/main.go rename to cmds/nerfs/main.go index a88b9fd..4771ab3 100644 --- a/cmds/nerfs-builds/main.go +++ b/cmds/nerfs/main.go @@ -4,7 +4,7 @@ import ( "os" "cattlecloud.net/go/babycli" - "cattlecloud.net/nerfs/cmds/nerfs-builds/commands" + "cattlecloud.net/nerfs/cmds/nerfs/commands" ) func main() { diff --git a/cmds/nerfs-builds/wordlist/artifact.go b/cmds/nerfs/wordlist/artifact.go similarity index 96% rename from cmds/nerfs-builds/wordlist/artifact.go rename to cmds/nerfs/wordlist/artifact.go index f1cb1e1..ee926da 100644 --- a/cmds/nerfs-builds/wordlist/artifact.go +++ b/cmds/nerfs/wordlist/artifact.go @@ -19,7 +19,7 @@ func NewArtifact() *Artifact { func (a *Artifact) Add(line string) { // given line is directly from words.txt which is in the form - // -> + // -> tokens := strings.Split(line, "->") if len(tokens) != 2 { diff --git a/cmds/nerfs-builds/wordlist/artifact_test.go b/cmds/nerfs/wordlist/artifact_test.go similarity index 100% rename from cmds/nerfs-builds/wordlist/artifact_test.go rename to cmds/nerfs/wordlist/artifact_test.go diff --git a/cmds/nerfs-builds/wordlist/builder.go b/cmds/nerfs/wordlist/builder.go similarity index 87% rename from cmds/nerfs-builds/wordlist/builder.go rename to cmds/nerfs/wordlist/builder.go index f1c4090..e6c7609 100644 --- a/cmds/nerfs-builds/wordlist/builder.go +++ b/cmds/nerfs/wordlist/builder.go @@ -9,6 +9,7 @@ import ( "cattlecloud.net/go/atomicfs" "cattlecloud.net/go/ulog" + "cattlecloud.net/nerfs" ) type Builder struct { @@ -21,7 +22,7 @@ func NewBuilder() *Builder { } } -func (b *Builder) Build(destination string) error { +func (b *Builder) Build(directory string) error { start := time.Now() b.log.I.Fmt("starting the build ...") @@ -41,13 +42,13 @@ func (b *Builder) Build(destination string) error { return err } - directory := filepath.Dir(destination) fw := atomicfs.New(atomicfs.Options{ TmpDirectory: directory, TmpExtension: ".temp", Mode: 0o644, }) + destination := filepath.Join(directory, nerfs.WordsFile) b.log.I.Fmt("writing artifact to %s", destination) if err := fw.WriteFile(destination, buf); err != nil { return err diff --git a/cmds/nerfs-builds/wordlist/builder_test.go b/cmds/nerfs/wordlist/builder_test.go similarity index 75% rename from cmds/nerfs-builds/wordlist/builder_test.go rename to cmds/nerfs/wordlist/builder_test.go index be6adbe..9696480 100644 --- a/cmds/nerfs-builds/wordlist/builder_test.go +++ b/cmds/nerfs/wordlist/builder_test.go @@ -3,28 +3,29 @@ package wordlist import ( "encoding/json" "os" + "path/filepath" "regexp" "testing" + "cattlecloud.net/nerfs" "github.com/shoenig/test/must" - "github.com/shoenig/test/util" ) const ( // numWords must match the number of expressions in words.txt - numWords = 28 + numWords = 14 ) func TestBuilder_Build(t *testing.T) { t.Parallel() - dest := util.TempFile(t) + dir := t.TempDir() b := NewBuilder() - err := b.Build(dest) + err := b.Build(dir) must.NoError(t, err) - f, ferr := os.Open(dest) + f, ferr := os.Open(filepath.Join(dir, nerfs.WordsFile)) must.NoError(t, ferr) m := make(map[string]*regexp.Regexp) @@ -34,8 +35,6 @@ func TestBuilder_Build(t *testing.T) { t.Run("spot checks", func(t *testing.T) { must.RegexMatch(t, m["wop"], "wop") - must.RegexMatch(t, m["coom"], "c00m$") - must.RegexMatch(t, m["camel jockey"], "c@m3l-jock3ys") must.RegexMatch(t, m["dago"], "d@g0$") // non-matching due to word boundary diff --git a/cmds/nerfs-builds/wordlist/embed.go b/cmds/nerfs/wordlist/embed.go similarity index 100% rename from cmds/nerfs-builds/wordlist/embed.go rename to cmds/nerfs/wordlist/embed.go diff --git a/cmds/nerfs/wordlist/words.txt b/cmds/nerfs/wordlist/words.txt new file mode 100644 index 0000000..6549c6f --- /dev/null +++ b/cmds/nerfs/wordlist/words.txt @@ -0,0 +1,14 @@ +chink -> (?i)\bch[i1]nk[s$]?\b +clit -> (?i)\bcl[i1]t[s$]?\b +dago -> (?i)\bd[a@]g[o0][s$]?\b +dyke -> (?i)\bd[i1y]k[e3][s$]?\b +fag -> (?i)\bf[a@]g[s$]?\b +faggot -> (?i)\bf[a@]gg[o0]t[s$]?\b +gook -> (?i)\bg[o0]+k[s$]?\b +heeb -> (?i)\bh[e3]b[s$]?\b +kyke -> (?i)\bk[i1y]k[e3][s$]?\b +nigger -> (?i)\bn[i1]g+[e3]r[zs$]?\b +spic -> (?i)\bsp[i1][ck][s$]?\b +wetback -> (?i)\bw[e3]tb[a@]c?k?[s$]?\b +wigger -> (?i)\bw[i1]gg[e3]r[s$]?\b +wop -> (?i)\bw[o0]p[s$]?\b diff --git a/nerfs.go b/nerfs.go index 55f437a..86559c6 100644 --- a/nerfs.go +++ b/nerfs.go @@ -14,11 +14,11 @@ import ( const ( DomainsFile = "domains.txt" - WordsFile = "wordlist.json" + WordsFile = "wordlist.txt" ) // An Artifact contains the in-memory optimized form of the domain and word -// block-list files created by the nerfs-builds tool. +// block-list files created by the nerfs tool. // // Create an Artifact by calling Load() with the directory of the compiled // artifacts. @@ -64,6 +64,11 @@ func (a *Artifact) Synopsis(r io.Reader) *Synopsis { } func (a *Artifact) matchDomain(s string) bool { + s, _ = strings.CutPrefix(s, "https://") + s, _ = strings.CutPrefix(s, "http://") + if i := strings.IndexAny(s, "/?#"); i >= 0 { + s = s[:i] + } return a.domains.Contains(s) } diff --git a/nerfs_test.go b/nerfs_test.go index 55c7e7e..265164a 100644 --- a/nerfs_test.go +++ b/nerfs_test.go @@ -112,3 +112,42 @@ visit example.org we have pOop and f4rts! example.xyz and example.com too! must.True(t, syn.Any()) }) } + +func TestArtifact_matchDomain(t *testing.T) { + t.Parallel() + + a := &Artifact{ + domains: set.From([]string{"example.com", "example.xyz"}), + } + + cases := []struct { + input string + exp bool + }{ + { + input: "example.com", + exp: true, + }, + { + input: "https://example.com", + exp: true, + }, + { + input: "https://example.com/path", + exp: true, + }, + { + input: "https://safe.example.com/path", + exp: false, + }, + { + input: "other", + exp: false, + }, + } + + for _, tc := range cases { + result := a.matchDomain(tc.input) + must.Eq(t, tc.exp, result) + } +}