diff --git a/.travis.yml b/.travis.yml index 2b58102..11d3088 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,7 @@ install: - go mod verify script: -- go install ./... +- go test ./... before_deploy: - GIT_TAG=$TRAVIS_TAG make clean build diff --git a/README.md b/README.md index 4299951..190e232 100644 --- a/README.md +++ b/README.md @@ -105,12 +105,13 @@ DESCRIPTION: echo my text | gotify push OPTIONS: - --priority value, -p value Set the priority (default: 0) - --title value, -t value Set the title (empty for app name) - --token value Override the app token - --url value Override the Gotify URL - --quiet, -q Do not output anything (on success) - --contentType value The content type of the message. See https://gotify.net/docs/msgextras#client-display + --priority value, -p value Set the priority (default: 0) + --title value, -t value Set the title (empty for app name) + --token value Override the app token + --url value Override the Gotify URL + --quiet, -q Do not output anything (on success) + --contentType value The content type of the message. See https://gotify.net/docs/msgextras#client-display + --disable-unescape-backslash Disable evaluating \n and \t (if set, \n and \t will be seen as a string) ``` ## Configuration diff --git a/command/push.go b/command/push.go index 6d16403..53d3e14 100644 --- a/command/push.go +++ b/command/push.go @@ -16,6 +16,7 @@ import ( "gopkg.in/urfave/cli.v1" ) + func Push() cli.Command { return cli.Command{ Name: "push", @@ -30,6 +31,7 @@ func Push() cli.Command { cli.StringFlag{Name: "url", Usage: "Override the Gotify URL"}, cli.BoolFlag{Name: "quiet,q", Usage: "Do not output anything (on success)"}, cli.StringFlag{Name: "contentType", Usage: "The content type of the message. See https://gotify.net/docs/msgextras#client-display"}, + cli.BoolFlag{Name: "disable-unescape-backslash", Usage: "Disable evaluating \\n and \\t (if set, \\n and \\t will be seen as a string)"}, }, Action: doPush, } @@ -39,6 +41,9 @@ func doPush(ctx *cli.Context) { conf, confErr := config.ReadConfig(config.GetLocations()) msgText := readMessage(ctx) + if !ctx.Bool("disable-unescape-backslash") { + msgText = utils.Evaluate(msgText) + } priority := ctx.Int("priority") title := ctx.String("title") diff --git a/utils/evaluate.go b/utils/evaluate.go new file mode 100644 index 0000000..e4d2b4f --- /dev/null +++ b/utils/evaluate.go @@ -0,0 +1,34 @@ +package utils + +import ( + "bytes" + "io" +) + +func Evaluate(s string) string { + res := bytes.NewBuffer([]byte{}) + sourceReader := bytes.NewBufferString(s) + for { + r, _, err := sourceReader.ReadRune() + if err == io.EOF { + break + } + if r == '\\' { + nextRune, _, err := sourceReader.ReadRune() + if err == nil { + switch nextRune { + case '\\': + // ignore + case 't': + r = '\t' + case 'n': + r = '\n' + default: + sourceReader.UnreadRune() + } + } + } + res.WriteRune(r) + } + return res.String() +} diff --git a/utils/evaluate_test.go b/utils/evaluate_test.go new file mode 100644 index 0000000..7258bd0 --- /dev/null +++ b/utils/evaluate_test.go @@ -0,0 +1,29 @@ +package utils + +import "testing" + +func TestEvaluate(t *testing.T) { + items := []struct { + str string + expected string + }{ + {str: "test\\ntest", expected: "test\ntest"}, + {str: "test\ntest", expected: "test\ntest"}, + {str: "test\\\\ntest", expected: "test\\ntest"}, + {str: "\\n", expected: "\n"}, + {str: "\\\\n\\n", expected: "\\n\n"}, + {str: "\\n", expected: "\n"}, + {str: "\n", expected: "\n"}, + {str: "\\n\\thi", expected: "\n\thi"}, + {str: "\\n\t\\n\\t\n\n", expected: "\n\t\n\t\n\n"}, + {str: "\\\\n\\\\thallo\\\\t\\\\n", expected: "\\n\\thallo\\t\\n"}, + } + for _, item := range items { + t.Run(item.str, func(t *testing.T) { + eval := Evaluate(item.str) + if eval != item.expected { + t.Fatalf("str '%s' should be evaluated to '%s' but was '%s'.", item.str, item.expected, eval) + } + }) + } +}