Ntfy with custom server and authentication support

This commit is contained in:
Jan-Lukas Else 2022-04-04 13:07:36 +02:00
parent 2a867e7c3f
commit 92172d6404
7 changed files with 88 additions and 33 deletions

View File

@ -336,7 +336,7 @@ func (a *goBlog) apUndelete(p *post) {
// Update "activityPubVersion" parameter to current timestamp in nanoseconds // Update "activityPubVersion" parameter to current timestamp in nanoseconds
p.Parameters[activityPubVersionParam] = []string{fmt.Sprintf("%d", utcNowNanos())} p.Parameters[activityPubVersionParam] = []string{fmt.Sprintf("%d", utcNowNanos())}
a.db.replacePostParam(p.Path, activityPubVersionParam, p.Parameters[activityPubVersionParam]) _ = a.db.replacePostParam(p.Path, activityPubVersionParam, p.Parameters[activityPubVersionParam])
// Post as new post // Post as new post
a.apPost(p) a.apPost(p)
} }

View File

@ -267,6 +267,9 @@ type configNotifications struct {
type configNtfy struct { type configNtfy struct {
Enabled bool `mapstructure:"enabled"` Enabled bool `mapstructure:"enabled"`
Topic string `mapstructure:"topic"` Topic string `mapstructure:"topic"`
Server string `mapstructure:"server"`
User string `mapstructure:"user"`
Pass string `mapstructure:"pass"`
} }
type configTelegram struct { type configTelegram struct {

View File

@ -131,7 +131,10 @@ micropub:
notifications: notifications:
ntfy: # Receive notifications using Ntfy.sh ntfy: # Receive notifications using Ntfy.sh
enabled: true # Enable it enabled: true # Enable it
topic: ntfy.sh/mynotificationstopic # The topic for the notifications topic: mynotificationstopic # The topic for the notifications
server: https://ntfy.sh # The server to use (default is https://ntfy.sh)
user: myusername # The username to use (optional)
password: mypassword # The password to use (optional)
telegram: # Receive notifications via Telegram telegram: # Receive notifications via Telegram
enabled: true # Enable it enabled: true # Enable it
chatId: 123456 # Telegram chat ID (usually the user id on Telegram) chatId: 123456 # Telegram chat ID (usually the user id on Telegram)

6
go.mod
View File

@ -11,7 +11,7 @@ require (
github.com/alecthomas/chroma v0.10.0 github.com/alecthomas/chroma v0.10.0
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de
github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2 github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2
github.com/carlmjohnson/requests v0.22.1 github.com/carlmjohnson/requests v0.22.2
github.com/cretz/bine v0.2.0 github.com/cretz/bine v0.2.0
github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f github.com/dchest/captcha v0.0.0-20200903113550-03f5f0333e1f
github.com/dgraph-io/ristretto v0.1.0 github.com/dgraph-io/ristretto v0.1.0
@ -57,8 +57,8 @@ require (
github.com/yuin/goldmark v1.4.11 github.com/yuin/goldmark v1.4.11
// master // master
github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38 github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38
golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29
golang.org/x/net v0.0.0-20220325170049-de3da57026de golang.org/x/net v0.0.0-20220403103023-749bd193bc2b
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/text v0.3.7 golang.org/x/text v0.3.7
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b

12
go.sum
View File

@ -68,8 +68,8 @@ github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc h1:biVzkmvwrH8
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8= github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2 h1:t8KYCwSKsOEZBFELI4Pn/phbp38iJ1RRAkDFNin1aak= github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2 h1:t8KYCwSKsOEZBFELI4Pn/phbp38iJ1RRAkDFNin1aak=
github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/c2h5oh/datasize v0.0.0-20200825124411-48ed595a09d2/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M=
github.com/carlmjohnson/requests v0.22.1 h1:YoifpEbpJW4LPRX/+0dJe3vTLducEE9Ib10k6lElIUM= github.com/carlmjohnson/requests v0.22.2 h1:hccG5g9ITJlnDip54OVa810AkB366kthFjvA90N4owM=
github.com/carlmjohnson/requests v0.22.1/go.mod h1:Hw4fFOk3xDlHQbNRTGo4oc52TUTpVEq93sNy/H+mrQM= github.com/carlmjohnson/requests v0.22.2/go.mod h1:Hw4fFOk3xDlHQbNRTGo4oc52TUTpVEq93sNy/H+mrQM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
@ -488,8 +488,8 @@ golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWP
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064 h1:S25/rfnfsMVgORT4/J61MJ7rdyseOZOyvLIrZEZ7s6s= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29 h1:tkVvjkPTB7pnW3jnid7kNyAMPVWllTNOf/qKDze4p9o=
golang.org/x/crypto v0.0.0-20220321153916-2c7772ba3064/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220331220935-ae2d96664a29/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@ -575,8 +575,8 @@ golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211020060615-d418f374d309/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220325170049-de3da57026de h1:pZB1TWnKi+o4bENlbzAgLrEbY4RMYmUIRobMcSmfeYc= golang.org/x/net v0.0.0-20220403103023-749bd193bc2b h1:vI32FkLJNAWtGD4BwkThwEy6XS7ZLLMHkSkYfF8M0W0=
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220403103023-749bd193bc2b/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=

19
ntfy.go
View File

@ -19,11 +19,22 @@ func (a *goBlog) sendNtfy(cfg *configNtfy, msg string) error {
if !cfg.enabled() { if !cfg.enabled() {
return nil return nil
} }
return requests. topic := cfg.Topic
URL(cfg.Topic). if strings.HasPrefix(topic, "ntfy.sh/") { // Old configuration example
topic = strings.TrimPrefix(topic, "ntfy.sh/")
}
server := "https://ntfy.sh"
if cfg.Server != "" {
server = cfg.Server
}
builder := requests.
URL(server + "/" + topic).
Client(a.httpClient). Client(a.httpClient).
UserAgent(appUserAgent). UserAgent(appUserAgent).
Method(http.MethodPost). Method(http.MethodPost).
BodyReader(strings.NewReader(msg)). BodyReader(strings.NewReader(msg))
Fetch(context.Background()) if cfg.User != "" {
builder.BasicAuth(cfg.User, cfg.Pass)
}
return builder.Fetch(context.Background())
} }

View File

@ -17,35 +17,73 @@ func Test_ntfySending(t *testing.T) {
cfg: createDefaultTestConfig(t), cfg: createDefaultTestConfig(t),
httpClient: fakeClient.Client, httpClient: fakeClient.Client,
} }
app.cfg.Notifications = &configNotifications{
Ntfy: &configNtfy{
Enabled: true,
Topic: "example.com/topic",
},
}
_ = app.initConfig() _ = app.initConfig()
_ = app.initDatabase(false) _ = app.initDatabase(false)
defer app.db.close() defer app.db.close()
app.initComponents(false) app.initComponents(false)
app.sendNotification("Test notification") t.Run("Default", func(t *testing.T) {
app.cfg.Notifications = &configNotifications{
Ntfy: &configNtfy{
Enabled: true,
Topic: "topic",
},
}
req := fakeClient.req app.sendNotification("Test notification")
require.NotNil(t, req) req := fakeClient.req
assert.Equal(t, http.MethodPost, req.Method)
assert.Equal(t, "https://example.com/topic", req.URL.String())
reqBody, _ := req.GetBody() require.NotNil(t, req)
reqBodyByte, _ := io.ReadAll(reqBody) assert.Equal(t, http.MethodPost, req.Method)
assert.Equal(t, "https://ntfy.sh/topic", req.URL.String())
assert.Equal(t, "Test notification", string(reqBodyByte)) reqBody, _ := req.GetBody()
reqBodyByte, _ := io.ReadAll(reqBody)
res := fakeClient.res assert.Equal(t, "Test notification", string(reqBodyByte))
res := fakeClient.res
require.NotNil(t, res)
assert.Equal(t, http.StatusOK, res.StatusCode)
})
t.Run("Custom server with Basic Auth", func(t *testing.T) {
app.cfg.Notifications = &configNotifications{
Ntfy: &configNtfy{
Enabled: true,
Topic: "topic",
Server: "https://ntfy.example.com",
User: "user",
Pass: "pass",
},
}
app.sendNotification("Test notification")
req := fakeClient.req
require.NotNil(t, req)
assert.Equal(t, http.MethodPost, req.Method)
assert.Equal(t, "https://ntfy.example.com/topic", req.URL.String())
user, pass, _ := req.BasicAuth()
assert.Equal(t, "user", user)
assert.Equal(t, "pass", pass)
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)
})
require.NotNil(t, res)
assert.Equal(t, http.StatusOK, res.StatusCode)
} }
func Test_ntfyConfig(t *testing.T) { func Test_ntfyConfig(t *testing.T) {
@ -61,7 +99,7 @@ func Test_ntfyConfig(t *testing.T) {
assert.False(t, cfg.enabled()) assert.False(t, cfg.enabled())
cfg.Topic = "example.com/topic" cfg.Topic = "topic"
assert.True(t, cfg.enabled()) assert.True(t, cfg.enabled())
} }