func (w *WebhookConfig) Template() (*template.Template, error) {
	template := template.New("webhook").Funcs(template.FuncMap{
		"encode":     func(v interface{}) string { b, _ := json.Marshal(v); return string(b) },
		"rawencode":  func(v interface{}) string { b, _ := json.Marshal(v); return strings.Trim(string(b), `"`) }, // yuck
		"formencode": url.QueryEscape,
		"separator":  separator,
		"humanbytes": humanbytes,
		"nickname":   func() string { return w.Nickname },
		"channel":    func() string { return w.Channel },
		"token":      func() string { return w.Token },
		"timestamp":  func(t time.Time) string { return t.Format(time.RFC3339) },
		"name":       func() string { return w.Name },
	})
	// Figure out which template to use based on URL or template_path.
	switch url := strings.ToLower(w.URL); {
	default:
		fallthrough
	case strings.Contains(url, "discordnotifier.com") || strings.Contains(url, "notifiarr.com"):
		return template.Parse(WebhookTemplateNotifiarr) //nolint:wrapcheck
	case w.TmplPath != "":
		s, err := ioutil.ReadFile(w.TmplPath)
		if err != nil {
			return nil, fmt.Errorf("template file: %w", err)
		}
		return template.Parse(string(s)) //nolint:wrapcheck
	case strings.Contains(url, "discord.com"):
		return template.Parse(WebhookTemplateDiscord) //nolint:wrapcheck
	case strings.Contains(url, "api.telegram.org"):
		return template.Parse(WebhookTemplateTelegram) //nolint:wrapcheck
	case strings.Contains(url, "hooks.slack.com"):
		return template.Parse(WebhookTemplateSlack) //nolint:wrapcheck
	case strings.Contains(url, "pushover.net"):
		return template.Parse(WebhookTemplatePushover)  
	}
}
Template returns a template specific to this webhook.
package unpackerr
import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/url"
	"strings"
	"text/template"
	"time"
	"golift.io/cnfg"
)
type WebhookPayload struct {
	Path  string                 `json:"path"`                 
	App   string                 `json:"app"`                  
	IDs   map[string]interface{} `json:"ids,omitempty"`        
	Event ExtractStatus          `json:"unpackerr_eventtype"`  
	Time  time.Time              `json:"time"`                 
	Data  *XtractPayload         `json:"data,omitempty"`       
	Go       string    `json:"go_version"`  
	OS       string    `json:"os"`          
	Arch     string    `json:"arch"`        
	Version  string    `json:"version"`     
	Revision string    `json:"revision"`    
	Branch   string    `json:"branch"`      
	Started  time.Time `json:"started"`     
}
type XtractPayload struct {
	Error    string        `json:"error,omitempty"`       
	Archives []string      `json:"archives,omitempty"`    
	Files    []string      `json:"files,omitempty"`       
	Start    time.Time     `json:"start,omitempty"`       
	Output   string        `json:"tmp_folder,omitempty"`  
	Bytes    int64         `json:"bytes,omitempty"`       
	Elapsed  cnfg.Duration `json:"elapsed,omitempty"`     
	Queue    int           `json:"queue,omitempty"`       
}
const WebhookTemplateNotifiarr = `{
  "path": {{encode .Path}},
  "app": "{{.App}}",
  "ids": {
    {{$s := separator ",\n"}}{{range $key, $value := .IDs}}{{call $s}}"{{$key}}": {{encode $value}}{{end}}
  },
  "unpackerr_eventtype": "{{.Event}}",
  "time": "{{.Time}}",
{{ if .Data }}    "data": {
    "error": {{encode .Data.Error}},
    "archives": [{{$s := separator ","}}{{range $index, $value := .Data.Archives}}{{call $s}}"{{$value}}"{{end}}],
    "files": [{{$s := separator ","}}{{range $index, $value := .Data.Files}}{{call $s}}"{{$value}}"{{end}}],
    "start": "{{.Data.Start}}",
    "tmp_folder": {{encode .Data.Output}},
    "bytes": "{{.Data.Bytes}}",
    "elapsed": "{{.Data.Elapsed}}"
    },
{{ end }}    "go_version": "{{.Go}}",
  "os": "{{.OS}}",
  "arch": "{{.Arch}}",
  "version": "{{.Version}}",
  "revision": "{{.Revision}}",
  "branch": "{{.Branch}}",
  "started": "{{.Started}}"
}
`
const WebhookTemplateTelegram = `{
  "chat_id": "{{nickname}}",
  "parse_mode": "HTML",
  "text": "<b><a href=\"https://github.com/davidnewhall/unpackerr/releases\">Unpackerr<a>: {{.Event.Desc}}</b>
    \n<b>Title</b>: {{rawencode (index .IDs "title") -}}
    \n<b>App</b>: {{.App -}}
    \n\n<b>Path</b>: <code>{{rawencode .Path}}</code>
  {{ if .Data -}}\n
    {{ if .Data.Elapsed.Duration}}\n <b>Elapsed</b>: {{.Data.Elapsed}}{{end -}}
    {{ if .Data.Archives}}\n <b>Archives</b>: {{len .Data.Archives}}{{end -}}
    {{ if .Data.Files}}\n <b>Files</b>: {{len .Data.Files}}{{end -}}
    {{ if .Data.Bytes}}\n <b>Size</b>: {{humanbytes .Data.Bytes}}{{end -}}
    {{ if and (gt .Event 1) (lt .Event 5)}}\n <b>Queue</b>: {{.Data.Queue}}{{end -}}
    {{ if .Data.Error}}\n\n <b>ERROR</b>: <pre>{{rawencode .Data.Error}}</pre>\n{{end -}}
  {{end -}}"}
`
const WebhookTemplateDiscord = `{
  "username": "{{nickname}}",
  "avatar_url": "https://raw.githubusercontent.com/wiki/davidnewhall/unpackerr/images/logo.png",
  "embeds": [{
    "title": {{encode (index .IDs "title")}},
    "timestamp": "{{timestamp .Time}}",
    "author": {
     "name": "Unpackerr: {{.Event.Desc}}",
     "icon_url": "https://raw.githubusercontent.com/wiki/davidnewhall/unpackerr/images/logo.png",
     "url": "https://github.com/davidnewhall/unpackerr/releases"
    },
    "color": {{ if (eq 1 .Event)}}1752220
            {{- else if (eq 2 .Event)}}16384255
            {{- else if(eq 3 .Event)}}10038562
            {{- else if(eq 4 .Event)}}786176
            {{- else if(eq 5 .Event)}}12745742
            {{- else}}16711695{{end}},
    "fields": [
     {"name": "Path", "value": {{encode .Path}}, "inline": false},
     {"name": "App", "value": "{{.App}}", "inline": true}{{ if .Data }}
     {{ if .Data.Archives}},{"name": "Archives", "value": "{{len .Data.Archives}}", "inline": true}
     {{end -}}
     {{ if .Data.Elapsed.Duration}},{"name": "Elapsed", "value": "{{.Data.Elapsed}}", "inline": true}
     {{end -}}
     {{ if .Data.Files}},{"name": "Files", "value": "{{len .Data.Files}}", "inline": true}
     {{end -}}
     {{ if .Data.Bytes}},{"name": "Size", "value": "{{humanbytes .Data.Bytes}}", "inline": true}
     {{end -}}
     {{ if and (gt .Event 1) (lt .Event 5)}},{"name": "Queue", "value": "{{.Data.Queue}}", "inline": true}
     {{end -}}
     {{ if .Data.Error }},{"name": "Error", "value": {{encode .Data.Error}}, "inline": false}
     {{end}}{{end -}}
    ],
    "footer": {
     "text": "v{{.Version}}-{{.Revision}} ({{.OS}}/{{.Arch}})",
     "icon_url": "https://docs.golift.io/integrations/golift.png"
    }
  }]
}
`
const WebhookTemplatePushover = `token={{token}}&user={{channel}}&html=1&title={{formencode .Event.Desc}}&` +
	`{{if nickname}}device={{nickname}}&{{end}}message=<pre><b>App</b>: {{.App}}
<b>Name</b>: {{formencode (index .IDs "title")}}
<b>Path</b>: {{formencode .Path}}
{{ if .Data -}}
{{ if .Data.Elapsed.Duration}}<b>Time</b>: {{.Data.Elapsed}}
{{end}}{{ if .Data.Archives}}<b>RARs</b>: {{len .Data.Archives}}
{{end}}{{ if .Data.Files}}<b>Files</b>: {{len .Data.Files}}
{{end}}{{ if .Data.Bytes}}<b>Bytes</b>: {{humanbytes .Data.Bytes}}
{{end}}{{ if and (gt .Event 1) (lt .Event 5)}}<b>Queue</b>: {{.Data.Queue}}
{{end}}{{ if .Data.Error}}
<font color="#FF0000"><b>ERROR</b>: {{formencode .Data.Error}}</font>
{{end}}{{end -}}</pre>`
const WebhookTemplateSlack = `
{
  "username": "{{nickname}}",
  {{if channel}}"channel": "{{channel}}",{{end}}
  "icon_url": "https://raw.githubusercontent.com/wiki/davidnewhall/unpackerr/images/logo.png",
  "blocks": [
    {
      "type": "header",
      "text": {
        "type": "plain_text",
        "text": "Unpackerr: {{.Event.Desc}}"
      }
    },
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": {{encode (print ":star: *" (index .IDs "title") "*")}}
      }
    },
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": {{encode (print "*Path*: " .Path)}}
      }
    },
    {
      "type": "section",
      "fields": [
        {
          "type": "mrkdwn",
          "text": "*Version*\nv{{.Version}}-{{.Revision}}"
        },
        {
          "type": "mrkdwn",
          "text": "*OS (Go)*\n{{.OS}} ({{.Arch}}/{{.Go}})"
        },
        {
          "type": "mrkdwn",
          "text": "*App*\n{{.App}}"
        }{{ if .Data }}
        {{ if .Data.Bytes }},{
          "type": "mrkdwn",
          "text": "*Size*\n{{humanbytes .Data.Bytes}}"
        }{{end -}}
        {{ if .Data.Archives }},{
          "type": "mrkdwn",
          "text": "*Archives*\n{{len .Data.Archives}}"
        }{{end -}}
        {{ if .Data.Files }},{
          "type": "mrkdwn",
          "text": "*Files*\n{{len .Data.Files}}"
        }{{end -}}
        {{ if and (gt .Event 1) (lt .Event 5)}},{
          "type": "mrkdwn",
          "text": "*Queue*\n{{.Data.Queue}}"
        }{{end -}}
        {{ if .Data.Elapsed.Duration }},{
          "type": "mrkdwn",
          "text": "*Elapsed*\n{{.Data.Elapsed}}"
        }{{end}}{{end -}}
      ]
    }{{if and (.Data .Data.Error)}},{
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": {{encode (print "*Error*: " .Data.Error)}}
      }
    }{{end}}
  ]
}
`