forked from mirrors/ntfy
1
0
Fork 0

Compare commits

..

6 Commits

Author SHA1 Message Date
binwiederhier 2697600111 Merge branch 'main' into web-improvements 2023-05-24 22:28:53 -04:00
nimbleghost 025ea3c1d6 Make small code style improvements 2023-05-24 22:18:06 +02:00
nimbleghost be6d962cc3 Fix param reassignment issue 2023-05-24 22:18:06 +02:00
nimbleghost 4a0a22566a Fix jsx key issue 2023-05-24 22:18:06 +02:00
nimbleghost 25d6725d8f Use es6 destructuring swap for shuffling 2023-05-24 22:18:06 +02:00
nimbleghost 1291c3afe9 Make async for loops performant using Promise.all 2023-05-24 22:18:06 +02:00
20 changed files with 56 additions and 308 deletions

View File

@ -1,3 +0,0 @@
dist
*/node_modules
Dockerfile*

1
.gitignore vendored
View File

@ -1,5 +1,4 @@
dist/
dev-dist/
build/
.idea/
.vscode/

View File

@ -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/"

View File

@ -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"]

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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:**

View File

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

View File

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

View File

@ -355,15 +355,5 @@
"account_upgrade_dialog_billing_contact_website": "Otázky týkající se fakturace naleznete na našich <Link>webových stránkách</Link>.",
"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"
}

View File

@ -355,31 +355,5 @@
"account_upgrade_dialog_billing_contact_email": "Para preguntas sobre facturación, por favor <Link>contáctenos</Link> 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"
}

View File

@ -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"
}

View File

@ -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"
}

View File

@ -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 <mdnLink>API de Notificações</mdnLink>.",
"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"
}

View File

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

View File

@ -352,34 +352,5 @@
"account_upgrade_dialog_reservations_warning_other": "Обраний рівень дозволяє менше зарезервованих тем, ніж ваш поточний рівень. Перш ніж змінити свій рівень, <strong>будь ласка, видаліть принаймні {{count}} резервувань</strong>. Ви можете видалити резервування в <Link>Налаштуваннях</Link>.",
"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": "Оплатити зараз і підписатися"
}

View File

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