mirror of https://github.com/jlelse/GoBlog
Support sending notifications to ntfy.sh
This commit is contained in:
parent
4099f6c56c
commit
e994e5400d
|
@ -258,9 +258,15 @@ type configActivityPub struct {
|
|||
}
|
||||
|
||||
type configNotifications struct {
|
||||
Ntfy *configNtfy `mapstructure:"ntfy"`
|
||||
Telegram *configTelegram `mapstructure:"telegram"`
|
||||
}
|
||||
|
||||
type configNtfy struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
Topic string `mapstructure:"topic"`
|
||||
}
|
||||
|
||||
type configTelegram struct {
|
||||
Enabled bool `mapstructure:"enabled"`
|
||||
ChatID string `mapstructure:"chatId"`
|
||||
|
|
|
@ -34,4 +34,10 @@ It is possible to configure multiple compression providers. If one fails, the ne
|
|||
|
||||
GoBlog features a button on each post that allows you to read the post's content aloud. By default, that uses an API from the browser to generate the speech. But it's not available on all browsers and on some operating systems it sounds horrible.
|
||||
|
||||
There's also the possibility to configure GoBlog to use Google Cloud's Text-to-Speech API. For that take a look at the `example-config.yml` file. If configured and enabled, after publishing a post, GoBlog will automatically generate an audio file, save it to the configured media storage (local file storage by default) and safe the audio file URL to the post's `tts` parameter. After updating a post, you can manually regenerate the audio file by using the button on the post. When deleting a post or regenerating the audio, GoBlog tries to delete the old audio file as well.
|
||||
There's also the possibility to configure GoBlog to use Google Cloud's Text-to-Speech API. For that take a look at the `example-config.yml` file. If configured and enabled, after publishing a post, GoBlog will automatically generate an audio file, save it to the configured media storage (local file storage by default) and safe the audio file URL to the post's `tts` parameter. After updating a post, you can manually regenerate the audio file by using the button on the post. When deleting a post or regenerating the audio, GoBlog tries to delete the old audio file as well.
|
||||
|
||||
## Notifications
|
||||
|
||||
On receiving a webmention, a new comment or a contact form submission, GoBlog will create a new notification. Notifications are displayed on `/notifications` and can be deleted by the user.
|
||||
|
||||
If configured, GoBlog will also send a notification using a Telegram Bot or [Ntfy.sh](https://ntfy.sh/). See the `example-config.yml` file for how to configure the notification providers.
|
|
@ -114,8 +114,11 @@ micropub:
|
|||
|
||||
# Notifications
|
||||
notifications:
|
||||
ntfy: # Receive notifications using Ntfy.sh
|
||||
enabled: true # Enable it
|
||||
topic: ntfy.sh/mynotificationstopic # The topic for the notifications
|
||||
telegram: # Receive notifications via Telegram
|
||||
enabled: true
|
||||
enabled: true # Enable it
|
||||
chatId: 123456 # Telegram chat ID (usually the user id on Telegram)
|
||||
botToken: BOT-TOKEN # Telegram bot token
|
||||
|
||||
|
|
|
@ -30,10 +30,12 @@ func (a *goBlog) sendNotification(text string) {
|
|||
if err := a.db.saveNotification(n); err != nil {
|
||||
log.Println("Failed to save notification:", err.Error())
|
||||
}
|
||||
if an := a.cfg.Notifications; an != nil {
|
||||
_, _, err := a.send(an.Telegram, n.Text, "")
|
||||
if err != nil {
|
||||
log.Println("Failed to send Telegram notification:", err.Error())
|
||||
if cfg := a.cfg.Notifications; cfg != nil {
|
||||
if err := a.sendNtfy(cfg.Ntfy, n.Text); err != nil {
|
||||
log.Println("Failed to send notification to Ntfy:", err.Error())
|
||||
}
|
||||
if _, _, err := a.sendTelegram(cfg.Telegram, n.Text, ""); err != nil {
|
||||
log.Println("Failed to send notification to Telegram:", err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/carlmjohnson/requests"
|
||||
)
|
||||
|
||||
func (ntfy *configNtfy) enabled() bool {
|
||||
if ntfy == nil || !ntfy.Enabled || ntfy.Topic == "" {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (a *goBlog) sendNtfy(cfg *configNtfy, msg string) error {
|
||||
if !cfg.enabled() {
|
||||
return nil
|
||||
}
|
||||
return requests.
|
||||
URL(cfg.Topic).
|
||||
Client(a.httpClient).
|
||||
UserAgent(appUserAgent).
|
||||
Post().
|
||||
BodyReader(strings.NewReader(msg)).
|
||||
Fetch(context.Background())
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"io"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_ntfySending(t *testing.T) {
|
||||
fakeClient := newFakeHttpClient()
|
||||
fakeClient.setHandler(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {}))
|
||||
|
||||
app := &goBlog{
|
||||
cfg: createDefaultTestConfig(t),
|
||||
httpClient: fakeClient.Client,
|
||||
}
|
||||
app.cfg.Notifications = &configNotifications{
|
||||
Ntfy: &configNtfy{
|
||||
Enabled: true,
|
||||
Topic: "example.com/topic",
|
||||
},
|
||||
}
|
||||
|
||||
_ = app.initConfig()
|
||||
_ = app.initDatabase(false)
|
||||
app.initComponents(true)
|
||||
|
||||
app.sendNotification("Test notification")
|
||||
|
||||
req := fakeClient.req
|
||||
|
||||
require.NotNil(t, req)
|
||||
assert.Equal(t, http.MethodPost, req.Method)
|
||||
assert.Equal(t, "https://example.com/topic", req.URL.String())
|
||||
|
||||
reqBody, _ := req.GetBody()
|
||||
reqBodyByte, _ := io.ReadAll(reqBody)
|
||||
|
||||
assert.Equal(t, "Test notification", string(reqBodyByte))
|
||||
|
||||
res := fakeClient.res
|
||||
|
||||
require.NotNil(t, res)
|
||||
assert.Equal(t, http.StatusOK, res.StatusCode)
|
||||
}
|
||||
|
||||
func Test_ntfyConfig(t *testing.T) {
|
||||
var cfg *configNtfy
|
||||
|
||||
assert.False(t, cfg.enabled())
|
||||
|
||||
cfg = &configNtfy{}
|
||||
|
||||
assert.False(t, cfg.enabled())
|
||||
|
||||
cfg.Enabled = true
|
||||
|
||||
assert.False(t, cfg.enabled())
|
||||
|
||||
cfg.Topic = "example.com/topic"
|
||||
|
||||
assert.True(t, cfg.enabled())
|
||||
}
|
12
telegram.go
12
telegram.go
|
@ -25,7 +25,7 @@ func (a *goBlog) initTelegram() {
|
|||
return
|
||||
}
|
||||
// Send message
|
||||
chatId, msgId, err := a.send(tg, html, tgbotapi.ModeHTML)
|
||||
chatId, msgId, err := a.sendTelegram(tg, html, tgbotapi.ModeHTML)
|
||||
if err != nil {
|
||||
log.Printf("Failed to send post to Telegram: %v", err)
|
||||
return
|
||||
|
@ -71,7 +71,7 @@ func (a *goBlog) initTelegram() {
|
|||
return
|
||||
}
|
||||
// Send update
|
||||
err = a.update(tg, chatId, messageId, html, "HTML")
|
||||
err = a.updateTelegram(tg, chatId, messageId, html, "HTML")
|
||||
if err != nil {
|
||||
log.Printf("Failed to send update to Telegram: %v", err)
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ func (a *goBlog) initTelegram() {
|
|||
return
|
||||
}
|
||||
// Delete message
|
||||
err = a.delete(tg, chatId, messageId)
|
||||
err = a.deleteTelegram(tg, chatId, messageId)
|
||||
if err != nil {
|
||||
log.Printf("Failed to delete Telegram message: %v", err)
|
||||
}
|
||||
|
@ -134,7 +134,7 @@ func (tg *configTelegram) generateHTML(title, fullURL, shortURL string) string {
|
|||
return message.String()
|
||||
}
|
||||
|
||||
func (a *goBlog) send(tg *configTelegram, message, mode string) (int64, int, error) {
|
||||
func (a *goBlog) sendTelegram(tg *configTelegram, message, mode string) (int64, int, error) {
|
||||
if !tg.enabled() {
|
||||
return 0, 0, nil
|
||||
}
|
||||
|
@ -156,7 +156,7 @@ func (a *goBlog) send(tg *configTelegram, message, mode string) (int64, int, err
|
|||
return res.Chat.ID, res.MessageID, nil
|
||||
}
|
||||
|
||||
func (a *goBlog) update(tg *configTelegram, chatId int64, messageId int, message, mode string) error {
|
||||
func (a *goBlog) updateTelegram(tg *configTelegram, chatId int64, messageId int, message, mode string) error {
|
||||
if !tg.enabled() {
|
||||
return nil
|
||||
}
|
||||
|
@ -189,7 +189,7 @@ func (a *goBlog) update(tg *configTelegram, chatId int64, messageId int, message
|
|||
return err
|
||||
}
|
||||
|
||||
func (a *goBlog) delete(tg *configTelegram, chatId int64, messageId int) error {
|
||||
func (a *goBlog) deleteTelegram(tg *configTelegram, chatId int64, messageId int) error {
|
||||
if !tg.enabled() {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ func Test_configTelegram_send(t *testing.T) {
|
|||
httpClient: fakeClient.Client,
|
||||
}
|
||||
|
||||
chatId, msgId, err := app.send(tg, "Message", "HTML")
|
||||
chatId, msgId, err := app.sendTelegram(tg, "Message", "HTML")
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.Equal(t, 123, msgId)
|
||||
|
|
Loading…
Reference in New Issue