From 64fa922ec013079f8f0c90fc9e93c56db3611d30 Mon Sep 17 00:00:00 2001 From: Tulir Asokan Date: Sun, 22 Apr 2018 21:25:06 +0300 Subject: Switch to dep --- vendor/gopkg.in/toast.v1/toast.go | 354 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 354 insertions(+) create mode 100644 vendor/gopkg.in/toast.v1/toast.go (limited to 'vendor/gopkg.in/toast.v1/toast.go') diff --git a/vendor/gopkg.in/toast.v1/toast.go b/vendor/gopkg.in/toast.v1/toast.go new file mode 100644 index 0000000..1782e5e --- /dev/null +++ b/vendor/gopkg.in/toast.v1/toast.go @@ -0,0 +1,354 @@ +package toast + +import ( + "bytes" + "errors" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + "text/template" + + "github.com/nu7hatch/gouuid" +) + +var toastTemplate *template.Template + +var ( + ErrorInvalidAudio error = errors.New("toast: invalid audio") + ErrorInvalidDuration = errors.New("toast: invalid duration") +) + +type toastAudio string + +const ( + Default toastAudio = "ms-winsoundevent:Notification.Default" + IM = "ms-winsoundevent:Notification.IM" + Mail = "ms-winsoundevent:Notification.Mail" + Reminder = "ms-winsoundevent:Notification.Reminder" + SMS = "ms-winsoundevent:Notification.SMS" + LoopingAlarm = "ms-winsoundevent:Notification.Looping.Alarm" + LoopingAlarm2 = "ms-winsoundevent:Notification.Looping.Alarm2" + LoopingAlarm3 = "ms-winsoundevent:Notification.Looping.Alarm3" + LoopingAlarm4 = "ms-winsoundevent:Notification.Looping.Alarm4" + LoopingAlarm5 = "ms-winsoundevent:Notification.Looping.Alarm5" + LoopingAlarm6 = "ms-winsoundevent:Notification.Looping.Alarm6" + LoopingAlarm7 = "ms-winsoundevent:Notification.Looping.Alarm7" + LoopingAlarm8 = "ms-winsoundevent:Notification.Looping.Alarm8" + LoopingAlarm9 = "ms-winsoundevent:Notification.Looping.Alarm9" + LoopingAlarm10 = "ms-winsoundevent:Notification.Looping.Alarm10" + LoopingCall = "ms-winsoundevent:Notification.Looping.Call" + LoopingCall2 = "ms-winsoundevent:Notification.Looping.Call2" + LoopingCall3 = "ms-winsoundevent:Notification.Looping.Call3" + LoopingCall4 = "ms-winsoundevent:Notification.Looping.Call4" + LoopingCall5 = "ms-winsoundevent:Notification.Looping.Call5" + LoopingCall6 = "ms-winsoundevent:Notification.Looping.Call6" + LoopingCall7 = "ms-winsoundevent:Notification.Looping.Call7" + LoopingCall8 = "ms-winsoundevent:Notification.Looping.Call8" + LoopingCall9 = "ms-winsoundevent:Notification.Looping.Call9" + LoopingCall10 = "ms-winsoundevent:Notification.Looping.Call10" + Silent = "silent" +) + +type toastDuration string + +const ( + Short toastDuration = "short" + Long = "long" +) + +func init() { + toastTemplate = template.New("toast") + toastTemplate.Parse(` +[Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null +[Windows.UI.Notifications.ToastNotification, Windows.UI.Notifications, ContentType = WindowsRuntime] | Out-Null +[Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime] | Out-Null + +$APP_ID = '{{if .AppID}}{{.AppID}}{{else}}Windows App{{end}}' + +$template = @" + + + + {{if .Icon}} + + {{end}} + {{if .Title}} + + {{end}} + {{if .Message}} + + {{end}} + + + {{if ne .Audio "silent"}} + +"@ + +$xml = New-Object Windows.Data.Xml.Dom.XmlDocument +$xml.LoadXml($template) +$toast = New-Object Windows.UI.Notifications.ToastNotification $xml +[Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($APP_ID).Show($toast) + `) +} + +// Notification +// +// The toast notification data. The following fields are strongly recommended; +// - AppID +// - Title +// +// If no toastAudio is provided, then the toast notification will be silent. +// You can set the toast to have a default audio by setting "Audio" to "toast.Default", or if your go app takes +// user-provided input for audio, call the "toast.Audio(name)" func. +// +// The AppID is shown beneath the toast message (in certain cases), and above the notification within the Action +// Center - and is used to group your notifications together. It is recommended that you provide a "pretty" +// name for your app, and not something like "com.example.MyApp". +// +// If no Title is provided, but a Message is, the message will display as the toast notification's title - +// which is a slightly different font style (heavier). +// +// The Icon should be an absolute path to the icon (as the toast is invoked from a temporary path on the user's +// system, not the working directory). +// +// If you would like the toast to call an external process/open a webpage, then you can set ActivationArguments +// to the uri you would like to trigger when the toast is clicked. For example: "https://google.com" would open +// the Google homepage when the user clicks the toast notification. +// By default, clicking the toast just hides/dismisses it. +// +// The following would show a notification to the user letting them know they received an email, and opens +// gmail.com when they click the notification. It also makes the Windows 10 "mail" sound effect. +// +// toast := toast.Notification{ +// AppID: "Google Mail", +// Title: email.Subject, +// Message: email.Preview, +// Icon: "C:/Program Files/Google Mail/icons/logo.png", +// ActivationArguments: "https://gmail.com", +// Audio: toast.Mail, +// } +// +// err := toast.Push() +type Notification struct { + // The name of your app. This value shows up in Windows 10's Action Centre, so make it + // something readable for your users. It can contain spaces, however special characters + // (eg. é) are not supported. + AppID string + + // The main title/heading for the toast notification. + Title string + + // The single/multi line message to display for the toast notification. + Message string + + // An optional path to an image on the OS to display to the left of the title & message. + Icon string + + // The type of notification level action (like toast.Action) + ActivationType string + + // The activation/action arguments (invoked when the user clicks the notification) + ActivationArguments string + + // Optional action buttons to display below the notification title & message. + Actions []Action + + // The audio to play when displaying the toast + Audio toastAudio + + // Whether to loop the audio (default false) + Loop bool + + // How long the toast should show up for (short/long) + Duration toastDuration +} + +// Action +// +// Defines an actionable button. +// See https://msdn.microsoft.com/en-us/windows/uwp/controls-and-patterns/tiles-and-notifications-adaptive-interactive-toasts for more info. +// +// Only protocol type action buttons are actually useful, as there's no way of receiving feedback from the +// user's choice. Examples of protocol type action buttons include: "bingmaps:?q=sushi" to open up Windows 10's +// maps app with a pre-populated search field set to "sushi". +// +// toast.Action{"protocol", "Open Maps", "bingmaps:?q=sushi"} +type Action struct { + Type string + Label string + Arguments string +} + +func (n *Notification) applyDefaults() { + if n.ActivationType == "" { + n.ActivationType = "protocol" + } + if n.Duration == "" { + n.Duration = Short + } + if n.Audio == "" { + n.Audio = Default + } +} + +func (n *Notification) buildXML() (string, error) { + var out bytes.Buffer + err := toastTemplate.Execute(&out, n) + if err != nil { + return "", err + } + return out.String(), nil +} + +// Builds the Windows PowerShell script & invokes it, causing the toast to display. +// +// Note: Running the PowerShell script is by far the slowest process here, and can take a few +// seconds in some cases. +// +// notification := toast.Notification{ +// AppID: "Example App", +// Title: "My notification", +// Message: "Some message about how important something is...", +// Icon: "go.png", +// Actions: []toast.Action{ +// {"protocol", "I'm a button", ""}, +// {"protocol", "Me too!", ""}, +// }, +// } +// err := notification.Push() +// if err != nil { +// log.Fatalln(err) +// } +func (n *Notification) Push() error { + n.applyDefaults() + xml, err := n.buildXML() + if err != nil { + return err + } + return invokeTemporaryScript(xml) +} + +// Returns a toastAudio given a user-provided input (useful for cli apps). +// +// If the "name" doesn't match, then the default toastAudio is returned, along with ErrorInvalidAudio. +// +// The following names are valid; +// - default +// - im +// - mail +// - reminder +// - sms +// - loopingalarm +// - loopimgalarm[2-10] +// - loopingcall +// - loopingcall[2-10] +// - silent +// +// Handle the error appropriately according to how your app should work. +func Audio(name string) (toastAudio, error) { + switch strings.ToLower(name) { + case "default": + return Default, nil + case "im": + return IM, nil + case "mail": + return Mail, nil + case "reminder": + return Reminder, nil + case "sms": + return SMS, nil + case "loopingalarm": + return LoopingAlarm, nil + case "loopingalarm2": + return LoopingAlarm2, nil + case "loopingalarm3": + return LoopingAlarm3, nil + case "loopingalarm4": + return LoopingAlarm4, nil + case "loopingalarm5": + return LoopingAlarm5, nil + case "loopingalarm6": + return LoopingAlarm6, nil + case "loopingalarm7": + return LoopingAlarm7, nil + case "loopingalarm8": + return LoopingAlarm8, nil + case "loopingalarm9": + return LoopingAlarm9, nil + case "loopingalarm10": + return LoopingAlarm10, nil + case "loopingcall": + return LoopingCall, nil + case "loopingcall2": + return LoopingCall2, nil + case "loopingcall3": + return LoopingCall3, nil + case "loopingcall4": + return LoopingCall4, nil + case "loopingcall5": + return LoopingCall5, nil + case "loopingcall6": + return LoopingCall6, nil + case "loopingcall7": + return LoopingCall7, nil + case "loopingcall8": + return LoopingCall8, nil + case "loopingcall9": + return LoopingCall9, nil + case "loopingcall10": + return LoopingCall10, nil + case "silent": + return Silent, nil + default: + return Default, ErrorInvalidAudio + } +} + +// Returns a toastDuration given a user-provided input (useful for cli apps). +// +// The default duration is short. If the "name" doesn't match, then the default toastDuration is returned, +// along with ErrorInvalidDuration. Most of the time "short" is the most appropriate for a toast notification, +// and Microsoft recommend not using "long", but it can be useful for important dialogs or looping sound toasts. +// +// The following names are valid; +// - short +// - long +// +// Handle the error appropriately according to how your app should work. +func Duration(name string) (toastDuration, error) { + switch strings.ToLower(name) { + case "short": + return Short, nil + case "long": + return Long, nil + default: + return Short, ErrorInvalidDuration + } +} + +func invokeTemporaryScript(content string) error { + id, _ := uuid.NewV4() + file := filepath.Join(os.TempDir(), id.String()+".ps1") + defer os.Remove(file) + err := ioutil.WriteFile(file, []byte(content), 0600) + if err != nil { + return err + } + if err = exec.Command("PowerShell", "-ExecutionPolicy", "Bypass", "-File", file).Run(); err != nil { + return err + } + return nil +} -- cgit v1.2.3