diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 3bf2a12..0000000 --- a/.dockerignore +++ /dev/null @@ -1,3 +0,0 @@ -dist -*/node_modules -Dockerfile* diff --git a/.gitignore b/.gitignore index f695607..b0c2d33 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ dist/ -dev-dist/ build/ .idea/ .vscode/ diff --git a/Dockerfile b/Dockerfile index feb813f..7c2052e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM r.batts.cloud/debian:testing +FROM alpine LABEL org.opencontainers.image.authors="philipp.heckel@gmail.com" LABEL org.opencontainers.image.url="https://ntfy.sh/" diff --git a/Dockerfile-build b/Dockerfile-build deleted file mode 100644 index 9c6d1bc..0000000 --- a/Dockerfile-build +++ /dev/null @@ -1,54 +0,0 @@ -FROM r.batts.cloud/golang:1.19 as builder - -ARG VERSION=dev -ARG COMMIT=unknown - -RUN apt-get update -RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash -RUN apt-get install -y \ - build-essential \ - nodejs \ - python3-pip \ - python3-venv - -WORKDIR /app -ADD Makefile . - -# docs -ADD ./requirements.txt . -RUN make docs-deps -ADD ./mkdocs.yml . -ADD ./docs ./docs -RUN make docs-build - -# web -ADD ./web/package.json ./web/package-lock.json ./web/ -RUN make web-deps -ADD ./web ./web -RUN make web-build - -# cli & server -ADD go.mod go.sum main.go ./ -ADD ./client ./client -ADD ./cmd ./cmd -ADD ./log ./log -ADD ./server ./server -ADD ./user ./user -ADD ./util ./util -RUN make VERSION=$VERSION COMMIT=$COMMIT cli-linux-server - -FROM r.batts.cloud/debian:testing - -LABEL org.opencontainers.image.authors="philipp.heckel@gmail.com" -LABEL org.opencontainers.image.url="https://ntfy.sh/" -LABEL org.opencontainers.image.documentation="https://docs.ntfy.sh/" -LABEL org.opencontainers.image.source="https://github.com/binwiederhier/ntfy" -LABEL org.opencontainers.image.vendor="Philipp C. Heckel" -LABEL org.opencontainers.image.licenses="Apache-2.0, GPL-2.0" -LABEL org.opencontainers.image.title="ntfy" -LABEL org.opencontainers.image.description="Send push notifications to your phone or desktop using PUT/POST" - -COPY --from=builder /app/dist/ntfy_linux_server/ntfy /usr/bin/ntfy - -EXPOSE 80/tcp -ENTRYPOINT ["ntfy"] diff --git a/Makefile b/Makefile index 440bfa6..7398844 100644 --- a/Makefile +++ b/Makefile @@ -31,16 +31,12 @@ help: @echo " make cli-darwin-server - Build client & server (no GoReleaser, current arch, macOS)" @echo " make cli-client - Build client only (no GoReleaser, current arch, Linux/macOS/Windows)" @echo - @echo "Build dev Docker:" - @echo " make docker-dev - Build client & server for current architecture using Docker only" - @echo @echo "Build web app:" @echo " make web - Build the web app" @echo " make web-deps - Install web app dependencies (npm install the universe)" @echo " make web-build - Actually build the web app" - @echo " make web-lint - Run eslint on the web app" - @echo " make web-format - Run prettier on the web app" - @echo " make web-format-check - Run prettier on the web app, but don't change anything" + @echo " make web-format - Run prettier on the web app + @echo " make web-format-check - Run prettier on the web app, but don't change anything @echo @echo "Build documentation:" @echo " make docs - Build the documentation" @@ -86,33 +82,23 @@ build: web docs cli update: web-deps-update cli-deps-update docs-deps-update docker pull alpine -docker-dev: - docker build \ - --file ./Dockerfile-build \ - --tag binwiederhier/ntfy:$(VERSION) \ - --tag binwiederhier/ntfy:dev \ - --build-arg VERSION=$(VERSION) \ - --build-arg COMMIT=$(COMMIT) \ - ./ - # Ubuntu-specific build-deps-ubuntu: - sudo apt-get update - sudo apt-get install -y \ + sudo apt update + sudo apt install -y \ curl \ gcc-aarch64-linux-gnu \ gcc-arm-linux-gnueabi \ jq - which pip3 || sudo apt-get install -y python3-pip + which pip3 || sudo apt install -y python3-pip # Documentation docs: docs-deps docs-build -docs-build: venv .PHONY - @. venv/bin/activate && \ - if ! /bin/echo -e "import sys\nif sys.version_info < (3,8):\n exit(1)" | python3; then \ +docs-build: .PHONY + @if ! /bin/echo -e "import sys\nif sys.version_info < (3,8):\n exit(1)" | python3; then \ if which python3.8; then \ echo "python3.8 $(shell which mkdocs) build"; \ python3.8 $(shell which mkdocs) build; \ @@ -125,15 +111,10 @@ docs-build: venv .PHONY mkdocs build; \ fi -venv: - python3 -m venv ./venv - -docs-deps: venv .PHONY - . venv/bin/activate && \ +docs-deps: .PHONY pip3 install -r requirements.txt -docs-deps-update: venv .PHONY - . venv/bin/activate && \ +docs-deps-update: .PHONY pip3 install -r requirements.txt --upgrade diff --git a/client/client.go b/client/client.go index 93cf7da..b744fa1 100644 --- a/client/client.go +++ b/client/client.go @@ -11,25 +11,23 @@ import ( "heckel.io/ntfy/util" "io" "net/http" - "regexp" "strings" "sync" "time" ) +// Event type constants const ( - // MessageEvent identifies a message event - MessageEvent = "message" + MessageEvent = "message" + KeepaliveEvent = "keepalive" + OpenEvent = "open" + PollRequestEvent = "poll_request" ) const ( maxResponseBytes = 4096 ) -var ( - topicRegex = regexp.MustCompile(`^[-_A-Za-z0-9]{1,64}$`) // Same as in server/server.go -) - // Client is the ntfy client that can be used to publish and subscribe to ntfy topics type Client struct { Messages chan *Message @@ -98,14 +96,8 @@ func (c *Client) Publish(topic, message string, options ...PublishOption) (*Mess // To pass title, priority and tags, check out WithTitle, WithPriority, WithTagsList, WithDelay, WithNoCache, // WithNoFirebase, and the generic WithHeader. func (c *Client) PublishReader(topic string, body io.Reader, options ...PublishOption) (*Message, error) { - topicURL, err := c.expandTopicURL(topic) - if err != nil { - return nil, err - } - req, err := http.NewRequest("POST", topicURL, body) - if err != nil { - return nil, err - } + topicURL := c.expandTopicURL(topic) + req, _ := http.NewRequest("POST", topicURL, body) for _, option := range options { if err := option(req); err != nil { return nil, err @@ -141,14 +133,11 @@ func (c *Client) PublishReader(topic string, body io.Reader, options ...PublishO // By default, all messages will be returned, but you can change this behavior using a SubscribeOption. // See WithSince, WithSinceAll, WithSinceUnixTime, WithScheduled, and the generic WithQueryParam. func (c *Client) Poll(topic string, options ...SubscribeOption) ([]*Message, error) { - topicURL, err := c.expandTopicURL(topic) - if err != nil { - return nil, err - } ctx := context.Background() messages := make([]*Message, 0) msgChan := make(chan *Message) errChan := make(chan error) + topicURL := c.expandTopicURL(topic) log.Debug("%s Polling from topic", util.ShortTopicURL(topicURL)) options = append(options, WithPoll()) go func() { @@ -177,18 +166,15 @@ func (c *Client) Poll(topic string, options ...SubscribeOption) ([]*Message, err // Example: // // c := client.New(client.NewConfig()) -// subscriptionID, _ := c.Subscribe("mytopic") +// subscriptionID := c.Subscribe("mytopic") // for m := range c.Messages { // fmt.Printf("New message: %s", m.Message) // } -func (c *Client) Subscribe(topic string, options ...SubscribeOption) (string, error) { - topicURL, err := c.expandTopicURL(topic) - if err != nil { - return "", err - } +func (c *Client) Subscribe(topic string, options ...SubscribeOption) string { c.mu.Lock() defer c.mu.Unlock() subscriptionID := util.RandomString(10) + topicURL := c.expandTopicURL(topic) log.Debug("%s Subscribing to topic", util.ShortTopicURL(topicURL)) ctx, cancel := context.WithCancel(context.Background()) c.subscriptions[subscriptionID] = &subscription{ @@ -197,7 +183,7 @@ func (c *Client) Subscribe(topic string, options ...SubscribeOption) (string, er cancel: cancel, } go handleSubscribeConnLoop(ctx, c.Messages, topicURL, subscriptionID, options...) - return subscriptionID, nil + return subscriptionID } // Unsubscribe unsubscribes from a topic that has been previously subscribed to using the unique @@ -213,16 +199,31 @@ func (c *Client) Unsubscribe(subscriptionID string) { sub.cancel() } -func (c *Client) expandTopicURL(topic string) (string, error) { +// UnsubscribeAll unsubscribes from a topic that has been previously subscribed with Subscribe. +// If there are multiple subscriptions matching the topic, all of them are unsubscribed from. +// +// A topic can be either a full URL (e.g. https://myhost.lan/mytopic), a short URL which is then prepended https:// +// (e.g. myhost.lan -> https://myhost.lan), or a short name which is expanded using the default host in the +// config (e.g. mytopic -> https://ntfy.sh/mytopic). +func (c *Client) UnsubscribeAll(topic string) { + c.mu.Lock() + defer c.mu.Unlock() + topicURL := c.expandTopicURL(topic) + for _, sub := range c.subscriptions { + if sub.topicURL == topicURL { + delete(c.subscriptions, sub.ID) + sub.cancel() + } + } +} + +func (c *Client) expandTopicURL(topic string) string { if strings.HasPrefix(topic, "http://") || strings.HasPrefix(topic, "https://") { - return topic, nil + return topic } else if strings.Contains(topic, "/") { - return fmt.Sprintf("https://%s", topic), nil + return fmt.Sprintf("https://%s", topic) } - if !topicRegex.MatchString(topic) { - return "", fmt.Errorf("invalid topic name: %s", topic) - } - return fmt.Sprintf("%s/%s", c.config.DefaultHost, topic), nil + return fmt.Sprintf("%s/%s", c.config.DefaultHost, topic) } func handleSubscribeConnLoop(ctx context.Context, msgChan chan *Message, topicURL, subcriptionID string, options ...SubscribeOption) { diff --git a/client/client_test.go b/client/client_test.go index f0b15a3..a71ea5c 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -21,7 +21,7 @@ func TestClient_Publish_Subscribe(t *testing.T) { defer test.StopServer(t, s, port) c := client.New(newTestConfig(port)) - subscriptionID, _ := c.Subscribe("mytopic") + subscriptionID := c.Subscribe("mytopic") time.Sleep(time.Second) msg, err := c.Publish("mytopic", "some message") diff --git a/cmd/subscribe.go b/cmd/subscribe.go index c85c468..2691e6a 100644 --- a/cmd/subscribe.go +++ b/cmd/subscribe.go @@ -72,7 +72,7 @@ ntfy subscribe TOPIC COMMAND $NTFY_TITLE $title, $t Message title $NTFY_PRIORITY $priority, $prio, $p Message priority (1=min, 5=max) $NTFY_TAGS $tags, $tag, $ta Message tags (comma separated list) - $NTFY_RAW $raw Raw JSON message + $NTFY_RAW $raw Raw JSON message Examples: ntfy sub mytopic 'notify-send "$m"' # Execute command for incoming messages @@ -194,10 +194,7 @@ func doSubscribe(c *cli.Context, cl *client.Client, conf *client.Config, topic, topicOptions = append(topicOptions, auth) } - subscriptionID, err := cl.Subscribe(s.Topic, topicOptions...) - if err != nil { - return err - } + subscriptionID := cl.Subscribe(s.Topic, topicOptions...) if s.Command != "" { cmds[subscriptionID] = s.Command } else if conf.DefaultCommand != "" { @@ -207,10 +204,7 @@ func doSubscribe(c *cli.Context, cl *client.Client, conf *client.Config, topic, } } if topic != "" { - subscriptionID, err := cl.Subscribe(topic, options...) - if err != nil { - return err - } + subscriptionID := cl.Subscribe(topic, options...) cmds[subscriptionID] = command } for m := range cl.Messages { diff --git a/docs/develop.md b/docs/develop.md index baab3f3..a53c503 100644 --- a/docs/develop.md +++ b/docs/develop.md @@ -163,15 +163,6 @@ $ make release-snapshot During development, you may want to be more picky and build only certain things. Here are a few examples. -### Build a Docker image only for Linux - -This is useful to test the final build with web app, docs, and server without any dependencies locally - -``` shell -$ make docker-dev -$ docker run --rm -p 80:80 binwiederhier/ntfy:dev serve -``` - ### Build the ntfy binary To build only the `ntfy` binary **without the web app or documentation**, use the `make cli-...` targets: diff --git a/docs/releases.md b/docs/releases.md index 0e93b67..71fceb1 100644 --- a/docs/releases.md +++ b/docs/releases.md @@ -1225,8 +1225,6 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release **Bug fixes:** * Support encoding any header as RFC 2047 ([#737](https://github.com/binwiederhier/ntfy/issues/737), thanks to [@cfouche3005](https://github.com/cfouche3005) for reporting) -* Do not forward poll requests for UnifiedPush messages (no ticket, thanks to NoName for reporting) -* Fix `ntfy pub %` segfaulting ([#760](https://github.com/binwiederhier/ntfy/issues/760), thanks to [@clesmian](https://github.com/clesmian) for reporting) **Maintenance:** diff --git a/server/server.go b/server/server.go index d2fac01..ac54aa5 100644 --- a/server/server.go +++ b/server/server.go @@ -760,7 +760,7 @@ func (s *Server) handlePublishInternal(r *http.Request, v *visitor) (*message, e if s.config.TwilioAccount != "" && call != "" { go s.callPhone(v, r, m, call) } - if s.config.UpstreamBaseURL != "" && !unifiedpush { // UP messages are not sent to upstream + if s.config.UpstreamBaseURL != "" { go s.forwardPollRequest(v, m) } } else { diff --git a/server/server_test.go b/server/server_test.go index d7c4a7c..73df276 100644 --- a/server/server_test.go +++ b/server/server_test.go @@ -2559,29 +2559,6 @@ func TestServer_UpstreamBaseURL_With_Access_Token_Success(t *testing.T) { }) } -func TestServer_UpstreamBaseURL_DoNotForwardUnifiedPush(t *testing.T) { - upstreamServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - t.Fatal("UnifiedPush messages should not be forwarded") - })) - defer upstreamServer.Close() - - c := newTestConfigWithAuthFile(t) - c.BaseURL = "http://myserver.internal" - c.UpstreamBaseURL = upstreamServer.URL - s := newTestServer(t, c) - - // Send UP message, this should not forward to upstream server - response := request(t, s, "PUT", "/mytopic?up=1", `hi there`, nil) - require.Equal(t, 200, response.Code) - m := toMessage(t, response.Body.String()) - require.NotEmpty(t, m.ID) - require.Equal(t, "hi there", m.Message) - - // Forwarding is done asynchronously, so wait a bit. - // This ensures that the t.Fatal above is actually not triggered. - time.Sleep(500 * time.Millisecond) -} - func newTestConfig(t *testing.T) *Config { conf := NewConfig() conf.BaseURL = "http://127.0.0.1:12345" diff --git a/web/public/static/langs/cs.json b/web/public/static/langs/cs.json index 6b967c8..aeff195 100644 --- a/web/public/static/langs/cs.json +++ b/web/public/static/langs/cs.json @@ -355,15 +355,5 @@ "account_upgrade_dialog_billing_contact_website": "Otázky týkající se fakturace naleznete na našich webových stránkách.", "account_upgrade_dialog_tier_features_reservations_one": "{{reservations}} rezervované téma", "account_upgrade_dialog_tier_features_messages_one": "{{messages}} denní zpráva", - "account_upgrade_dialog_tier_features_emails_one": "{{emails}} denní e-mail", - "publish_dialog_call_label": "Telefonát", - "publish_dialog_call_reset": "Odstranit telefonát", - "publish_dialog_chip_call_label": "Telefonát", - "account_basics_phone_numbers_title": "Telefonní čísla", - "account_basics_phone_numbers_dialog_description": "Pro oznámení prostřednictvím tel. hovoru, musíte přidat a ověřit alespoň jedno telefonní číslo. Ověření lze provést pomocí SMS nebo telefonátu.", - "account_basics_phone_numbers_description": "K oznámení telefonátem", - "account_basics_phone_numbers_no_phone_numbers_yet": "Zatím žádná telefonní čísla", - "account_basics_phone_numbers_copied_to_clipboard": "Telefonní číslo zkopírováno do schránky", - "publish_dialog_chip_call_no_verified_numbers_tooltip": "Žádná ověřená telefonní čísla", - "publish_dialog_call_item": "Vytočit číslo {{number}}" + "account_upgrade_dialog_tier_features_emails_one": "{{emails}} denní e-mail" } diff --git a/web/public/static/langs/es.json b/web/public/static/langs/es.json index 62ecdaf..3166a52 100644 --- a/web/public/static/langs/es.json +++ b/web/public/static/langs/es.json @@ -355,31 +355,5 @@ "account_upgrade_dialog_billing_contact_email": "Para preguntas sobre facturación, por favor contáctenos directamente.", "account_upgrade_dialog_tier_features_messages_one": "{{messages}} mensaje diario", "account_upgrade_dialog_tier_features_emails_one": "{{emails}} correo electrónico diario", - "account_upgrade_dialog_tier_features_reservations_one": "{{reservations}} tema reservado", - "publish_dialog_call_label": "Llamada telefónica", - "publish_dialog_call_placeholder": "Número de teléfono al cual llamar con el mensaje, por ejemplo +12223334444, o \"sí\"", - "publish_dialog_chip_call_label": "Llamada telefónica", - "account_basics_phone_numbers_title": "Números de teléfono", - "account_basics_phone_numbers_description": "Para notificaciones por llamada teléfonica", - "account_basics_phone_numbers_no_phone_numbers_yet": "Aún no hay números de teléfono", - "account_basics_phone_numbers_dialog_number_label": "Número de teléfono", - "account_basics_phone_numbers_dialog_number_placeholder": "p. ej. +1222333444", - "account_basics_phone_numbers_dialog_verify_button_sms": "Envía SMS", - "account_basics_phone_numbers_dialog_verify_button_call": "Llámame", - "account_basics_phone_numbers_dialog_code_label": "Código de verificación", - "account_basics_phone_numbers_dialog_channel_sms": "SMS", - "account_basics_phone_numbers_dialog_channel_call": "Llamar", - "account_usage_calls_title": "Llamadas telefónicas realizadas", - "account_usage_calls_none": "No se pueden hacer llamadas telefónicas con esta cuenta", - "account_upgrade_dialog_tier_features_calls_one": "{{llamadas}} llamadas telefónicas diarias", - "account_upgrade_dialog_tier_features_calls_other": "{{llamadas}} llamadas telefónicas diarias", - "account_upgrade_dialog_tier_features_no_calls": "No hay llamadas telefónicas", - "publish_dialog_call_reset": "Eliminar llamada telefónica", - "account_basics_phone_numbers_dialog_description": "Para utilizar la función de notificación de llamadas, tiene que añadir y verificar al menos un número de teléfono. La verificación puede realizarse mediante un SMS o una llamada telefónica.", - "account_basics_phone_numbers_copied_to_clipboard": "Número de teléfono copiado al portapapeles", - "account_basics_phone_numbers_dialog_check_verification_button": "Confirmar código", - "account_basics_phone_numbers_dialog_title": "Agregar número de teléfono", - "account_basics_phone_numbers_dialog_code_placeholder": "p.ej. 123456", - "publish_dialog_call_item": "Llamar al número de teléfono {{number}}", - "publish_dialog_chip_call_no_verified_numbers_tooltip": "No hay números de teléfono verificados" + "account_upgrade_dialog_tier_features_reservations_one": "{{reservations}} tema reservado" } diff --git a/web/public/static/langs/id.json b/web/public/static/langs/id.json index 48fcda0..76c9d1d 100644 --- a/web/public/static/langs/id.json +++ b/web/public/static/langs/id.json @@ -379,7 +379,5 @@ "account_basics_phone_numbers_dialog_channel_sms": "SMS", "account_upgrade_dialog_tier_features_calls_one": "{{calls}} panggilan telepon harian", "account_upgrade_dialog_tier_features_no_calls": "Tidak ada panggilan telepon", - "account_basics_phone_numbers_dialog_code_label": "Kode verifikasi", - "publish_dialog_call_item": "Panggil nomor telepon {{number}}", - "publish_dialog_chip_call_no_verified_numbers_tooltip": "Tidak ada nomor telepon terverifikasi" + "account_basics_phone_numbers_dialog_code_label": "Kode verifikasi" } diff --git a/web/public/static/langs/nl.json b/web/public/static/langs/nl.json index 8ccb629..ca7a2a1 100644 --- a/web/public/static/langs/nl.json +++ b/web/public/static/langs/nl.json @@ -355,30 +355,5 @@ "prefs_reservations_table_topic_header": "Onderwerp", "prefs_reservations_table_access_header": "Toegang", "prefs_reservations_table_everyone_read_write": "Iedereen kan publiceren en abonneren", - "prefs_reservations_table_not_subscribed": "Niet geabonneerd", - "publish_dialog_call_label": "Telefoongesprek", - "publish_dialog_call_reset": "Telefoongesprek verwijderen", - "publish_dialog_chip_call_label": "Telefoongesprek", - "account_basics_phone_numbers_title": "Telefoonnummers", - "account_basics_phone_numbers_description": "Voor meldingen via telefoongesprekken", - "account_basics_phone_numbers_no_phone_numbers_yet": "Nog geen telefoonnummers", - "account_basics_phone_numbers_dialog_verify_button_call": "Bel me", - "account_upgrade_dialog_tier_features_calls_one": "{{calls}} dagelijkse telefoontjes", - "account_basics_phone_numbers_copied_to_clipboard": "Telefoonnummer gekopieerd naar klembord", - "publish_dialog_call_item": "Bel telefoonnummer {{nummer}}", - "account_basics_phone_numbers_dialog_check_verification_button": "Bevestig code", - "publish_dialog_chip_call_no_verified_numbers_tooltip": "Geen geverifieerde telefoonnummers", - "account_basics_phone_numbers_dialog_channel_call": "Telefoongesprek", - "account_basics_phone_numbers_dialog_number_label": "Telefoonnummer", - "account_basics_phone_numbers_dialog_channel_sms": "SMS", - "account_basics_phone_numbers_dialog_code_placeholder": "bijv. 123456", - "account_upgrade_dialog_tier_features_calls_other": "{{calls}} dagelijkse telefoontjes", - "account_upgrade_dialog_tier_features_no_calls": "Geen telefoontjes", - "account_basics_phone_numbers_dialog_description": "Als u de functie voor oproepmeldingen wilt gebruiken, moet u ten minste één telefoonnummer toevoegen en verifiëren. Verificatie kan worden gedaan via sms of een telefoontje.", - "account_basics_phone_numbers_dialog_title": "Telefoonnummer toevoegen", - "account_basics_phone_numbers_dialog_number_placeholder": "bijv. +1222333444", - "account_basics_phone_numbers_dialog_verify_button_sms": "Stuur SMS", - "account_basics_phone_numbers_dialog_code_label": "Verificatiecode", - "account_usage_calls_title": "Aantal telefoontjes", - "account_usage_calls_none": "Met dit account kan niet worden gebeld" + "prefs_reservations_table_not_subscribed": "Niet geabonneerd" } diff --git a/web/public/static/langs/pt.json b/web/public/static/langs/pt.json index 57d5656..bf753c9 100644 --- a/web/public/static/langs/pt.json +++ b/web/public/static/langs/pt.json @@ -214,17 +214,5 @@ "login_link_signup": "Registar", "action_bar_reservation_add": "Reservar tópico", "action_bar_sign_up": "Registar", - "nav_button_account": "Conta", - "common_copy_to_clipboard": "Copiar", - "nav_upgrade_banner_label": "Atualizar para ntfy Pro", - "alert_not_supported_context_description": "Notificações são suportadas apenas sobre HTTPS. Essa é uma limitação da API de Notificações.", - "display_name_dialog_title": "Alterar nome mostrado", - "display_name_dialog_description": "Configura um nome alternativo ao tópico que é mostrado na lista de assinaturas. Isto ajuda a identificar tópicos com nomes complicados mais facilmente.", - "display_name_dialog_placeholder": "Nome exibido", - "reserve_dialog_checkbox_label": "Reservar tópico e configurar acesso", - "publish_dialog_call_label": "Chamada telefônica", - "publish_dialog_call_placeholder": "Número de telefone para ligar com a mensagem, ex: +12223334444, ou 'Sim'", - "publish_dialog_call_reset": "Remover chamada telefônica", - "publish_dialog_chip_call_label": "Chamada telefônica", - "subscribe_dialog_subscribe_button_generate_topic_name": "Gerar nome" + "nav_button_account": "Conta" } diff --git a/web/public/static/langs/sv.json b/web/public/static/langs/sv.json index bc4a540..31e809c 100644 --- a/web/public/static/langs/sv.json +++ b/web/public/static/langs/sv.json @@ -355,30 +355,5 @@ "reservation_delete_dialog_action_keep_title": "Behåll cachade meddelanden och bilagor", "reservation_delete_dialog_action_keep_description": "Meddelanden och bilagor som lagras på servern blir offentligt synliga för personer som känner till ämnesnamnet.", "reservation_delete_dialog_action_delete_title": "Ta bort meddelanden och bilagor som sparats i cacheminnet", - "reservation_delete_dialog_description": "Om du tar bort en reservation ger du upp äganderätten till ämnet och låter andra reservera det. Du kan behålla eller radera befintliga meddelanden och bilagor.", - "publish_dialog_call_label": "Telefonsamtal", - "publish_dialog_call_reset": "Ta bort telefonsamtal", - "publish_dialog_chip_call_label": "Telefonsamtal", - "account_basics_phone_numbers_title": "Telefonnummer", - "account_basics_phone_numbers_description": "För notifieringar via telefonsamtal", - "account_basics_phone_numbers_no_phone_numbers_yet": "Inga telefonnummer ännu", - "account_basics_phone_numbers_copied_to_clipboard": "Telefonnummer kopierat till urklipp", - "account_basics_phone_numbers_dialog_title": "Lägga till telefonnummer", - "account_basics_phone_numbers_dialog_number_label": "Telefonnummer", - "account_basics_phone_numbers_dialog_number_placeholder": "t.ex. +1222333444", - "account_basics_phone_numbers_dialog_verify_button_sms": "Skicka SMS", - "account_basics_phone_numbers_dialog_verify_button_call": "Ring mig", - "account_basics_phone_numbers_dialog_code_label": "Verifieringskod", - "account_basics_phone_numbers_dialog_channel_call": "Ring", - "account_usage_calls_title": "Telefonsamtal som gjorts", - "account_usage_calls_none": "Inga telefonsamtal kan göras med detta konto", - "publish_dialog_call_item": "Ring telefonnummer {{number}}", - "publish_dialog_chip_call_no_verified_numbers_tooltip": "Inga verifierade telefonnummer", - "account_basics_phone_numbers_dialog_description": "För att använda funktionen för samtalsavisering måste du lägga till och verifiera minst ett telefonnummer. Verifieringen kan göras via SMS eller ett telefonsamtal.", - "account_basics_phone_numbers_dialog_code_placeholder": "t.ex. 123456", - "account_basics_phone_numbers_dialog_check_verification_button": "Bekräfta kod", - "account_basics_phone_numbers_dialog_channel_sms": "SMS", - "account_upgrade_dialog_tier_features_calls_other": "{{calls}} dagliga telefonsamtal", - "account_upgrade_dialog_tier_features_no_calls": "Inga telefonsamtal", - "account_upgrade_dialog_tier_features_calls_one": "{{calls}} dagliga telefonsamtal" + "reservation_delete_dialog_description": "Om du tar bort en reservation ger du upp äganderätten till ämnet och låter andra reservera det. Du kan behålla eller radera befintliga meddelanden och bilagor." } diff --git a/web/public/static/langs/uk.json b/web/public/static/langs/uk.json index 32a3079..7d995dd 100644 --- a/web/public/static/langs/uk.json +++ b/web/public/static/langs/uk.json @@ -352,34 +352,5 @@ "account_upgrade_dialog_reservations_warning_other": "Обраний рівень дозволяє менше зарезервованих тем, ніж ваш поточний рівень. Перш ніж змінити свій рівень, будь ласка, видаліть принаймні {{count}} резервувань. Ви можете видалити резервування в Налаштуваннях.", "account_upgrade_dialog_button_cancel": "Скасувати", "account_upgrade_dialog_button_redirect_signup": "Зареєструватися зараз", - "account_upgrade_dialog_button_pay_now": "Оплатити зараз і підписатися", - "prefs_reservations_add_button": "Додати зарезервовану тему", - "prefs_reservations_edit_button": "Редагувати доступ до теми", - "prefs_reservations_limit_reached": "Ви досягли ліміту зарезервованих тем.", - "prefs_reservations_table_click_to_subscribe": "Натисніть, щоб підписатися", - "prefs_reservations_table_topic_header": "Тема", - "prefs_reservations_description": "Тут ви можете зарезервувати назви тем для особистого користування. Резервування теми дає вам право власності на тему і дозволяє визначати права доступу до неї інших користувачів.", - "prefs_reservations_table": "Таблиця зарезервованих тем", - "prefs_reservations_table_access_header": "Доступ", - "prefs_reservations_table_everyone_deny_all": "Тільки я можу публікувати та підписуватись", - "prefs_reservations_table_everyone_read_only": "Я можу публікувати та підписуватись, кожен може підписатися", - "prefs_reservations_table_everyone_write_only": "Я можу публікувати і підписуватися, кожен може публікувати", - "prefs_reservations_table_everyone_read_write": "Кожен може публікувати та підписуватися", - "prefs_reservations_table_not_subscribed": "Не підписаний", - "prefs_reservations_dialog_title_add": "Зарезервувати тему", - "prefs_reservations_dialog_title_edit": "Редагувати зарезервовану тему", - "prefs_reservations_title": "Зарезервовані теми", - "prefs_reservations_delete_button": "Скинути доступ до теми", - "prefs_reservations_dialog_description": "Резервування теми дає вам право власності на цю тему і дозволяє визначати права доступу до неї інших користувачів.", - "prefs_reservations_dialog_topic_label": "Тема", - "prefs_reservations_dialog_access_label": "Доступ", - "reservation_delete_dialog_description": "Видалення резервування позбавляє вас права власності на тему і дозволяє іншим зарезервувати її. Ви можете зберегти або видалити існуючі повідомлення і вкладення.", - "reservation_delete_dialog_submit_button": "Видалити резервування", - "publish_dialog_call_item": "Телефонувати за номером {{номер}}", - "publish_dialog_chip_call_no_verified_numbers_tooltip": "Немає підтверджених номерів телефонів", - "prefs_reservations_dialog_title_delete": "Видалити резервування теми", - "reservation_delete_dialog_action_delete_title": "Видалення кешованих повідомлень і вкладень", - "reservation_delete_dialog_action_keep_title": "Збереження кешованих повідомлень і вкладень", - "reservation_delete_dialog_action_keep_description": "Повідомлення і вкладення, які кешуються на сервері, стають загальнодоступними для людей, які знають назву теми.", - "reservation_delete_dialog_action_delete_description": "Кешовані повідомлення та вкладення будуть видалені назавжди. Ця дія не може бути скасована." + "account_upgrade_dialog_button_pay_now": "Оплатити зараз і підписатися" } diff --git a/web/src/components/hooks.js b/web/src/components/hooks.js index 6b68188..b9c5536 100644 --- a/web/src/components/hooks.js +++ b/web/src/components/hooks.js @@ -47,13 +47,6 @@ export const useConnectionListeners = (account, subscriptions, users) => { const handleMessage = async (subscriptionId, message) => { const subscription = await subscriptionManager.get(subscriptionId); - - // Race condition: sometimes the subscription is already unsubscribed from account - // sync before the message is handled - if (!subscription) { - return; - } - if (subscription.internal) { await handleInternalMessage(message); } else {