Initial support for iOS app
This commit is contained in:
parent
2eff8d6b47
commit
1b5be4fc6b
5 changed files with 61 additions and 1 deletions
12
Makefile
12
Makefile
|
@ -25,6 +25,7 @@ help:
|
|||
@echo " make build - Build"
|
||||
@echo " make build-snapshot - Build snapshot"
|
||||
@echo " make build-simple - Build (using go build, without goreleaser)"
|
||||
@echo " make build-simple-darwin - Build (using go build, without goreleaser) on macOS systems"
|
||||
@echo " make clean - Clean build folder"
|
||||
@echo
|
||||
@echo "Releasing (requires goreleaser):"
|
||||
|
@ -114,6 +115,17 @@ build-simple: clean
|
|||
-ldflags \
|
||||
"-linkmode=external -extldflags=-static -s -w -X main.version=$(VERSION) -X main.commit=$(shell git rev-parse --short HEAD) -X main.date=$(shell date +%s)"
|
||||
|
||||
build-simple-darwin: clean
|
||||
mkdir -p dist/ntfy_linux_amd64 server/docs
|
||||
touch server/docs/dummy
|
||||
export CGO_ENABLED=1
|
||||
go build \
|
||||
-o dist/ntfy_linux_amd64/ntfy \
|
||||
-tags sqlite_omit_load_extension,osusergo,netgo \
|
||||
-ldflags \
|
||||
"-linkmode=external -s -w -X main.version=$(VERSION) -X main.commit=$(shell git rev-parse --short HEAD) -X main.date=$(shell date +%s)"
|
||||
|
||||
|
||||
clean: .PHONY
|
||||
rm -rf dist build server/docs
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ Build:
|
|||
make build - Build
|
||||
make build-snapshot - Build snapshot
|
||||
make build-simple - Build (using go build, without goreleaser)
|
||||
make build-simple-darwin - Build (using go build, without goreleaser) on macOS systems
|
||||
make clean - Clean build folder
|
||||
|
||||
Releasing (requires goreleaser):
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
|
||||
const (
|
||||
fcmMessageLimit = 4000
|
||||
fcmApnsBodyMessageLimit = 100
|
||||
)
|
||||
|
||||
// maybeTruncateFCMMessage performs best-effort truncation of FCM messages.
|
||||
|
@ -34,6 +35,14 @@ func maybeTruncateFCMMessage(m *messaging.Message) *messaging.Message {
|
|||
return m
|
||||
}
|
||||
|
||||
func maybeTruncateAPNSBodyMessage(s string) string {
|
||||
if len(s) >= fcmApnsBodyMessageLimit {
|
||||
over := len(s) - fcmApnsBodyMessageLimit + 3 // len("...")
|
||||
return s[:len(s)-over] + "..."
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func createFirebaseSubscriber(credentialsFile string, auther auth.Auther) (subscriber, error) {
|
||||
fb, err := firebase.NewApp(context.Background(), nil, option.WithCredentialsFile(credentialsFile))
|
||||
if err != nil {
|
||||
|
@ -55,6 +64,7 @@ func createFirebaseSubscriber(credentialsFile string, auther auth.Auther) (subsc
|
|||
|
||||
func toFirebaseMessage(m *message, auther auth.Auther) (*messaging.Message, error) {
|
||||
var data map[string]string // Mostly matches https://ntfy.sh/docs/subscribe/api/#json-message-format
|
||||
var apnsConfig *messaging.APNSConfig
|
||||
switch m.Event {
|
||||
case keepaliveEvent, openEvent:
|
||||
data = map[string]string{
|
||||
|
@ -88,6 +98,17 @@ func toFirebaseMessage(m *message, auther auth.Auther) (*messaging.Message, erro
|
|||
data["attachment_expires"] = fmt.Sprintf("%d", m.Attachment.Expires)
|
||||
data["attachment_url"] = m.Attachment.URL
|
||||
}
|
||||
apnsConfig = &messaging.APNSConfig{
|
||||
Payload: &messaging.APNSPayload{
|
||||
Aps: &messaging.Aps{
|
||||
MutableContent: true,
|
||||
Alert: &messaging.ApsAlert{
|
||||
Title: m.Title,
|
||||
Body: maybeTruncateAPNSBodyMessage(m.Message),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
} else {
|
||||
// If anonymous read for a topic is not allowed, we cannot send the message along
|
||||
// via Firebase. Instead, we send a "poll_request" message, asking the client to poll.
|
||||
|
@ -109,5 +130,6 @@ func toFirebaseMessage(m *message, auther auth.Auther) (*messaging.Message, erro
|
|||
Topic: m.Topic,
|
||||
Data: data,
|
||||
Android: androidConfig,
|
||||
APNS: apnsConfig,
|
||||
}), nil
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ func TestToFirebaseMessage_Keepalive(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
require.Equal(t, "mytopic", fbm.Topic)
|
||||
require.Nil(t, fbm.Android)
|
||||
require.Nil(t, fbm.APNS)
|
||||
require.Equal(t, map[string]string{
|
||||
"id": m.ID,
|
||||
"time": fmt.Sprintf("%d", m.Time),
|
||||
|
@ -46,6 +47,7 @@ func TestToFirebaseMessage_Open(t *testing.T) {
|
|||
require.Nil(t, err)
|
||||
require.Equal(t, "mytopic", fbm.Topic)
|
||||
require.Nil(t, fbm.Android)
|
||||
require.Nil(t, fbm.APNS)
|
||||
require.Equal(t, map[string]string{
|
||||
"id": m.ID,
|
||||
"time": fmt.Sprintf("%d", m.Time),
|
||||
|
@ -74,6 +76,17 @@ func TestToFirebaseMessage_Message_Normal_Allowed(t *testing.T) {
|
|||
require.Equal(t, &messaging.AndroidConfig{
|
||||
Priority: "high",
|
||||
}, fbm.Android)
|
||||
require.Equal(t, &messaging.APNSConfig{
|
||||
Payload: &messaging.APNSPayload{
|
||||
Aps: &messaging.Aps{
|
||||
MutableContent: true,
|
||||
Alert: &messaging.ApsAlert{
|
||||
Title: "some title",
|
||||
Body: "this is a message",
|
||||
},
|
||||
},
|
||||
},
|
||||
}, fbm.APNS)
|
||||
require.Equal(t, map[string]string{
|
||||
"id": m.ID,
|
||||
"time": fmt.Sprintf("%d", m.Time),
|
||||
|
@ -102,6 +115,7 @@ func TestToFirebaseMessage_Message_Normal_Not_Allowed(t *testing.T) {
|
|||
require.Equal(t, &messaging.AndroidConfig{
|
||||
Priority: "high",
|
||||
}, fbm.Android)
|
||||
require.Nil(t, fbm.APNS)
|
||||
require.Equal(t, "", fbm.Data["message"])
|
||||
require.Equal(t, "", fbm.Data["priority"])
|
||||
require.Equal(t, map[string]string{
|
||||
|
@ -129,6 +143,17 @@ func TestMaybeTruncateFCMMessage(t *testing.T) {
|
|||
Android: &messaging.AndroidConfig{
|
||||
Priority: "high",
|
||||
},
|
||||
APNS: &messaging.APNSConfig{
|
||||
Payload: &messaging.APNSPayload{
|
||||
Aps: &messaging.Aps{
|
||||
MutableContent: true,
|
||||
Alert: &messaging.ApsAlert{
|
||||
Title: "some title",
|
||||
Body: maybeTruncateAPNSBodyMessage(origMessage),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
origMessageLength := len(origFCMMessage.Data["message"])
|
||||
serializedOrigFCMMessage, _ := json.Marshal(origFCMMessage)
|
||||
|
|
|
@ -156,7 +156,7 @@ func TestServer_StaticSites(t *testing.T) {
|
|||
require.Equal(t, 301, rr.Code)
|
||||
|
||||
rr = request(t, s, "GET", "/docs/", "", nil)
|
||||
require.Equal(t, 200, rr.Code)
|
||||
require.Equal(t, 200, rr.Code) // Test will fail if docs have not yet been built
|
||||
require.Contains(t, rr.Body.String(), `Made with ❤️ by Philipp C. Heckel`)
|
||||
require.Contains(t, rr.Body.String(), `<script src=static/js/extra.js></script>`)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue