0
0
mirror of https://github.com/crazy-max/diun.git synced 2024-12-22 19:38:28 +00:00
crazy-max_diun/vendor/github.com/gregdel/pushover/pushover.go
2024-12-14 22:30:21 +01:00

237 lines
7.0 KiB
Go

// Package pushover provides a wrapper around the Pushover API
package pushover
import (
"encoding/json"
"errors"
"fmt"
"net/http"
"regexp"
)
// Regexp validation.
var tokenRegexp *regexp.Regexp
func init() {
tokenRegexp = regexp.MustCompile(`^[A-Za-z0-9]{30}$`)
}
// APIEndpoint is the API base URL for any request.
var APIEndpoint = "https://api.pushover.net/1"
// Pushover custom errors.
var (
ErrHTTPPushover = errors.New("pushover: http error")
ErrEmptyToken = errors.New("pushover: empty API token")
ErrEmptyURL = errors.New("pushover: empty URL, URLTitle needs an URL")
ErrEmptyRecipientToken = errors.New("pushover: empty recipient token")
ErrInvalidRecipientToken = errors.New("pushover: invalid recipient token")
ErrInvalidHeaders = errors.New("pushover: invalid headers in server response")
ErrInvalidPriority = errors.New("pushover: invalid priority")
ErrInvalidToken = errors.New("pushover: invalid API token")
ErrMessageEmpty = errors.New("pushover: message empty")
ErrMessageTitleTooLong = errors.New("pushover: message title too long")
ErrMessageTooLong = errors.New("pushover: message too long")
ErrMessageAttachmentTooLarge = errors.New("pushover: message attachment is too large")
ErrMessageURLTitleTooLong = errors.New("pushover: message URL title too long")
ErrMessageURLTooLong = errors.New("pushover: message URL too long")
ErrMissingAttachment = errors.New("pushover: missing attachment")
ErrMissingEmergencyParameter = errors.New("pushover: missing emergency parameter")
ErrInvalidDeviceName = errors.New("pushover: invalid device name")
ErrEmptyReceipt = errors.New("pushover: empty receipt")
ErrGlancesMissingData = errors.New("pushover: glance update data missing")
ErrGlancesTitleTooLong = errors.New("pushover: glance title too long")
ErrGlancesTextTooLong = errors.New("pushover: glance text too long")
ErrGlancesSubtextTooLong = errors.New("pushover: glance subtext too long")
ErrGlancesInvalidPercent = errors.New("pushover: glance percent must be in range of 0-100")
)
// API limitations.
const (
// MessageMaxLength is the max message number of characters.
MessageMaxLength = 1024
// MessageTitleMaxLength is the max title number of characters.
MessageTitleMaxLength = 250
// MessageURLMaxLength is the max URL number of characters.
MessageURLMaxLength = 512
// MessageURLTitleMaxLength is the max URL title number of characters.
MessageURLTitleMaxLength = 100
// MessageMaxAttachmentByte is the max attachment size in byte.
MessageMaxAttachmentByte = 2621440
)
// Message priorities
const (
PriorityLowest = -2
PriorityLow = -1
PriorityNormal = 0
PriorityHigh = 1
PriorityEmergency = 2
)
// Sounds
const (
SoundPushover = "pushover"
SoundBike = "bike"
SoundBugle = "bugle"
SoundCashRegister = "cashregister"
SoundClassical = "classical"
SoundCosmic = "cosmic"
SoundFalling = "falling"
SoundGamelan = "gamelan"
SoundIncoming = "incoming"
SoundIntermission = "intermission"
SoundMagic = "magic"
SoundMechanical = "mechanical"
SoundPianobar = "pianobar"
SoundSiren = "siren"
SoundSpaceAlarm = "spacealarm"
SoundTugBoat = "tugboat"
SoundAlien = "alien"
SoundClimb = "climb"
SoundPersistent = "persistent"
SoundEcho = "echo"
SoundUpDown = "updown"
SoundVibrate = "vibrate"
SoundNone = "none"
)
// Pushover is the representation of an app using the pushover API.
type Pushover struct {
token string
}
// New returns a new app to talk to the pushover API.
func New(token string) *Pushover {
return &Pushover{token}
}
// Validate Pushover token.
func (p *Pushover) validate() error {
// Check empty token
if p.token == "" {
return ErrEmptyToken
}
// Check invalid token
if !tokenRegexp.MatchString(p.token) {
return ErrInvalidToken
}
return nil
}
// SendMessage is used to send message to a recipient.
func (p *Pushover) SendMessage(message *Message, recipient *Recipient) (*Response, error) {
// Validate pushover
if err := p.validate(); err != nil {
return nil, err
}
// Validate recipient
if err := recipient.validate(); err != nil {
return nil, err
}
// Validate message
if err := message.validate(); err != nil {
return nil, err
}
return message.send(p.token, recipient.token)
}
// SendGlanceUpdate is used to send glance updates to a recipient.
// It can be used to display widgets on a smart watch
func (p *Pushover) SendGlanceUpdate(msg *Glance, rec *Recipient) (*Response, error) {
// Validate pushover
if err := p.validate(); err != nil {
return nil, err
}
// Validate rec
if err := rec.validate(); err != nil {
return nil, err
}
// Validate msg
if err := msg.validate(); err != nil {
return nil, err
}
return msg.send(p.token, rec.token)
}
// GetReceiptDetails return detailed information about a receipt. This is used
// used to check the acknowledged status of an Emergency notification.
func (p *Pushover) GetReceiptDetails(receipt string) (*ReceiptDetails, error) {
url := fmt.Sprintf("%s/receipts/%s.json?token=%s", APIEndpoint, receipt, p.token)
if receipt == "" {
return nil, ErrEmptyReceipt
}
// Send request
resp, err := http.Get(url)
if err != nil {
return nil, err
}
// Decode the JSON response
var details *ReceiptDetails
if err = json.NewDecoder(resp.Body).Decode(&details); err != nil {
return nil, err
}
return details, nil
}
// GetRecipientDetails allows to check if a recipient exists, if it's a group
// and the devices associated to this recipient. The Errors field of the
// RecipientDetails object will contain an error if the recipient is not valid
// in the Pushover API.
func (p *Pushover) GetRecipientDetails(recipient *Recipient) (*RecipientDetails, error) {
endpoint := fmt.Sprintf("%s/users/validate.json", APIEndpoint)
// Validate pushover
if err := p.validate(); err != nil {
return nil, err
}
// Validate recipient
if err := recipient.validate(); err != nil {
return nil, err
}
req, err := newURLEncodedRequest("POST", endpoint,
map[string]string{"token": p.token, "user": recipient.token})
if err != nil {
return nil, err
}
var response RecipientDetails
if err := do(req, &response, false); err != nil {
return nil, err
}
return &response, nil
}
// CancelEmergencyNotification helps stop a notification retry in case of a
// notification with an Emergency priority before reaching the expiration time.
// It requires the response receipt in order to stop the right notification.
func (p *Pushover) CancelEmergencyNotification(receipt string) (*Response, error) {
endpoint := fmt.Sprintf("%s/receipts/%s/cancel.json", APIEndpoint, receipt)
req, err := newURLEncodedRequest("POST", endpoint, map[string]string{"token": p.token})
if err != nil {
return nil, err
}
response := &Response{}
if err := do(req, response, false); err != nil {
return nil, err
}
return response, nil
}