diff --git a/template.go b/template.go new file mode 100644 index 0000000..d67d919 --- /dev/null +++ b/template.go @@ -0,0 +1,118 @@ +package main + +import "fmt" + +func truthy(val interface{}) bool { + switch v := val.(type) { + case string: + return v != "" + case bool: + return v + case int: + return v != 0 + } + return false +} + +// Templater for custom emails. +// Variables should be written as {varName}. +// If statements should be written as {if (!)varName}...{endif}. +// Strings are true if != "", ints are true if != 0. +func templateEmail(content string, variables []string, conditionals []string, values map[string]interface{}) string { + ifStart, ifEnd := -1, -1 + ifTrue := false + invalidIf := false + previousEnd := -2 + cStart, cEnd := -1, -1 + varStart, varEnd := -1, -1 + varName := "" + out := "" + for i, c := range content { + if c == '{' { + cStart = i + 1 + for content[cStart] == ' ' { + cStart++ + } + if content[cStart:cStart+3] == "if " { + varStart = cStart + 3 + for content[varStart] == ' ' { + varStart++ + } + } + if ifStart == -1 { + out += content[previousEnd+2 : i] + } + if content[cStart:cStart+5] != "endif" || invalidIf { + continue + } + ifEnd = i - 1 + if ifTrue { + b := templateEmail(content[ifStart:ifEnd+1], variables, conditionals, values) + out += b + ifTrue = false + } + } else if c == '}' { + if varStart != -1 { + ifStart = i + 1 + varEnd = i - 1 + for content[varEnd] == ' ' { + varEnd-- + } + varName = content[varStart : varEnd+1] + positive := true + if varName[0] == '!' { + positive = false + varName = varName[1:] + } + validVar := false + wrappedVarName := "{" + varName + "}" + for _, v := range conditionals { + if v == wrappedVarName { + validVar = true + break + } + } + if validVar { + ifTrue = positive == truthy(values[varName]) + } else { + invalidIf = true + ifStart, ifEnd = -1, -1 + } + varStart, varEnd = -1, -1 + } + cEnd = i - 1 + for content[cEnd] == ' ' { + cEnd-- + } + previousEnd = i - 1 + if content[cEnd-4:cEnd+1] == "endif" && !invalidIf { + continue + } + validVar := false + varName = content[cStart : cEnd+1] + cStart, cEnd = -1, -1 + if ifStart != -1 { + continue + } + wrappedVarName := "{" + varName + "}" + for _, v := range variables { + if v == wrappedVarName { + validVar = true + break + } + } + if !validVar { + out += wrappedVarName + continue + } + out += fmt.Sprint(values[varName]) + } + } + if previousEnd+1 != len(content)-1 { + out += content[previousEnd+2:] + } + if out == "" { + return content + } + return out +}