Cont'd, getting there

This commit is contained in:
binwiederhier 2023-05-15 22:06:43 -04:00
parent 4b9e0c5c38
commit deb4f24856
3 changed files with 44 additions and 62 deletions

View file

@ -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.

View file

@ -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,

View file

@ -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))