mirror of
https://github.com/binwiederhier/ntfy.git
synced 2024-11-21 19:03:26 +01:00
Cont'd, getting there
This commit is contained in:
parent
4b9e0c5c38
commit
deb4f24856
3 changed files with 44 additions and 62 deletions
|
@ -2698,19 +2698,25 @@ title `You've Got Mail` to topic `sometopic` (see [ntfy.sh/sometopic](https://nt
|
|||
## Phone calls
|
||||
_Supported on:_ :material-android: :material-apple: :material-firefox:
|
||||
|
||||
You can use ntfy to call a phone and **read the message out loud using text-to-speech**, by specifying a phone number a header.
|
||||
You can use ntfy to call a phone and **read the message out loud using text-to-speech**.
|
||||
Similar to email notifications, this can be useful to blast-notify yourself on all possible channels, or to notify people that do not have
|
||||
the ntfy app installed on their phone.
|
||||
|
||||
Phone numbers have to be previously verified (via the web app). To forward a message as a voice call, pass a phone number
|
||||
in the `X-Call` header (or its alias: `Call`), prefixed with a plus sign and the country code, e.g. `+12223334444`. You may
|
||||
also simply pass `yes` as a value if you only have one verified phone number.
|
||||
**Phone numbers have to be previously verified** (via the web app), so this feature is **only available to authenticated users**.
|
||||
To forward a message as a voice call, pass a phone number in the `X-Call` header (or its alias: `Call`), prefixed with a
|
||||
plus sign and the country code, e.g. `+12223334444`. You may also simply pass `yes` as a value to pick the first of your
|
||||
verified phone numbers.
|
||||
|
||||
!!! info
|
||||
As of today, the text-to-speed voice used will only support English. If there is demand for other languages, we'll
|
||||
be happy to add support for that. Please [open an issue on GitHub](https://github.com/binwiederhier/ntfy/issues).
|
||||
|
||||
On ntfy.sh, this feature is only supported to [ntfy Pro](https://ntfy.sh/app) plans.
|
||||
|
||||
=== "Command line (curl)"
|
||||
```
|
||||
curl \
|
||||
-u :tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2 \
|
||||
-H "Call: +12223334444" \
|
||||
-d "Your garage seems to be on fire. You should probably check that out, and call 0118 999 881 999 119 725 3 for help." \
|
||||
ntfy.sh/alerts
|
||||
|
@ -2719,6 +2725,7 @@ On ntfy.sh, this feature is only supported to [ntfy Pro](https://ntfy.sh/app) pl
|
|||
=== "ntfy CLI"
|
||||
```
|
||||
ntfy publish \
|
||||
--token=tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2 \
|
||||
--call=+12223334444 \
|
||||
alerts "Your garage seems to be on fire. You should probably check that out, and call 0118 999 881 999 119 725 3 for help."
|
||||
```
|
||||
|
@ -2727,6 +2734,7 @@ On ntfy.sh, this feature is only supported to [ntfy Pro](https://ntfy.sh/app) pl
|
|||
``` http
|
||||
POST /alerts HTTP/1.1
|
||||
Host: ntfy.sh
|
||||
Authorization: Bearer tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2
|
||||
Call: +12223334444
|
||||
|
||||
Your garage seems to be on fire. You should probably check that out, and call 0118 999 881 999 119 725 3 for help.
|
||||
|
@ -2738,9 +2746,8 @@ On ntfy.sh, this feature is only supported to [ntfy Pro](https://ntfy.sh/app) pl
|
|||
method: 'POST',
|
||||
body: "Your garage seems to be on fire. You should probably check that out, and call 0118 999 881 999 119 725 3 for help.",
|
||||
headers: {
|
||||
'Email': 'phil@example.com',
|
||||
'Tags': 'warning,skull,backup-host,ssh-login',
|
||||
'Priority': 'high'
|
||||
'Authorization': 'Bearer tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2',
|
||||
'Call': '+12223334444'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
@ -2748,10 +2755,9 @@ On ntfy.sh, this feature is only supported to [ntfy Pro](https://ntfy.sh/app) pl
|
|||
=== "Go"
|
||||
``` go
|
||||
req, _ := http.NewRequest("POST", "https://ntfy.sh/alerts",
|
||||
strings.NewReader("Unknown login from 5.31.23.83 to backups.example.com"))
|
||||
req.Header.Set("Email", "phil@example.com")
|
||||
req.Header.Set("Tags", "warning,skull,backup-host,ssh-login")
|
||||
req.Header.Set("Priority", "high")
|
||||
strings.NewReader("Your garage seems to be on fire. You should probably check that out, and call 0118 999 881 999 119 725 3 for help."))
|
||||
req.Header.Set("Call", "+12223334444")
|
||||
req.Header.Set("Authorization", "Bearer tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2")
|
||||
http.DefaultClient.Do(req)
|
||||
```
|
||||
|
||||
|
@ -2761,12 +2767,10 @@ On ntfy.sh, this feature is only supported to [ntfy Pro](https://ntfy.sh/app) pl
|
|||
Method = "POST"
|
||||
URI = "https://ntfy.sh/alerts"
|
||||
Headers = @{
|
||||
Title = "Low disk space alert"
|
||||
Priority = "high"
|
||||
Tags = "warning,skull,backup-host,ssh-login")
|
||||
Email = "phil@example.com"
|
||||
Authorization = "Bearer tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2"
|
||||
Call = "+12223334444"
|
||||
}
|
||||
Body = "Unknown login from 5.31.23.83 to backups.example.com"
|
||||
Body = "Your garage seems to be on fire. You should probably check that out, and call 0118 999 881 999 119 725 3 for help."
|
||||
}
|
||||
Invoke-RestMethod @Request
|
||||
```
|
||||
|
@ -2774,11 +2778,10 @@ On ntfy.sh, this feature is only supported to [ntfy Pro](https://ntfy.sh/app) pl
|
|||
=== "Python"
|
||||
``` python
|
||||
requests.post("https://ntfy.sh/alerts",
|
||||
data="Unknown login from 5.31.23.83 to backups.example.com",
|
||||
data="Your garage seems to be on fire. You should probably check that out, and call 0118 999 881 999 119 725 3 for help.",
|
||||
headers={
|
||||
"Email": "phil@example.com",
|
||||
"Tags": "warning,skull,backup-host,ssh-login",
|
||||
"Priority": "high"
|
||||
"Authorization": "Bearer tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2",
|
||||
"Call": "+12223334444"
|
||||
})
|
||||
```
|
||||
|
||||
|
@ -2789,21 +2792,13 @@ On ntfy.sh, this feature is only supported to [ntfy Pro](https://ntfy.sh/app) pl
|
|||
'method' => 'POST',
|
||||
'header' =>
|
||||
"Content-Type: text/plain\r\n" .
|
||||
"Email: phil@example.com\r\n" .
|
||||
"Tags: warning,skull,backup-host,ssh-login\r\n" .
|
||||
"Priority: high",
|
||||
'content' => 'Unknown login from 5.31.23.83 to backups.example.com'
|
||||
"Authorization: Bearer tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2\r\n" .
|
||||
"Call: +12223334444",
|
||||
'content' => 'Your garage seems to be on fire. You should probably check that out, and call 0118 999 881 999 119 725 3 for help.'
|
||||
]
|
||||
]));
|
||||
```
|
||||
|
||||
Here's what that looks like in Google Mail:
|
||||
|
||||
<figure markdown>
|
||||
![e-mail notification](static/img/screenshot-email.png){ width=600 }
|
||||
<figcaption>E-mail notification</figcaption>
|
||||
</figure>
|
||||
|
||||
## Authentication
|
||||
Depending on whether the server is configured to support [access control](config.md#access-control), some topics
|
||||
may be read/write protected so that only users with the correct credentials can subscribe or publish to them.
|
||||
|
|
|
@ -15,8 +15,6 @@ var (
|
|||
metricEmailsPublishedFailure prometheus.Counter
|
||||
metricEmailsReceivedSuccess prometheus.Counter
|
||||
metricEmailsReceivedFailure prometheus.Counter
|
||||
metricSMSSentSuccess prometheus.Counter
|
||||
metricSMSSentFailure prometheus.Counter
|
||||
metricCallsMadeSuccess prometheus.Counter
|
||||
metricCallsMadeFailure prometheus.Counter
|
||||
metricUnifiedPushPublishedSuccess prometheus.Counter
|
||||
|
@ -61,12 +59,6 @@ func initMetrics() {
|
|||
metricEmailsReceivedFailure = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "ntfy_emails_received_failure",
|
||||
})
|
||||
metricSMSSentSuccess = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "ntfy_sms_sent_success",
|
||||
})
|
||||
metricSMSSentFailure = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "ntfy_sms_sent_failure",
|
||||
})
|
||||
metricCallsMadeSuccess = prometheus.NewCounter(prometheus.CounterOpts{
|
||||
Name: "ntfy_calls_made_success",
|
||||
})
|
||||
|
@ -111,8 +103,6 @@ func initMetrics() {
|
|||
metricEmailsPublishedFailure,
|
||||
metricEmailsReceivedSuccess,
|
||||
metricEmailsReceivedFailure,
|
||||
metricSMSSentSuccess,
|
||||
metricSMSSentFailure,
|
||||
metricCallsMadeSuccess,
|
||||
metricCallsMadeFailure,
|
||||
metricUnifiedPushPublishedSuccess,
|
||||
|
|
|
@ -15,19 +15,21 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
twilioMessageFooterFormat = "This message was sent by %s via %s"
|
||||
twilioCallEndpoint = "Calls.json"
|
||||
twilioCallFormat = `
|
||||
twilioCallEndpoint = "Calls.json"
|
||||
twilioCallFormat = `
|
||||
<Response>
|
||||
<Pause length="1"/>
|
||||
<Say>You have a message from notify on topic %s. Message:</Say>
|
||||
<Pause length="1"/>
|
||||
<Say>%s</Say>
|
||||
<Pause length="1"/>
|
||||
<Say>End message.</Say>
|
||||
<Pause length="1"/>
|
||||
<Say>%s</Say>
|
||||
<Pause length="1"/>
|
||||
<Say loop="5">
|
||||
You have a notification from notify on topic %s. Message:
|
||||
<break time="1s"/>
|
||||
%s
|
||||
<break time="1s"/>
|
||||
End message.
|
||||
<break time="1s"/>
|
||||
This message was sent by user %s. It will be repeated up to five times.
|
||||
<break time="3s"/>
|
||||
</Say>
|
||||
<Say>Goodbye.</Say>
|
||||
</Response>`
|
||||
)
|
||||
|
||||
|
@ -55,7 +57,11 @@ func (s *Server) convertPhoneNumber(u *user.User, phoneNumber string) (string, *
|
|||
}
|
||||
|
||||
func (s *Server) callPhone(v *visitor, r *http.Request, m *message, to string) {
|
||||
body := fmt.Sprintf(twilioCallFormat, xmlEscapeText(m.Topic), xmlEscapeText(m.Message), xmlEscapeText(s.messageFooter(v.User(), m)))
|
||||
u, sender := v.User(), m.Sender.String()
|
||||
if u != nil {
|
||||
sender = u.Name
|
||||
}
|
||||
body := fmt.Sprintf(twilioCallFormat, xmlEscapeText(m.Topic), xmlEscapeText(m.Message), xmlEscapeText(sender))
|
||||
data := url.Values{}
|
||||
data.Set("From", s.config.TwilioFromNumber)
|
||||
data.Set("To", to)
|
||||
|
@ -186,15 +192,6 @@ func (s *Server) performTwilioMessagingRequestInternal(endpoint string, data url
|
|||
return string(response), nil
|
||||
}
|
||||
|
||||
func (s *Server) messageFooter(u *user.User, m *message) string { // u may be nil!
|
||||
topicURL := s.config.BaseURL + "/" + m.Topic
|
||||
sender := m.Sender.String()
|
||||
if u != nil {
|
||||
sender = fmt.Sprintf("%s (%s)", u.Name, m.Sender)
|
||||
}
|
||||
return fmt.Sprintf(twilioMessageFooterFormat, sender, util.ShortTopicURL(topicURL))
|
||||
}
|
||||
|
||||
func xmlEscapeText(text string) string {
|
||||
var buf bytes.Buffer
|
||||
_ = xml.EscapeText(&buf, []byte(text))
|
||||
|
|
Loading…
Reference in a new issue