From 2ad97e09f19b5cc9a3c183a348659853fb702c75 Mon Sep 17 00:00:00 2001 From: Zephyr Lykos Date: Fri, 10 Jan 2025 20:11:46 +0800 Subject: [PATCH] feat: follow XDG Base Directory Specification --- cmd/init.go | 14 +++++++++----- cmd/privileges.go | 21 ++++++++++----------- cmd/url.go | 3 +-- go.mod | 3 ++- go.sum | 6 ++++-- utils/filter.go | 21 ++++++++++----------- utils/filter_test.go | 6 ++---- utils/pqueue_test.go | 2 +- yaml/yaml.go | 2 +- yaml/yaml_test.go | 10 +++++----- 10 files changed, 45 insertions(+), 43 deletions(-) diff --git a/cmd/init.go b/cmd/init.go index a1024d3..292e3f1 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -17,10 +17,9 @@ import ( "encoding/gob" "fmt" "os" - "path" vt "github.com/VirusTotal/vt-go" - "github.com/mitchellh/go-homedir" + "github.com/adrg/xdg" "github.com/spf13/cobra" ) @@ -68,13 +67,13 @@ func NewInitCmd() *cobra.Command { os.Exit(1) } - dir, err := homedir.Dir() + relCache, err := xdg.CacheFile("vt-cli/relationships") if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) } - relCacheFile, err := os.Create(path.Join(dir, ".vt.relationships.cache")) + relCacheFile, err := os.Create(relCache) if err != nil { fmt.Fprintln(os.Stderr, err) os.Exit(1) @@ -88,7 +87,12 @@ func NewInitCmd() *cobra.Command { os.Exit(1) } - configFilePath := path.Join(dir, ".vt.toml") + configFilePath, err := xdg.ConfigFile("vt-cli/vt.toml") + if err != nil { + fmt.Fprintln(os.Stderr, err) + os.Exit(1) + } + configFile, err := os.Create(configFilePath) if err != nil { fmt.Fprintln(os.Stderr, err) diff --git a/cmd/privileges.go b/cmd/privileges.go index 03287a6..5df7000 100644 --- a/cmd/privileges.go +++ b/cmd/privileges.go @@ -11,7 +11,7 @@ import ( func NewPrivilegeCmd(target string) *cobra.Command { cmd := &cobra.Command{ - Use: "privileges", + Use: "privileges", Short: fmt.Sprintf("Change %s privileges", target), } @@ -21,9 +21,8 @@ func NewPrivilegeCmd(target string) *cobra.Command { return cmd } - type Privilege struct { - Granted bool `json:"granted"` + Granted bool `json:"granted"` ExpirationDate int64 `json:"expiration_date"` } @@ -31,13 +30,13 @@ type Privileges map[string]Privilege func NewPrivilegeGrantCmd(target string) *cobra.Command { cmd := &cobra.Command{ - Use: fmt.Sprintf("grant [%sname] [privilege]...", target), - Short: fmt.Sprintf("Grant privileges to a %s", target), + Use: fmt.Sprintf("grant [%sname] [privilege]...", target), + Short: fmt.Sprintf("Grant privileges to a %s", target), Example: fmt.Sprintf(" vt %s privileges grant my%s intelligence downloads-tier-2", target, target), - Args: cobra.MinimumNArgs(2), + Args: cobra.MinimumNArgs(2), RunE: func(cmd *cobra.Command, args []string) error { var expirationDate int64 - if expiration:= viper.GetString("expiration"); expiration != "" { + if expiration := viper.GetString("expiration"); expiration != "" { var err error expirationDate, err = strconv.ParseInt(expiration, 10, 64) if err != nil { @@ -68,7 +67,7 @@ func NewPrivilegeGrantCmd(target string) *cobra.Command { }, } - cmd.Flags().StringP("" + + cmd.Flags().StringP(""+ "expiration", "e", "", "expiration time for the granted privileges (UNIX timestamp or YYYY-MM-DD)") return cmd @@ -76,10 +75,10 @@ func NewPrivilegeGrantCmd(target string) *cobra.Command { func NewPrivilegeRevokeCmd(target string) *cobra.Command { return &cobra.Command{ - Use: fmt.Sprintf("revoke [%sname] [privilege]...", target), - Short: fmt.Sprintf("Revoke privileges from a %s", target), + Use: fmt.Sprintf("revoke [%sname] [privilege]...", target), + Short: fmt.Sprintf("Revoke privileges from a %s", target), Example: fmt.Sprintf(" vt %s privileges revoke my%s intelligence downloads-tier-2", target, target), - Args: cobra.MinimumNArgs(2), + Args: cobra.MinimumNArgs(2), RunE: func(cmd *cobra.Command, args []string) error { privileges := Privileges{} for _, arg := range args[1:] { diff --git a/cmd/url.go b/cmd/url.go index eacc4c8..ab34c4b 100644 --- a/cmd/url.go +++ b/cmd/url.go @@ -35,7 +35,6 @@ var urlCmdExample = ` vt url https://www.virustotal.com vt url f1177df4692356280844e1d5af67cc4a9eccecf77aa61c229d483b7082c70a8e cat list_of_urls | vt url -` - // Regular expressions used for validating a URL identifier. var urlID = regexp.MustCompile(`[0-9a-fA-F]{64}`) @@ -55,7 +54,7 @@ func NewURLCmd() *cobra.Command { } r := utils.NewMappedStringReader( utils.StringReaderFromCmdArgs(args), - func (url string) string { + func(url string) string { if urlID.MatchString(url) { // The user provided a URL identifier as returned by // VirusTotal's API, which consists in the URL's SHA-256. diff --git a/go.mod b/go.mod index bd19f96..f7157ff 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.22.0 require ( github.com/VirusTotal/vt-go v1.0.1 + github.com/adrg/xdg v0.5.3 github.com/briandowns/spinner v1.23.1 github.com/cavaliergopher/grab/v3 v3.0.1 github.com/dustin/go-humanize v1.0.1 @@ -45,7 +46,7 @@ require ( go.uber.org/atomic v1.9.0 // indirect go.uber.org/multierr v1.9.0 // indirect golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect - golang.org/x/sys v0.18.0 // indirect + golang.org/x/sys v0.26.0 // indirect golang.org/x/term v0.1.0 // indirect golang.org/x/text v0.14.0 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 76f6527..7d43922 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/VirusTotal/vt-go v1.0.1 h1:rj/qugIY8XNC6ogwOaeJAGCOsb3nmY63+yuDMtHOx0Q= github.com/VirusTotal/vt-go v1.0.1/go.mod h1:u1+HeRyl/gQs67eDgVEWNE7+x+zCyXhdtNVrRJR5YPE= +github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= +github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= github.com/briandowns/spinner v1.23.1 h1:t5fDPmScwUjozhDj4FA46p5acZWIPXYE30qW2Ptu650= github.com/briandowns/spinner v1.23.1/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM= github.com/cavaliergopher/grab/v3 v3.0.1 h1:4z7TkBfmPjmLAAmkkAZNX/6QJ1nNFdv3SdIHXju0Fr4= @@ -101,8 +103,8 @@ golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= +golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= diff --git a/utils/filter.go b/utils/filter.go index 7526333..55c73cc 100644 --- a/utils/filter.go +++ b/utils/filter.go @@ -25,19 +25,18 @@ import ( // excluding keys matching any of the patterns in "exclude". The logic for // determining if a key matches the pattern goes as follow: // -// * The path for the key is computed. If the key is in the top-level map its -// path is the key itself, if the key is contained within a nested map its -// path is the concatenation of the parent's path and the key, using a dot (.) -// as a separator. The path for "key" in {a:{b:{key:val}}} is a.b.key. +// - The path for the key is computed. If the key is in the top-level map its +// path is the key itself, if the key is contained within a nested map its +// path is the concatenation of the parent's path and the key, using a dot (.) +// as a separator. The path for "key" in {a:{b:{key:val}}} is a.b.key. // -// * The path is matched against the pattern, which can contain asterisks (*) -// as a placeholder for any character different from a dot (.) and ** as a -// placeholder for any character including a dot. For more information go to: -// https://godoc.org/github.com/gobwas/glob#Compile -// -// * If the path matches any pattern in "include" the key is included in the -// resulting map, as long as it doesn't match a pattern in "exclude". +// - The path is matched against the pattern, which can contain asterisks (*) +// as a placeholder for any character different from a dot (.) and ** as a +// placeholder for any character including a dot. For more information go to: +// https://godoc.org/github.com/gobwas/glob#Compile // +// - If the path matches any pattern in "include" the key is included in the +// resulting map, as long as it doesn't match a pattern in "exclude". func FilterMap(m map[string]interface{}, include, exclude []string) map[string]interface{} { includeGlob := make([]glob.Glob, len(include)) excludeGlob := make([]glob.Glob, len(exclude)) diff --git a/utils/filter_test.go b/utils/filter_test.go index 1cfdb35..0235fc4 100644 --- a/utils/filter_test.go +++ b/utils/filter_test.go @@ -3,7 +3,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -77,9 +77,7 @@ var testCases = []testCase{ include: []string{"foo"}, exclude: []string{"**.quux"}, input: testMap, - output: map[string]interface{}{ - - }, + output: map[string]interface{}{}, }, testCase{ diff --git a/utils/pqueue_test.go b/utils/pqueue_test.go index 2f1b6ed..57e7514 100644 --- a/utils/pqueue_test.go +++ b/utils/pqueue_test.go @@ -3,7 +3,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, diff --git a/yaml/yaml.go b/yaml/yaml.go index 9de45ef..04b5f95 100644 --- a/yaml/yaml.go +++ b/yaml/yaml.go @@ -145,7 +145,7 @@ func (enc *Encoder) encodeMap(m reflect.Value, indent int, prefix string) (err e // If the key is an empty string or starts with some non-letter character // let's enclose the key in double quotes. firstChar, kLen := utf8.DecodeRuneInString(k.String()) - if kLen == 0 || (firstChar != '_' && !unicode.IsLetter(firstChar)) { + if kLen == 0 || (firstChar != '_' && !unicode.IsLetter(firstChar)) { keyPrinter(enc.w, "\"%s\": ", k) } else { keyPrinter(enc.w, "%s: ", k) diff --git a/yaml/yaml_test.go b/yaml/yaml_test.go index 8fc190f..cb5a92f 100644 --- a/yaml/yaml_test.go +++ b/yaml/yaml_test.go @@ -3,7 +3,7 @@ // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // -// http://www.apache.org/licenses/LICENSE-2.0 +// http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, @@ -98,7 +98,7 @@ var tests = []T{ "uno": "1", "dos": "2", "tres": "3", - "": "", + "": "", "#foo": "foo", "|foo": "foo", "_foo": "foo", @@ -180,7 +180,7 @@ var tests = []T{ }, yaml: Y(fmt.Sprintf(` Foo_date: 10000 # %v - `, time.Unix(10000, 0))), + `, time.Unix(10000, 0))), }, { data: struct { @@ -190,7 +190,7 @@ var tests = []T{ }, yaml: Y(fmt.Sprintf(` Bar_date: 10000 # %v - `, time.Unix(10000, 0))), + `, time.Unix(10000, 0))), }, { data: struct { @@ -200,7 +200,7 @@ var tests = []T{ }, yaml: Y(fmt.Sprintf(` Baz_date: 1.618312811e+09 # %v - `, time.Unix(1618312811, 0))), + `, time.Unix(1618312811, 0))), }, }