forked from clem109/drone-wechat
-
Notifications
You must be signed in to change notification settings - Fork 0
/
template.go
137 lines (118 loc) · 3.09 KB
/
template.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package main
import (
"fmt"
"io/ioutil"
"net/http"
"net/url"
"strings"
"time"
"unicode"
"unicode/utf8"
"github.com/aymerick/raymond"
)
func init() {
raymond.RegisterHelpers(funcs)
}
// Render parses and executes a template, returning the results in string format.
func Render(template string, payload interface{}) (s string, err error) {
u, err := url.Parse(template)
if err == nil {
switch u.Scheme {
case "http", "https":
res, err := http.Get(template)
if err != nil {
return s, err
}
defer res.Body.Close()
out, err := ioutil.ReadAll(res.Body)
if err != nil {
return s, err
}
template = string(out)
case "file":
out, err := ioutil.ReadFile(u.Path)
if err != nil {
return s, err
}
template = string(out)
}
}
return raymond.Render(template, payload)
}
// RenderTrim parses and executes a template, returning the results in string
// format. The result is trimmed to remove left and right padding and newlines
// that may be added unintentially in the template markup.
func RenderTrim(template string, playload interface{}) (string, error) {
out, err := Render(template, playload)
return strings.Trim(out, " \n"), err
}
var funcs = map[string]interface{}{
"uppercasefirst": uppercaseFirst,
"uppercase": strings.ToUpper,
"lowercase": strings.ToLower,
"duration": toDuration,
"datetime": toDatetime,
"success": isSuccess,
"failure": isFailure,
"truncate": truncate,
"urlencode": urlencode,
"since": since,
}
func truncate(s string, len int) string {
if utf8.RuneCountInString(s) <= len {
return s
}
runes := []rune(s)
return string(runes[:len])
}
func uppercaseFirst(s string) string {
a := []rune(s)
a[0] = unicode.ToUpper(a[0])
s = string(a)
return s
}
func toDuration(started, finished float64) string {
return fmt.Sprintln(time.Duration(finished-started) * time.Second)
}
func toDatetime(timestamp float64, layout, zone string) string {
if len(zone) == 0 {
return time.Unix(int64(timestamp), 0).Format(layout)
}
loc, err := time.LoadLocation(zone)
if err != nil {
return time.Unix(int64(timestamp), 0).Local().Format(layout)
}
return time.Unix(int64(timestamp), 0).In(loc).Format(layout)
}
func isSuccess(conditional bool, options *raymond.Options) string {
if !conditional {
return options.Inverse()
}
switch options.ParamStr(0) {
case "success":
return options.Fn()
default:
return options.Inverse()
}
}
func isFailure(conditional bool, options *raymond.Options) string {
if !conditional {
return options.Inverse()
}
switch options.ParamStr(0) {
case "failure", "error", "killed":
return options.Fn()
default:
return options.Inverse()
}
}
func urlencode(options *raymond.Options) string {
return url.QueryEscape(options.Fn())
}
func since(start int64) string {
// NOTE: not using `time.Since()` because the fractional second component
// will give us something like "40m12.917523438s" vs "40m12s". We lose
// some precision, but the format is much more readable.
now := time.Unix(time.Now().Unix(), 0)
return fmt.Sprintln(now.Sub(time.Unix(start, 0)))
}