Merge branch 'main' into webpush-key-file

This commit is contained in:
Philipp C. Heckel
2025-05-21 20:39:12 -04:00
committed by GitHub
40 changed files with 3299 additions and 2356 deletions

View File

@@ -9,7 +9,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v4 uses: actions/setup-go@v4
with: with:
go-version: '1.22.x' go-version: '1.24.x'
- name: Install node - name: Install node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:

View File

@@ -12,7 +12,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v4 uses: actions/setup-go@v4
with: with:
go-version: '1.22.x' go-version: '1.24.x'
- name: Install node - name: Install node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:

View File

@@ -9,7 +9,7 @@ jobs:
- name: Install Go - name: Install Go
uses: actions/setup-go@v4 uses: actions/setup-go@v4
with: with:
go-version: '1.22.x' go-version: '1.24.x'
- name: Install node - name: Install node
uses: actions/setup-node@v3 uses: actions/setup-node@v3
with: with:

View File

@@ -1,4 +1,4 @@
FROM golang:1.22-bullseye as builder FROM golang:1.24-bullseye as builder
ARG VERSION=dev ARG VERSION=dev
ARG COMMIT=unknown ARG COMMIT=unknown
@@ -44,6 +44,8 @@ RUN make VERSION=$VERSION COMMIT=$COMMIT cli-linux-server
FROM alpine FROM alpine
ARG VERSION=dev
LABEL org.opencontainers.image.authors="philipp.heckel@gmail.com" LABEL org.opencontainers.image.authors="philipp.heckel@gmail.com"
LABEL org.opencontainers.image.url="https://ntfy.sh/" LABEL org.opencontainers.image.url="https://ntfy.sh/"
LABEL org.opencontainers.image.documentation="https://docs.ntfy.sh/" LABEL org.opencontainers.image.documentation="https://docs.ntfy.sh/"
@@ -52,6 +54,7 @@ LABEL org.opencontainers.image.vendor="Philipp C. Heckel"
LABEL org.opencontainers.image.licenses="Apache-2.0, GPL-2.0" LABEL org.opencontainers.image.licenses="Apache-2.0, GPL-2.0"
LABEL org.opencontainers.image.title="ntfy" LABEL org.opencontainers.image.title="ntfy"
LABEL org.opencontainers.image.description="Send push notifications to your phone or desktop using PUT/POST" LABEL org.opencontainers.image.description="Send push notifications to your phone or desktop using PUT/POST"
LABEL org.opencontainers.image.version="$VERSION"
COPY --from=builder /app/dist/ntfy_linux_server/ntfy /usr/bin/ntfy COPY --from=builder /app/dist/ntfy_linux_server/ntfy /usr/bin/ntfy

View File

@@ -199,6 +199,16 @@ account costs. Even small donations are very much appreciated. A big fat **Thank
<a href="https://github.com/herzkerl"><img src="https://github.com/herzkerl.png" width="40px" /></a> <a href="https://github.com/herzkerl"><img src="https://github.com/herzkerl.png" width="40px" /></a>
<a href="https://github.com/0x45796164"><img src="https://github.com/0x45796164.png" width="40px" /></a> <a href="https://github.com/0x45796164"><img src="https://github.com/0x45796164.png" width="40px" /></a>
<a href="https://github.com/madchr1st"><img src="https://github.com/madchr1st.png" width="40px" /></a> <a href="https://github.com/madchr1st"><img src="https://github.com/madchr1st.png" width="40px" /></a>
<a href="https://github.com/avalentic"><img src="https://github.com/avalentic.png" width="40px" /></a>
<a href="https://github.com/TheCraiggers"><img src="https://github.com/TheCraiggers.png" width="40px" /></a>
<a href="https://github.com/sheetd"><img src="https://github.com/sheetd.png" width="40px" /></a>
<a href="https://github.com/dlt-green"><img src="https://github.com/dlt-green.png" width="40px" /></a>
<a href="https://github.com/suhlig"><img src="https://github.com/suhlig.png" width="40px" /></a>
<a href="https://github.com/Proximus888"><img src="https://github.com/Proximus888.png" width="40px" /></a>
<a href="https://github.com/wielandp"><img src="https://github.com/wielandp.png" width="40px" /></a>
<a href="https://github.com/chxseh"><img src="https://github.com/chxseh.png" width="40px" /></a>
<a href="https://github.com/user8446"><img src="https://github.com/user8446.png" width="40px" /></a>
<a href="https://github.com/cdf-eagles"><img src="https://github.com/cdf-eagles.png" width="40px" /></a>
I'd also like to thank JetBrains for their awesome [IntelliJ IDEA](https://www.jetbrains.com/idea/), I'd also like to thank JetBrains for their awesome [IntelliJ IDEA](https://www.jetbrains.com/idea/),
and [DigitalOcean](https://m.do.co/c/442b929528db) (*referral link*) for supporting the project: and [DigitalOcean](https://m.do.co/c/442b929528db) (*referral link*) for supporting the project:

View File

@@ -424,9 +424,9 @@ func execServe(c *cli.Context) error {
// Run server // Run server
s, err := server.New(conf) s, err := server.New(conf)
if err != nil { if err != nil {
log.Fatal(err.Error()) log.Fatal("%s", err.Error())
} else if err := s.Run(); err != nil { } else if err := s.Run(); err != nil {
log.Fatal(err.Error()) log.Fatal("%s", err.Error())
} }
log.Info("Exiting.") log.Info("Exiting.")
return nil return nil

View File

@@ -50,6 +50,7 @@ Here are a few working sample configs using a `/etc/ntfy/server.yml` file:
listen-http: ":2586" listen-http: ":2586"
cache-file: "/var/cache/ntfy/cache.db" cache-file: "/var/cache/ntfy/cache.db"
attachment-cache-dir: "/var/cache/ntfy/attachments" attachment-cache-dir: "/var/cache/ntfy/attachments"
behind-proxy: true
``` ```
=== "server.yml (ntfy.sh config)" === "server.yml (ntfy.sh config)"
@@ -631,7 +632,7 @@ or the root domain:
listen 443 ssl http2; listen 443 ssl http2;
server_name ntfy.sh; server_name ntfy.sh;
# See https://ssl-config.mozilla.org/#server=nginx&version=1.18.0&config=intermediate&openssl=1.1.1k&hsts=false&ocsp=false&guideline=5.6see https://ssl-config.mozilla.org/#server=nginx&version=1.18.0&config=intermediate&openssl=1.1.1k&hsts=false&ocsp=false&guideline=5.6 # See https://ssl-config.mozilla.org/#server=nginx&version=1.18.0&config=intermediate&openssl=1.1.1k&hsts=false&ocsp=false&guideline=5.6
ssl_session_timeout 1d; ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off; ssl_session_tickets off;
@@ -698,7 +699,7 @@ or the root domain:
listen 443 ssl http2; listen 443 ssl http2;
server_name ntfy.sh; server_name ntfy.sh;
# See https://ssl-config.mozilla.org/#server=nginx&version=1.18.0&config=intermediate&openssl=1.1.1k&hsts=false&ocsp=false&guideline=5.6see https://ssl-config.mozilla.org/#server=nginx&version=1.18.0&config=intermediate&openssl=1.1.1k&hsts=false&ocsp=false&guideline=5.6 # See https://ssl-config.mozilla.org/#server=nginx&version=1.18.0&config=intermediate&openssl=1.1.1k&hsts=false&ocsp=false&guideline=5.6
ssl_session_timeout 1d; ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m; # about 40000 sessions ssl_session_cache shared:MozSSL:10m; # about 40000 sessions
ssl_session_tickets off; ssl_session_tickets off;
@@ -777,6 +778,7 @@ or the root domain:
``` ```
# Note that this config is most certainly incomplete. Please help out and let me know what's missing # Note that this config is most certainly incomplete. Please help out and let me know what's missing
# via Discord/Matrix or in a GitHub issue. # via Discord/Matrix or in a GitHub issue.
# Note: Caddy automatically handles both HTTP and WebSockets with reverse_proxy
ntfy.sh, http://nfty.sh { ntfy.sh, http://nfty.sh {
reverse_proxy 127.0.0.1:2586 reverse_proxy 127.0.0.1:2586
@@ -864,7 +866,7 @@ it'll show `New message` as a popup.
## Web Push ## Web Push
[Web Push](https://developer.mozilla.org/en-US/docs/Web/API/Push_API) ([RFC8030](https://datatracker.ietf.org/doc/html/rfc8030)) [Web Push](https://developer.mozilla.org/en-US/docs/Web/API/Push_API) ([RFC8030](https://datatracker.ietf.org/doc/html/rfc8030))
allows ntfy to receive push notifications, even when the ntfy web app (or even the browser, depending on the platform) is closed. allows ntfy to receive push notifications, even when the ntfy web app (or even the browser, depending on the platform) is closed.
When enabled, the user can enable **background notifications** for their topics in the wep app under Settings. Once enabled by the When enabled, the user can enable **background notifications** for their topics in the web app under Settings. Once enabled by the
user, ntfy will forward published messages to the push endpoint (browser-provided, e.g. fcm.googleapis.com), which will then user, ntfy will forward published messages to the push endpoint (browser-provided, e.g. fcm.googleapis.com), which will then
forward it to the browser. forward it to the browser.
@@ -1242,6 +1244,10 @@ and [here](https://easyengine.io/tutorials/nginx/block-wp-login-php-bruteforce-a
maxretry = 10 maxretry = 10
``` ```
Note that if you run nginx in a container, append `, chain=DOCKER-USER` to the jail.local action. By default, the jail action chain
is `INPUT`, but `FORWARD` is used when using docker networks. `DOCKER-USER`, available when using docker, is part of the `FORWARD`
chain.
## Health checks ## Health checks
A preliminary health check API endpoint is exposed at `/v1/health`. The endpoint returns a `json` response in the format shown below. A preliminary health check API endpoint is exposed at `/v1/health`. The endpoint returns a `json` response in the format shown below.
If a non-200 HTTP status code is returned or if the returned `healthy` field is `false` the ntfy service should be considered as unhealthy. If a non-200 HTTP status code is returned or if the returned `healthy` field is `false` the ntfy service should be considered as unhealthy.
@@ -1374,10 +1380,10 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
| `listen-unix-mode` | `NTFY_LISTEN_UNIX_MODE` | *file mode* | *system default* | File mode of the Unix socket, e.g. 0700 or 0777 | | `listen-unix-mode` | `NTFY_LISTEN_UNIX_MODE` | *file mode* | *system default* | File mode of the Unix socket, e.g. 0700 or 0777 |
| `key-file` | `NTFY_KEY_FILE` | *filename* | - | HTTPS/TLS private key file, only used if `listen-https` is set. | | `key-file` | `NTFY_KEY_FILE` | *filename* | - | HTTPS/TLS private key file, only used if `listen-https` is set. |
| `cert-file` | `NTFY_CERT_FILE` | *filename* | - | HTTPS/TLS certificate file, only used if `listen-https` is set. | | `cert-file` | `NTFY_CERT_FILE` | *filename* | - | HTTPS/TLS certificate file, only used if `listen-https` is set. |
| `firebase-key-file` | `NTFY_FIREBASE_KEY_FILE` | *filename* | - | If set, also publish messages to a Firebase Cloud Messaging (FCM) topic for your app. This is optional and only required to save battery when using the Android app. See [Firebase (FCM](#firebase-fcm). | | `firebase-key-file` | `NTFY_FIREBASE_KEY_FILE` | *filename* | - | If set, also publish messages to a Firebase Cloud Messaging (FCM) topic for your app. This is optional and only required to save battery when using the Android app. See [Firebase (FCM)](#firebase-fcm). |
| `cache-file` | `NTFY_CACHE_FILE` | *filename* | - | If set, messages are cached in a local SQLite database instead of only in-memory. This allows for service restarts without losing messages in support of the since= parameter. See [message cache](#message-cache). | | `cache-file` | `NTFY_CACHE_FILE` | *filename* | - | If set, messages are cached in a local SQLite database instead of only in-memory. This allows for service restarts without losing messages in support of the since= parameter. See [message cache](#message-cache). |
| `cache-duration` | `NTFY_CACHE_DURATION` | *duration* | 12h | Duration for which messages will be buffered before they are deleted. This is required to support the `since=...` and `poll=1` parameter. Set this to `0` to disable the cache entirely. | | `cache-duration` | `NTFY_CACHE_DURATION` | *duration* | 12h | Duration for which messages will be buffered before they are deleted. This is required to support the `since=...` and `poll=1` parameter. Set this to `0` to disable the cache entirely. |
| `cache-startup-queries` | `NTFY_CACHE_STARTUP_QUERIES` | *string (SQL queries)* | - | SQL queries to run during database startup; this is useful for tuning and [enabling WAL mode](#wal-for-message-cache) | | `cache-startup-queries` | `NTFY_CACHE_STARTUP_QUERIES` | *string (SQL queries)* | - | SQL queries to run during database startup; this is useful for tuning and [enabling WAL mode](#message-cache) |
| `cache-batch-size` | `NTFY_CACHE_BATCH_SIZE` | *int* | 0 | Max size of messages to batch together when writing to message cache (if zero, writes are synchronous) | | `cache-batch-size` | `NTFY_CACHE_BATCH_SIZE` | *int* | 0 | Max size of messages to batch together when writing to message cache (if zero, writes are synchronous) |
| `cache-batch-timeout` | `NTFY_CACHE_BATCH_TIMEOUT` | *duration* | 0s | Timeout for batched async writes to the message cache (if zero, writes are synchronous) | | `cache-batch-timeout` | `NTFY_CACHE_BATCH_TIMEOUT` | *duration* | 0s | Timeout for batched async writes to the message cache (if zero, writes are synchronous) |
| `auth-file` | `NTFY_AUTH_FILE` | *filename* | - | Auth database file used for access control. If set, enables authentication and access control. See [access control](#access-control). | | `auth-file` | `NTFY_AUTH_FILE` | *filename* | - | Auth database file used for access control. If set, enables authentication and access control. See [access control](#access-control). |
@@ -1427,6 +1433,9 @@ variable before running the `ntfy` command (e.g. `export NTFY_LISTEN_HTTP=:80`).
| `web-push-file` | `NTFY_WEB_PUSH_FILE` | *string* | - | Web Push: Database file that stores subscriptions | | `web-push-file` | `NTFY_WEB_PUSH_FILE` | *string* | - | Web Push: Database file that stores subscriptions |
| `web-push-email-address` | `NTFY_WEB_PUSH_EMAIL_ADDRESS` | *string* | - | Web Push: Sender email address | | `web-push-email-address` | `NTFY_WEB_PUSH_EMAIL_ADDRESS` | *string* | - | Web Push: Sender email address |
| `web-push-startup-queries` | `NTFY_WEB_PUSH_STARTUP_QUERIES` | *string* | - | Web Push: SQL queries to run against subscription database at startup | | `web-push-startup-queries` | `NTFY_WEB_PUSH_STARTUP_QUERIES` | *string* | - | Web Push: SQL queries to run against subscription database at startup |
| `log-format` | `NTFY_LOG_FORMAT` | *string* | `text` | Defines the output format, can be text or json |
| `log-file` | `NTFY_LOG_FILE` | *string* | - | Defines the filename to write logs to. If this is not set, ntfy logs to stderr |
| `log-level` | `NTFY_LOG_LEVEL` | *string* | `info` | Defines the default log level, can be one of trace, debug, info, warn or error |
The format for a *duration* is: `<number>(smhd)`, e.g. 30s, 20m, 1h or 3d. The format for a *duration* is: `<number>(smhd)`, e.g. 30s, 20m, 1h or 3d.
The format for a *size* is: `<number>(GMK)`, e.g. 1G, 200M or 4000k. The format for a *size* is: `<number>(GMK)`, e.g. 1G, 200M or 4000k.

View File

@@ -384,7 +384,7 @@ strictly based off of my development on this app. There may be other versions of
### Apple setup ### Apple setup
!!! info !!! info
Along with this step, the [PLIST Deployment](#plist-deployment-and-configuration) step is also required Along with this step, the [PLIST Deployment](#plist-config) step is also required
for these changes to take effect in the iOS app. for these changes to take effect in the iOS app.
1. [Create a new key in Apple Developer Member Center](https://developer.apple.com/account/resources/authkeys/add) 1. [Create a new key in Apple Developer Member Center](https://developer.apple.com/account/resources/authkeys/add)

View File

@@ -31,6 +31,12 @@ GitHub have been hopeless. In case it ever becomes available, I want to know imm
*/6 * * * * if curl -s https://api.github.com/users/ntfy | grep "Not Found"; then curl -d "github.com/ntfy is available" -H "Tags: tada" -H "Prio: high" ntfy.sh/my-alerts; fi */6 * * * * if curl -s https://api.github.com/users/ntfy | grep "Not Found"; then curl -d "github.com/ntfy is available" -H "Tags: tada" -H "Prio: high" ntfy.sh/my-alerts; fi
``` ```
You can also use [`ntfy-run`](https://github.com/quantum5/ntfy-run) to send the output of your cronjob in the
notification, so that you know exactly why it failed:
```
0 0 * * * ntfy-run -n https://ntfy.sh/backups --success-priority low --failure-tags warning ~/backup-computer
```
## Low disk space alerts ## Low disk space alerts
Here's a simple cronjob that I use to alert me when the disk space on the root disk is running low. It's simple, but Here's a simple cronjob that I use to alert me when the disk space on the root disk is running low. It's simple, but
@@ -161,7 +167,6 @@ services:
watchtower: watchtower:
image: containrrr/watchtower image: containrrr/watchtower
environment: environment:
- WATCHTOWER_NOTIFICATIONS=shoutrrr
- WATCHTOWER_NOTIFICATION_SKIP_TITLE=True - WATCHTOWER_NOTIFICATION_SKIP_TITLE=True
- WATCHTOWER_NOTIFICATION_URL=ntfy://ntfy.sh/my_watchtower_topic?title=WatchtowerUpdates - WATCHTOWER_NOTIFICATION_URL=ntfy://ntfy.sh/my_watchtower_topic?title=WatchtowerUpdates
``` ```
@@ -173,7 +178,14 @@ Or, if you only want to send notifications using shoutrrr:
shoutrrr send -u "ntfy://ntfy.sh/my_watchtower_topic?title=WatchtowerUpdates" -m "testMessage" shoutrrr send -u "ntfy://ntfy.sh/my_watchtower_topic?title=WatchtowerUpdates" -m "testMessage"
``` ```
Authentication tokens are also supported via the generic webhook and authorization header using this url format (replace the domain, topic and token with your own): Authentication tokens are also supported:
- (Recommended) Ntfy url format (replace the domain, topic and token with your own):
```
ntfy://:TOKEN@DOMAIN/TOPIC
```
- Generic webhook and authorization header using this url format (replace the domain, topic and token with your own):
``` ```
generic+https://DOMAIN/TOPIC?@authorization=Bearer+TOKEN` generic+https://DOMAIN/TOPIC?@authorization=Bearer+TOKEN`
@@ -628,3 +640,56 @@ or by simply providing traccar with a valid username/password combination.
<entry key='sms.http.user'>phil</entry> <entry key='sms.http.user'>phil</entry>
<entry key='sms.http.password'>mypass</entry> <entry key='sms.http.password'>mypass</entry>
``` ```
## Terminal Notifications for Long-Running Commands
This example provides a simple way to send notifications using [ntfy.sh](https://ntfy.sh) when a terminal command completes. It includes success or failure indicators based on the command's exit status.
Store your ntfy.sh bearer token securely if access control is enabled:
```sh
echo "your_bearer_token_here" > ~/.ntfy_token
chmod 600 ~/.ntfy_token
```
Add the following function and alias to your `.bashrc` or `.bash_profile`:
```sh
# Function for alert notifications using ntfy.sh
notify_via_ntfy() {
local exit_status=$? # Capture the exit status before doing anything else
local token=$(< ~/.ntfy_token) # Securely read the token
local status_icon="$([ $exit_status -eq 0 ] && echo magic_wand || echo warning)"
local last_command=$(history | tail -n1 | sed -e 's/^[[:space:]]*[0-9]\{1,\}[[:space:]]*//' -e 's/[;&|][[:space:]]*alert$//')
curl -s -X POST "https://n.example.dev/alerts" \
-H "Authorization: Bearer $token" \
-H "Title: Terminal" \
-H "X-Priority: 3" \
-H "Tags: $status_icon" \
-d "Command: $last_command (Exit: $exit_status)"
echo "Tags: $status_icon"
echo "$last_command (Exit: $exit_status)"
}
# Add an "alert" alias for long running commands using ntfy.sh
alias alert='notify_via_ntfy'
```
Now you can run any long-running command and append `alert` to notify when it completes:
```sh
sleep 10; alert
```
![ntfy notifications on mobile device](static/img/mobile-screenshot-notification.png)
**Notification Sent** with a success 🪄 (`magic_wand`) or failure ⚠️ (`warning`) tag.
To test failure notifications:
```sh
false; alert # Always fails (exit 1)
ls --invalid; alert # Invalid option
cat nonexistent_file; alert # File not found
```

View File

@@ -7,7 +7,7 @@ or POST requests. I use it to notify myself when scripts fail, or long-running c
<a href="https://f-droid.org/en/packages/io.heckel.ntfy/"><img src="static/img/badge-fdroid.png"></a> <a href="https://f-droid.org/en/packages/io.heckel.ntfy/"><img src="static/img/badge-fdroid.png"></a>
<a href="https://apps.apple.com/us/app/ntfy/id1625396347"><img src="static/img/badge-appstore.png"></a> <a href="https://apps.apple.com/us/app/ntfy/id1625396347"><img src="static/img/badge-appstore.png"></a>
To [receive notifications on your phone](subscribe/phone.md), install the app, either via Google Play or F-Droid. To [receive notifications on your phone](subscribe/phone.md), install the app, either via Google Play, App Store or F-Droid.
Once installed, open it and subscribe to a topic of your choosing. Topics don't have to explicitly be created, so just Once installed, open it and subscribe to a topic of your choosing. Topics don't have to explicitly be created, so just
pick a name and use it later when you [publish a message](publish.md). Note that **topic names are public, so it's wise pick a name and use it later when you [publish a message](publish.md). Note that **topic names are public, so it's wise
to choose something that cannot be guessed easily.** to choose something that cannot be guessed easily.**

View File

@@ -540,7 +540,7 @@ kubectl apply -k /ntfy
cpu: 150m cpu: 150m
memory: 150Mi memory: 150Mi
volumeMounts: volumeMounts:
- mountPath: /etc/ntfy/server.yml - mountPath: /etc/ntfy
subPath: server.yml subPath: server.yml
name: config-volume # generated vie configMapGenerator from kustomization file name: config-volume # generated vie configMapGenerator from kustomization file
- mountPath: /var/cache/ntfy - mountPath: /var/cache/ntfy

View File

@@ -4,6 +4,16 @@ There are quite a few projects that work with ntfy, integrate ntfy, or have been
I've added a ⭐ to projects or posts that have a significant following, or had a lot of interaction by the community. I've added a ⭐ to projects or posts that have a significant following, or had a lot of interaction by the community.
## Table of Contents
- [Official integrations](#official-integrations)
- [Integration via HTTP/SMTP/etc.](#integration-via-httpsmtpetc)
- [UnifiedPush integrations](#unifiedpush-integrations)
- [Libraries](#libraries)
- [CLIs + GUIs](#clis--guis)
- [Projects + scripts](#projects--scripts)
- [Blog + forum posts](#blog--forum-posts)
- [Alternative ntfy servers](#alternative-ntfy-servers)
## Official integrations ## Official integrations
- [changedetection.io](https://changedetection.io) ⭐ - Website change detection and notification - [changedetection.io](https://changedetection.io) ⭐ - Website change detection and notification
@@ -26,6 +36,8 @@ I've added a ⭐ to projects or posts that have a significant following, or had
- [Cloudron](https://www.cloudron.io/store/sh.ntfy.cloudronapp.html) - Platform that makes it easy to manage web apps on your server - [Cloudron](https://www.cloudron.io/store/sh.ntfy.cloudronapp.html) - Platform that makes it easy to manage web apps on your server
- [Xitoring](https://xitoring.com/docs/notifications/notification-roles/ntfy/) - Server and Uptime monitoring - [Xitoring](https://xitoring.com/docs/notifications/notification-roles/ntfy/) - Server and Uptime monitoring
- [HetrixTools](https://docs.hetrixtools.com/ntfy-sh-notifications/) - Uptime monitoring - [HetrixTools](https://docs.hetrixtools.com/ntfy-sh-notifications/) - Uptime monitoring
- [EasyMorph](https://help.easymorph.com/doku.php?id=transformations:sendntfymessage) - Visual data transformation and automation tool
- [Monibot](https://monibot.io/) - Monibot monitors your websites, servers and applications and notifies you if something goes wrong.
## Integration via HTTP/SMTP/etc. ## Integration via HTTP/SMTP/etc.
@@ -35,6 +47,8 @@ I've added a ⭐ to projects or posts that have a significant following, or had
- [Tautulli](https://github.com/Tautulli/Tautulli) ⭐ - Monitoring and tracking tool for Plex (integration [via webhook](https://github.com/Tautulli/Tautulli/wiki/Notification-Agents-Guide#webhook)) - [Tautulli](https://github.com/Tautulli/Tautulli) ⭐ - Monitoring and tracking tool for Plex (integration [via webhook](https://github.com/Tautulli/Tautulli/wiki/Notification-Agents-Guide#webhook))
- [Mailrise](https://github.com/YoRyan/mailrise) - An SMTP gateway (integration via [Apprise](https://github.com/caronc/apprise/wiki/Notify_ntfy)) - [Mailrise](https://github.com/YoRyan/mailrise) - An SMTP gateway (integration via [Apprise](https://github.com/caronc/apprise/wiki/Notify_ntfy))
- [Proxmox-Ntfy](https://github.com/qtsone/proxmox-ntfy) - Python script that monitors Proxmox tasks and sends notifications using the Ntfy service. - [Proxmox-Ntfy](https://github.com/qtsone/proxmox-ntfy) - Python script that monitors Proxmox tasks and sends notifications using the Ntfy service.
- [Scrutiny](https://github.com/AnalogJ/scrutiny) - WebUI for smartd S.M.A.R.T monitoring. Scrutiny includes shoutrrr/ntfy integration ([see integration README](https://github.com/AnalogJ/scrutiny?tab=readme-ov-file#notifications))
- [UptimeObserver](https://uptimeobserver.com) - Uptime Monitoring tool for Websites, APIs, SSL Certificates, DNS, Domain Names and Ports. [Integration Guide](https://support.uptimeobserver.com/integrations/ntfy/)
## [UnifiedPush](https://unifiedpush.org/users/apps/) integrations ## [UnifiedPush](https://unifiedpush.org/users/apps/) integrations
@@ -72,6 +86,9 @@ I've added a ⭐ to projects or posts that have a significant following, or had
- [ntfysh-windows](https://github.com/lucas-bortoli/ntfysh-windows) - A ntfy client for Windows Desktop - [ntfysh-windows](https://github.com/lucas-bortoli/ntfysh-windows) - A ntfy client for Windows Desktop
- [ntfyr](https://github.com/haxwithaxe/ntfyr) - A simple commandline tool to send notifications to ntfy - [ntfyr](https://github.com/haxwithaxe/ntfyr) - A simple commandline tool to send notifications to ntfy
- [ntfy.py](https://github.com/ioqy/ntfy-client-python) - ntfy.py is a simple nfty.sh client for sending notifications - [ntfy.py](https://github.com/ioqy/ntfy-client-python) - ntfy.py is a simple nfty.sh client for sending notifications
- [wlzntfy](https://github.com/Walzen-Group/ntfy-toaster) - A minimalistic, receive-only toast notification client for Windows 11
- [Ntfy_CSV_Reminders](https://github.com/thiswillbeyourgithub/Ntfy_CSV_Reminders) - A Python tool that sends random-timing phone notifications for recurring tasks by using daily probability checks based on CSV-defined frequencies.
- [Daily Fact Ntfy](https://github.com/thiswillbeyourgithub/Daily_Fact_Ntfy) - Generate [llm](https://github.com/simonw/llm) generated fact every day about any topic you're interested in.
## Projects + scripts ## Projects + scripts
@@ -80,6 +97,7 @@ I've added a ⭐ to projects or posts that have a significant following, or had
- [Grafana-to-ntfy](https://gitlab.com/Saibe1111/grafana-to-ntfy) - Grafana-to-ntfy alerts channel (Node Js) - [Grafana-to-ntfy](https://gitlab.com/Saibe1111/grafana-to-ntfy) - Grafana-to-ntfy alerts channel (Node Js)
- [ntfy-long-zsh-command](https://github.com/robfox92/ntfy-long-zsh-command) - Notifies you once a long-running command completes (zsh) - [ntfy-long-zsh-command](https://github.com/robfox92/ntfy-long-zsh-command) - Notifies you once a long-running command completes (zsh)
- [ntfy-shellscripts](https://github.com/nickexyz/ntfy-shellscripts) - A few scripts for the ntfy project (Shell) - [ntfy-shellscripts](https://github.com/nickexyz/ntfy-shellscripts) - A few scripts for the ntfy project (Shell)
- [alertmanager-ntfy-relay](https://github.com/therobbielee/alertmanager-ntfy-relay) - ntfy.sh relay for Alertmanager (Go)
- [QuickStatus](https://github.com/corneliusroot/QuickStatus) - A shell script to alert to any immediate problems upon login (Shell) - [QuickStatus](https://github.com/corneliusroot/QuickStatus) - A shell script to alert to any immediate problems upon login (Shell)
- [ntfy.el](https://github.com/shombando/ntfy) - Send notifications from Emacs (Emacs) - [ntfy.el](https://github.com/shombando/ntfy) - Send notifications from Emacs (Emacs)
- [backup-projects](https://gist.github.com/anthonyaxenov/826ba65abbabd5b00196bc3e6af76002) - Stupidly simple backup script for own projects (Shell) - [backup-projects](https://gist.github.com/anthonyaxenov/826ba65abbabd5b00196bc3e6af76002) - Stupidly simple backup script for own projects (Shell)
@@ -127,7 +145,7 @@ I've added a ⭐ to projects or posts that have a significant following, or had
- [ntfyd](https://github.com/joachimschmidt557/ntfyd) - ntfy desktop daemon (Zig) - [ntfyd](https://github.com/joachimschmidt557/ntfyd) - ntfy desktop daemon (Zig)
- [ntfy-browser](https://github.com/johman10/ntfy-browser) - browser extension to receive notifications without having the page open (TypeScript) - [ntfy-browser](https://github.com/johman10/ntfy-browser) - browser extension to receive notifications without having the page open (TypeScript)
- [ntfy-electron](https://github.com/xdpirate/ntfy-electron) - Electron wrapper for the ntfy web app (JS) - [ntfy-electron](https://github.com/xdpirate/ntfy-electron) - Electron wrapper for the ntfy web app (JS)
- [systemd-ntfy-poweronoff](https://github.com/stendler/systemd-ntfy-poweronoff) - Systemd services to send notifications on system startup and shutdown (Go) - [systemd-ntfy-poweronoff](https://github.com/stendler/systemd-ntfy-poweronoff) - Systemd services to send notifications on system startup, shutdown and service failure
- [msgdrop](https://github.com/jbrubake/msgdrop) - Send and receive encrypted messages (Bash) - [msgdrop](https://github.com/jbrubake/msgdrop) - Send and receive encrypted messages (Bash)
- [vigilant](https://github.com/VerifiedJoseph/vigilant) - Monitor RSS/ATOM and JSON feeds, and send push notifications on new entries (PHP) - [vigilant](https://github.com/VerifiedJoseph/vigilant) - Monitor RSS/ATOM and JSON feeds, and send push notifications on new entries (PHP)
- [ansible-role-ntfy-alertmanager](https://github.com/bleetube/ansible-role-ntfy-alertmanager) - Ansible role to install xenrox/ntfy-alertmanager - [ansible-role-ntfy-alertmanager](https://github.com/bleetube/ansible-role-ntfy-alertmanager) - Ansible role to install xenrox/ntfy-alertmanager
@@ -142,6 +160,12 @@ I've added a ⭐ to projects or posts that have a significant following, or had
- [Notify](https://flathub.org/apps/com.ranfdev.Notify) - Native GTK4 client for ntfy (Rust) - [Notify](https://flathub.org/apps/com.ranfdev.Notify) - Native GTK4 client for ntfy (Rust)
- [notify-via-ntfy](https://exchange.checkmk.com/p/notify-via-ntfy) - Checkmk plugin to send notifications via ntfy (Python) - [notify-via-ntfy](https://exchange.checkmk.com/p/notify-via-ntfy) - Checkmk plugin to send notifications via ntfy (Python)
- [ntfy-java](https://github.com/MaheshBabu11/ntfy-java/) - A Java package to interact with a ntfy server (Java) - [ntfy-java](https://github.com/MaheshBabu11/ntfy-java/) - A Java package to interact with a ntfy server (Java)
- [container-update-check](https://github.com/stendler/container-update-check) - Scripts to check and notify if a podman or docker container image can be updated (Podman/Shell)
- [ignition-combustion-template](https://github.com/stendler/ignition-combustion-template) - Templates and scripts to generate a configuration to automatically setup a system on first boot. Including systemd-ntfy-poweronoff (Shell)
- [ntfy-run](https://github.com/quantum5/ntfy-run) - Tool to run a command, capture its output, and send it to ntfy (Rust)
- [Clipboard IO](https://github.com/jim3692/clipboard-io) - End to end encrypted clipboard
- [ntfy-me-mcp](https://github.com/gitmotion/ntfy-me-mcp) - An ntfy MCP server for sending/fetching ntfy notifications to your self-hosted ntfy server from AI Agents (supports secure token auth & more - use with npx or docker!) (Node/Typescript)
- [InvaderInformant](https://github.com/patricksthannon/InvaderInformant) - Script for Mac OS systems that monitors new or dropped connections to your network using ntfy (Shell)
## Blog + forum posts ## Blog + forum posts
@@ -242,6 +266,7 @@ I've added a ⭐ to projects or posts that have a significant following, or had
- [ntfy otro sistema de notificaciones pub-sub simple basado en HTTP](https://ugeek.github.io/blog/post/2021-11-05-ntfy-sh-otro-sistema-de-notificaciones-pub-sub-simple-basado-en-http.html) - ugeek.github.io - 11/2021 - [ntfy otro sistema de notificaciones pub-sub simple basado en HTTP](https://ugeek.github.io/blog/post/2021-11-05-ntfy-sh-otro-sistema-de-notificaciones-pub-sub-simple-basado-en-http.html) - ugeek.github.io - 11/2021
- [Show HN: A tool to send push notifications to your phone, written in Go](https://news.ycombinator.com/item?id=29715464) ⭐ - news.ycombinator.com - 12/2021 - [Show HN: A tool to send push notifications to your phone, written in Go](https://news.ycombinator.com/item?id=29715464) ⭐ - news.ycombinator.com - 12/2021
- [Reddit selfhostable post](https://www.reddit.com/r/selfhosted/comments/qxlsm9/my_open_source_notification_android_app_and/) ⭐ - reddit.com - 11/2021 - [Reddit selfhostable post](https://www.reddit.com/r/selfhosted/comments/qxlsm9/my_open_source_notification_android_app_and/) ⭐ - reddit.com - 11/2021
- [ntfy on The Canary in the Cage Podcast](https://odysee.com/@TheCanaryInTheCage:b/The-Canary-in-the-Cage-Episode-42:1?r=4gitYjTacQqPEjf22874USecDQYJ5y5E&t=3062) - odysee.com - 1/2025
## Alternative ntfy servers ## Alternative ntfy servers

View File

@@ -837,8 +837,7 @@ Here are a few examples (assuming today's date is **12/10/2021, 9am, Eastern Tim
_Supported on:_ :material-android: :material-apple: :material-firefox: _Supported on:_ :material-android: :material-apple: :material-firefox:
In addition to using PUT/POST, you can also send to topics via simple HTTP GET requests. This makes it easy to use In addition to using PUT/POST, you can also send to topics via simple HTTP GET requests. This makes it easy to use
a ntfy topic as a [webhook](https://en.wikipedia.org/wiki/Webhook), or if your client has limited HTTP support (e.g. a ntfy topic as a [webhook](https://en.wikipedia.org/wiki/Webhook), or if your client has limited HTTP support.
like the [MacroDroid](https://play.google.com/store/apps/details?id=com.arlosoft.macrodroid) Android app).
To send messages via HTTP GET, simply call the `/publish` endpoint (or its aliases `/send` and `/trigger`). Without To send messages via HTTP GET, simply call the `/publish` endpoint (or its aliases `/send` and `/trigger`). Without
any arguments, this will send the message `triggered` to the topic. However, you can provide all arguments that are any arguments, this will send the message `triggered` to the topic. However, you can provide all arguments that are
@@ -1008,7 +1007,7 @@ Here's an **easier example with a shorter JSON payload**:
=== "Command line (curl)" === "Command line (curl)"
``` ```
# To use { and } in the URL without encoding, we need to turn of # To use { and } in the URL without encoding, we need to turn off
# curl's globbing using --globoff # curl's globbing using --globoff
curl \ curl \
@@ -1244,7 +1243,7 @@ all the supported fields:
| `priority` | - | *int (one of: 1, 2, 3, 4, or 5)* | `4` | Message [priority](#message-priority) with 1=min, 3=default and 5=max | | `priority` | - | *int (one of: 1, 2, 3, 4, or 5)* | `4` | Message [priority](#message-priority) with 1=min, 3=default and 5=max |
| `actions` | - | *JSON array* | *(see [action buttons](#action-buttons))* | Custom [user action buttons](#action-buttons) for notifications | | `actions` | - | *JSON array* | *(see [action buttons](#action-buttons))* | Custom [user action buttons](#action-buttons) for notifications |
| `click` | - | *URL* | `https://example.com` | Website opened when notification is [clicked](#click-action) | | `click` | - | *URL* | `https://example.com` | Website opened when notification is [clicked](#click-action) |
| `attach` | - | *URL* | `https://example.com/file.jpg` | URL of an attachment, see [attach via URL](#attach-file-from-url) | | `attach` | - | *URL* | `https://example.com/file.jpg` | URL of an attachment, see [attach via URL](#attach-file-from-a-url) |
| `markdown` | - | *bool* | `true` | Set to true if the `message` is Markdown-formatted | | `markdown` | - | *bool* | `true` | Set to true if the `message` is Markdown-formatted |
| `icon` | - | *string* | `https://example.com/icon.png` | URL to use as notification [icon](#icons) | | `icon` | - | *string* | `https://example.com/icon.png` | URL to use as notification [icon](#icons) |
| `filename` | - | *string* | `file.jpg` | File name of the attachment | | `filename` | - | *string* | `file.jpg` | File name of the attachment |
@@ -2942,11 +2941,17 @@ format is:
ntfy-$topic@ntfy.sh ntfy-$topic@ntfy.sh
``` ```
If [access control](config.md#access-control) is enabled, and the target topic does not support anonymous writes, e-mail publishing won't work without providing an authorized access token. That will change the format of the e-mail's recipient address to If [access control](config.md#access-control) is enabled, and the target topic does not support anonymous writes, e-mail publishing won't work
without providing an authorized access token or using SMTP AUTH PLAIN.
If you use [access tokens](#access-tokens), that will change the format of the e-mail's recipient address to
``` ```
ntfy-$topic+$token@ntfy.sh ntfy-$topic+$token@ntfy.sh
``` ```
To use [username/password](https://docs.ntfy.sh/publish/#username-password), you can use SMTP PLAIN auth when authenticating
to the ntfy server.
As of today, e-mail publishing only supports adding a [message title](#message-title) (the e-mail subject). Tags, priority, As of today, e-mail publishing only supports adding a [message title](#message-title) (the e-mail subject). Tags, priority,
delay and other features are not supported (yet). Here's an example that will publish a message with the delay and other features are not supported (yet). Here's an example that will publish a message with the
title `You've Got Mail` to topic `sometopic` (see [ntfy.sh/sometopic](https://ntfy.sh/sometopic)): title `You've Got Mail` to topic `sometopic` (see [ntfy.sh/sometopic](https://ntfy.sh/sometopic)):
@@ -3089,7 +3094,7 @@ may be read/write protected so that only users with the correct credentials can
To publish/subscribe to protected topics, you can: To publish/subscribe to protected topics, you can:
* Use [username & password](#username-password) via Basic auth, e.g. `Authorization: Basic dGVzdHVzZXI6ZmFrZXBhc3N3b3Jk` * Use [username & password](#username-password) via Basic auth, e.g. `Authorization: Basic dGVzdHVzZXI6ZmFrZXBhc3N3b3Jk`
* Use [access tokens](#bearer-auth) via Bearer/Basic auth, e.g. `Authorization: Bearer tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2` * Use [access tokens](#access-tokens) via Bearer/Basic auth, e.g. `Authorization: Bearer tk_AgQdq7mVBoFD37zQVN29RhuMzNIz2`
* or use either with the [`auth` query parameter](#query-param), e.g. `?auth=QmFzaWMgZEdWemRIVnpaWEk2Wm1GclpYQmhjM04zYjNKaw` * or use either with the [`auth` query parameter](#query-param), e.g. `?auth=QmFzaWMgZEdWemRIVnpaWEk2Wm1GclpYQmhjM04zYjNKaw`
!!! warning !!! warning

View File

@@ -689,7 +689,7 @@ minute or so, due to competing stats gathering (personal installations will like
**Features:** **Features:**
* Add `cache-startup-queries` option to allow custom [SQLite performance tuning](config.md#wal-for-message-cache) (no ticket) * Add `cache-startup-queries` option to allow custom [SQLite performance tuning](config.md#message-cache) (no ticket)
* ntfy CLI can now [wait for a command or PID](subscribe/cli.md#wait-for-pidcommand) before publishing ([#263](https://github.com/binwiederhier/ntfy/issues/263), thanks to the [original ntfy](https://github.com/dschep/ntfy) for the idea) * ntfy CLI can now [wait for a command or PID](subscribe/cli.md#wait-for-pidcommand) before publishing ([#263](https://github.com/binwiederhier/ntfy/issues/263), thanks to the [original ntfy](https://github.com/dschep/ntfy) for the idea)
* Trace: Log entire HTTP request to simplify debugging (no ticket) * Trace: Log entire HTTP request to simplify debugging (no ticket)
* Allow setting user password via `NTFY_PASSWORD` env variable ([#327](https://github.com/binwiederhier/ntfy/pull/327), thanks to [@Kenix3](https://github.com/Kenix3)) * Allow setting user password via `NTFY_PASSWORD` env variable ([#327](https://github.com/binwiederhier/ntfy/pull/327), thanks to [@Kenix3](https://github.com/Kenix3))
@@ -1373,6 +1373,30 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
## Not released yet ## Not released yet
### ntfy server v2.12.0 (UNRELEASED)
**Features:**
* Add username/password auth to email publishing ([#1164](https://github.com/binwiederhier/ntfy/pull/1164), thanks to [@bishtawi](https://github.com/bishtawi))
**Bug fixes + maintenance:**
* Add `Date` header to outgoing emails to avoid rejection ([#1141](https://github.com/binwiederhier/ntfy/pull/1141), thanks to [@pcouy](https://github.com/pcouy))
* Security updates for dependencies and Docker images ([#1341](https://github.com/binwiederhier/ntfy/pull/1341))
* Fix IP address parsing when behind a proxy ([#1266](https://github.com/binwiederhier/ntfy/pull/1266), thanks to [@mmatuska](https://github.com/mmatuska))
* Make sure UnifiedPush messages are not treated as attachments ([#1312](https://github.com/binwiederhier/ntfy/pull/1312), thanks to [@vkrause](https://github.com/vkrause))
* Add OCI image version to Docker image ([#1307](https://github.com/binwiederhier/ntfy/pull/1307), thanks to [@jlssmt](https://github.com/jlssmt))
**Documentation:**
* Lots of new integrations: [ntfy-me-mcp](https://github.com/gitmotion/ntfy-me-mcp), [UptimeObserver](https://uptimeobserver.com), [alertmanager-ntfy-relay](https://github.com/therobbielee/alertmanager-ntfy-relay), [Monibot](https://monibot.io/), ... Amazing!
* Various docs updates ([#1161](https://github.com/binwiederhier/ntfy/pull/1161), thanks to [@OneWeekNotice](https://github.com/OneWeekNotice))
* Typo in config docs ([#1177](https://github.com/binwiederhier/ntfy/pull/1177), thanks to [@hoho4190](https://github.com/hoho4190))
* Typo in CLI docs ([#1172](https://github.com/binwiederhier/ntfy/pull/1172), thanks to [@anirvan](https://github.com/anirvan))
* Correction about MacroDroid ([#1137](https://github.com/binwiederhier/ntfy/pull/1137), thanks to [@ShlomoCode](https://github.com/ShlomoCode))
* Note about fail2ban in Docker ([#1175](https://github.com/binwiederhier/ntfy/pull/1175)), thanks to [@Measurity](https://github.com/Measurity))
* Lots of other tiny docs updates, tanks to everyone who contributed!
### ntfy Android app v1.16.1 (UNRELEASED) ### ntfy Android app v1.16.1 (UNRELEASED)
**Features:** **Features:**

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View File

@@ -132,7 +132,7 @@ easy to use. Here's what it looks like. You may also want to check out the [full
### Subscribe as raw stream ### Subscribe as raw stream
The `/raw` endpoint will output one line per message, and **will only include the message body**. It's useful for extremely The `/raw` endpoint will output one line per message, and **will only include the message body**. It's useful for extremely
simple scripts, and doesn't include all the data. Additional fields such as [priority](../publish.md#message-priority), simple scripts, and doesn't include all the data. Additional fields such as [priority](../publish.md#message-priority),
[tags](../publish.md#tags--emojis--) or [message title](../publish.md#message-title) are not included in this output [tags](../publish.md#tags-emojis) or [message title](../publish.md#message-title) are not included in this output
format. Keepalive messages are sent as empty lines. format. Keepalive messages are sent as empty lines.
=== "Command line (curl)" === "Command line (curl)"
@@ -305,7 +305,7 @@ Depending on whether the server is configured to support [access control](../con
may be read/write protected so that only users with the correct credentials can subscribe or publish to them. may be read/write protected so that only users with the correct credentials can subscribe or publish to them.
To publish/subscribe to protected topics, you can: To publish/subscribe to protected topics, you can:
* Use [basic auth](../publish.md#basic-auth), e.g. `Authorization: Basic dGVzdHVzZXI6ZmFrZXBhc3N3b3Jk` * Use [basic auth](../publish.md#authentication), e.g. `Authorization: Basic dGVzdHVzZXI6ZmFrZXBhc3N3b3Jk`
* or use the [`auth` query parameter](../publish.md#query-param), e.g. `?auth=QmFzaWMgZEdWemRIVnpaWEk2Wm1GclpYQmhjM04zYjNKaw` * or use the [`auth` query parameter](../publish.md#query-param), e.g. `?auth=QmFzaWMgZEdWemRIVnpaWEk2Wm1GclpYQmhjM04zYjNKaw`
Please refer to the [publishing documentation](../publish.md#authentication) for additional details. Please refer to the [publishing documentation](../publish.md#authentication) for additional details.

View File

@@ -317,7 +317,7 @@ You can either add your username and password to the configuration file:
password: mypass password: mypass
``` ```
Or with the `ntfy subscibe` command: Or with the `ntfy subscribe` command:
``` ```
ntfy subscribe \ ntfy subscribe \
-u phil:mypass \ -u phil:mypass \

124
go.mod
View File

@@ -1,27 +1,27 @@
module heckel.io/ntfy/v2 module heckel.io/ntfy/v2
go 1.21 go 1.24
toolchain go1.21.3 toolchain go1.24.0
require ( require (
cloud.google.com/go/firestore v1.15.0 // indirect cloud.google.com/go/firestore v1.18.0 // indirect
cloud.google.com/go/storage v1.41.0 // indirect cloud.google.com/go/storage v1.54.0 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect github.com/BurntSushi/toml v1.5.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.7 // indirect
github.com/emersion/go-smtp v0.18.0 github.com/emersion/go-smtp v0.18.0
github.com/gabriel-vasile/mimetype v1.4.3 github.com/gabriel-vasile/mimetype v1.4.9
github.com/gorilla/websocket v1.5.1 github.com/gorilla/websocket v1.5.3
github.com/mattn/go-sqlite3 v1.14.22 github.com/mattn/go-sqlite3 v1.14.28
github.com/olebedev/when v1.0.0 github.com/olebedev/when v1.1.0
github.com/stretchr/testify v1.9.0 github.com/stretchr/testify v1.10.0
github.com/urfave/cli/v2 v2.27.2 github.com/urfave/cli/v2 v2.27.6
golang.org/x/crypto v0.23.0 golang.org/x/crypto v0.38.0
golang.org/x/oauth2 v0.20.0 // indirect golang.org/x/oauth2 v0.30.0 // indirect
golang.org/x/sync v0.7.0 golang.org/x/sync v0.14.0
golang.org/x/term v0.20.0 golang.org/x/term v0.32.0
golang.org/x/time v0.5.0 golang.org/x/time v0.11.0
google.golang.org/api v0.180.0 google.golang.org/api v0.234.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
) )
@@ -30,61 +30,75 @@ replace github.com/emersion/go-smtp => github.com/emersion/go-smtp v0.17.0 // Pi
require github.com/pkg/errors v0.9.1 // indirect require github.com/pkg/errors v0.9.1 // indirect
require ( require (
firebase.google.com/go/v4 v4.14.0 firebase.google.com/go/v4 v4.15.2
github.com/SherClockHolmes/webpush-go v1.3.0 github.com/SherClockHolmes/webpush-go v1.4.0
github.com/microcosm-cc/bluemonday v1.0.26 github.com/microcosm-cc/bluemonday v1.0.27
github.com/prometheus/client_golang v1.19.1 github.com/prometheus/client_golang v1.22.0
github.com/stripe/stripe-go/v74 v74.30.0 github.com/stripe/stripe-go/v74 v74.30.0
) )
require ( require (
cloud.google.com/go v0.113.0 // indirect cel.dev/expr v0.24.0 // indirect
cloud.google.com/go/auth v0.4.1 // indirect cloud.google.com/go v0.121.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/auth v0.16.1 // indirect
cloud.google.com/go/compute/metadata v0.3.0 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
cloud.google.com/go/iam v1.1.8 // indirect cloud.google.com/go/compute/metadata v0.7.0 // indirect
cloud.google.com/go/longrunning v0.5.7 // indirect cloud.google.com/go/iam v1.5.2 // indirect
cloud.google.com/go/longrunning v0.6.7 // indirect
cloud.google.com/go/monitoring v1.24.2 // indirect
github.com/AlekSi/pointer v1.2.0 // indirect github.com/AlekSi/pointer v1.2.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 // indirect
github.com/MicahParks/keyfunc v1.9.0 // indirect github.com/MicahParks/keyfunc v1.9.0 // indirect
github.com/aymerick/douceur v0.2.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect github.com/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 // indirect github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 // indirect
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.1 // indirect github.com/go-jose/go-jose/v4 v4.1.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect github.com/golang/protobuf v1.5.4 // indirect
github.com/google/s2a-go v0.1.7 // indirect github.com/google/s2a-go v0.1.9 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
github.com/googleapis/gax-go/v2 v2.12.4 // indirect github.com/googleapis/gax-go/v2 v2.14.2 // indirect
github.com/gorilla/css v1.0.1 // indirect github.com/gorilla/css v1.0.1 // indirect
github.com/kr/text v0.2.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/client_model v0.6.2 // indirect
github.com/prometheus/common v0.53.0 // indirect github.com/prometheus/common v0.64.0 // indirect
github.com/prometheus/procfs v0.14.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect github.com/stretchr/objx v0.5.2 // indirect
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
go.opencensus.io v0.24.0 // indirect github.com/zeebo/errs v1.4.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 // indirect go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 // indirect go.opentelemetry.io/contrib/detectors/gcp v1.35.0 // indirect
go.opentelemetry.io/otel v1.26.0 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
go.opentelemetry.io/otel/metric v1.26.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
go.opentelemetry.io/otel/trace v1.26.0 // indirect go.opentelemetry.io/otel v1.36.0 // indirect
golang.org/x/net v0.25.0 // indirect go.opentelemetry.io/otel/metric v1.36.0 // indirect
golang.org/x/sys v0.20.0 // indirect go.opentelemetry.io/otel/sdk v1.36.0 // indirect
golang.org/x/text v0.15.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.36.0 // indirect
go.opentelemetry.io/otel/trace v1.36.0 // indirect
golang.org/x/net v0.40.0 // indirect
golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.25.0 // indirect
google.golang.org/appengine/v2 v2.0.6 // indirect google.golang.org/appengine/v2 v2.0.6 // indirect
google.golang.org/genproto v0.0.0-20240513163218-0867130af1f8 // indirect google.golang.org/genproto v0.0.0-20250519155744-55703ea1f237 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 // indirect
google.golang.org/grpc v1.63.2 // indirect google.golang.org/grpc v1.72.1 // indirect
google.golang.org/protobuf v1.34.1 // indirect google.golang.org/protobuf v1.36.6 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )

361
go.sum
View File

@@ -1,209 +1,216 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cel.dev/expr v0.24.0 h1:56OvJKSH3hDGL0ml5uSxZmz3/3Pq4tJ+fb1unVLAFcY=
cloud.google.com/go v0.113.0 h1:g3C70mn3lWfckKBiCVsAshabrDg01pQ0pnX1MNtnMkA= cel.dev/expr v0.24.0/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
cloud.google.com/go v0.113.0/go.mod h1:glEqlogERKYeePz6ZdkcLJ28Q2I6aERgDDErBg9GzO8= cloud.google.com/go v0.121.2 h1:v2qQpN6Dx9x2NmwrqlesOt3Ys4ol5/lFZ6Mg1B7OJCg=
cloud.google.com/go/auth v0.4.1 h1:Z7YNIhlWRtrnKlZke7z3GMqzvuYzdc2z98F9D1NV5Hg= cloud.google.com/go v0.121.2/go.mod h1:nRFlrHq39MNVWu+zESP2PosMWA0ryJw8KUBZ2iZpxbw=
cloud.google.com/go/auth v0.4.1/go.mod h1:QVBuVEKpCn4Zp58hzRGvL0tjRGU0YqdRTdCHM1IHnro= cloud.google.com/go/auth v0.16.1 h1:XrXauHMd30LhQYVRHLGvJiYeczweKQXZxsTbV9TiguU=
cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= cloud.google.com/go/auth v0.16.1/go.mod h1:1howDHJ5IETh/LwYs3ZxvlkXF48aSqqJUM+5o02dNOI=
cloud.google.com/go/auth/oauth2adapt v0.2.2/go.mod h1:wcYjgpZI9+Yu7LyYBg4pqSiaRkfEK3GQcpb7C/uyF1Q= cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc= cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.7.0 h1:PBWF+iiAerVNe8UCHxdOt6eHLVc3ydFeOCw78U8ytSU=
cloud.google.com/go/firestore v1.15.0 h1:/k8ppuWOtNuDHt2tsRV42yI21uaGnKDEQnRFeBpbFF8= cloud.google.com/go/compute/metadata v0.7.0/go.mod h1:j5MvL9PprKL39t166CoB1uVHfQMs4tFQZZcKwksXUjo=
cloud.google.com/go/firestore v1.15.0/go.mod h1:GWOxFXcv8GZUtYpWHw/w6IuYNux/BtmeVTMmjrm4yhk= cloud.google.com/go/firestore v1.18.0 h1:cuydCaLS7Vl2SatAeivXyhbhDEIR8BDmtn4egDhIn2s=
cloud.google.com/go/iam v1.1.8 h1:r7umDwhj+BQyz0ScZMp4QrGXjSTI3ZINnpgU2nlB/K0= cloud.google.com/go/firestore v1.18.0/go.mod h1:5ye0v48PhseZBdcl0qbl3uttu7FIEwEYVaWm0UIEOEU=
cloud.google.com/go/iam v1.1.8/go.mod h1:GvE6lyMmfxXauzNq8NbgJbeVQNspG+tcdL/W8QO1+zE= cloud.google.com/go/iam v1.5.2 h1:qgFRAGEmd8z6dJ/qyEchAuL9jpswyODjA2lS+w234g8=
cloud.google.com/go/longrunning v0.5.7 h1:WLbHekDbjK1fVFD3ibpFFVoyizlLRl73I7YKuAKilhU= cloud.google.com/go/iam v1.5.2/go.mod h1:SE1vg0N81zQqLzQEwxL2WI6yhetBdbNQuTvIKCSkUHE=
cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc=
cloud.google.com/go/storage v1.41.0 h1:RusiwatSu6lHeEXe3kglxakAmAbfV+rhtPqA6i8RBx0= cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA=
cloud.google.com/go/storage v1.41.0/go.mod h1:J1WCa/Z2FcgdEDuPUY8DxT5I+d9mFKsCepp5vR6Sq80= cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE=
firebase.google.com/go/v4 v4.14.0 h1:Tc9jWzMUApUFUA5UUx/HcBeZ+LPjlhG2vNRfWJrcMwU= cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY=
firebase.google.com/go/v4 v4.14.0/go.mod h1:pLATyL6xH2o9AMe7rqHdmmOUE/Ph7wcwepIs+uiEKPg= cloud.google.com/go/monitoring v1.24.2 h1:5OTsoJ1dXYIiMiuL+sYscLc9BumrL3CarVLL7dd7lHM=
cloud.google.com/go/monitoring v1.24.2/go.mod h1:x7yzPWcgDRnPEv3sI+jJGBkwl5qINf+6qY4eq0I9B4U=
cloud.google.com/go/storage v1.54.0 h1:Du3XEyliAiftfyW0bwfdppm2MMLdpVAfiIg4T2nAI+0=
cloud.google.com/go/storage v1.54.0/go.mod h1:hIi9Boe8cHxTyaeqh7KMMwKg088VblFK46C2x/BWaZE=
cloud.google.com/go/trace v1.11.6 h1:2O2zjPzqPYAHrn3OKl029qlqG6W8ZdYaOWRyr8NgMT4=
cloud.google.com/go/trace v1.11.6/go.mod h1:GA855OeDEBiBMzcckLPE2kDunIpC72N+Pq8WFieFjnI=
firebase.google.com/go/v4 v4.15.2 h1:KJtV4rAfO2CVCp40hBfVk+mqUqg7+jQKx7yOgFDnXBg=
firebase.google.com/go/v4 v4.15.2/go.mod h1:qkD/HtSumrPMTLs0ahQrje5gTw2WKFKrzVFoqy4SbKA=
github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w= github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w=
github.com/AlekSi/pointer v1.2.0/go.mod h1:gZGfd3dpW4vEc/UlyfKKi1roIqcCgwOIvb0tSNSBle0= github.com/AlekSi/pointer v1.2.0/go.mod h1:gZGfd3dpW4vEc/UlyfKKi1roIqcCgwOIvb0tSNSBle0=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 h1:ErKg/3iS1AKcTkf3yixlZ54f9U1rljCkQyEXWUnIUxc=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 h1:fYE9p3esPxA/C0rQ0AHhP0drtPXDRhaWiwg1DPqO7IU=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0/go.mod h1:BnBReJLvVYx2CS/UHOgVz2BXKXD9wsQPxZug20nZhd0=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.51.0 h1:OqVGm6Ei3x5+yZmSJG1Mh2NwHvpVmZ08CB5qJhT9Nuk=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.51.0/go.mod h1:SZiPHWGOOk3bl8tkevxkoiwPgsIl6CwrWcbwjfHZpdM=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 h1:6/0iUd0xrnX7qt+mLNRwg5c0PGv8wpE8K90ryANQwMI=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0/go.mod h1:otE2jQekW/PqXk1Awf5lmfokJx4uwuqcj1ab5SpGeW0=
github.com/MicahParks/keyfunc v1.9.0 h1:lhKd5xrFHLNOWrDc4Tyb/Q1AJ4LCzQ48GVJyVIID3+o= github.com/MicahParks/keyfunc v1.9.0 h1:lhKd5xrFHLNOWrDc4Tyb/Q1AJ4LCzQ48GVJyVIID3+o=
github.com/MicahParks/keyfunc v1.9.0/go.mod h1:IdnCilugA0O/99dW+/MkvlyrsX8+L8+x95xuVNtM5jw= github.com/MicahParks/keyfunc v1.9.0/go.mod h1:IdnCilugA0O/99dW+/MkvlyrsX8+L8+x95xuVNtM5jw=
github.com/SherClockHolmes/webpush-go v1.3.0 h1:CAu3FvEE9QS4drc3iKNgpBWFfGqNthKlZhp5QpYnu6k= github.com/SherClockHolmes/webpush-go v1.4.0 h1:ocnzNKWN23T9nvHi6IfyrQjkIc0oJWv1B1pULsf9i3s=
github.com/SherClockHolmes/webpush-go v1.3.0/go.mod h1:AxRHmJuYwKGG1PVgYzToik1lphQvDnqFYDqimHvwhIw= github.com/SherClockHolmes/webpush-go v1.4.0/go.mod h1:XSq8pKX11vNV8MJEMwjrlTkxhAj1zKfxmyhdV7Pd6UA=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443 h1:aQ3y1lwWyqYPiWZThqv1aFbZMiM9vblcSArJRf2Irls=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/xds/go v0.0.0-20250501225837-2ac532fd4443/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43 h1:hH4PQfOndHDlpzYfLAAfl63E8Le6F2+EL/cdhlkyRJY= github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6 h1:oP4q0fw+fOSWn3DfFi4EXdT+B+gTtzx8GC9xsc26Znk=
github.com/emersion/go-sasl v0.0.0-20231106173351-e73c9f7bad43/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= github.com/emersion/go-sasl v0.0.0-20241020182733-b788ff22d5a6/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ=
github.com/emersion/go-smtp v0.17.0 h1:tq90evlrcyqRfE6DSXaWVH54oX6OuZOQECEmhWBMEtI= github.com/emersion/go-smtp v0.17.0 h1:tq90evlrcyqRfE6DSXaWVH54oX6OuZOQECEmhWBMEtI=
github.com/emersion/go-smtp v0.17.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ= github.com/emersion/go-smtp v0.17.0/go.mod h1:qm27SGYgoIPRot6ubfQ/GpiPy/g3PaZAVRxiO/sDUgQ=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI=
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4=
github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8=
github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU=
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gabriel-vasile/mimetype v1.4.9/go.mod h1:WnSQhFKJuBlRyLiKohA/2DtIlPFAbguNaG7QCHcyGok=
github.com/go-jose/go-jose/v4 v4.1.0 h1:cYSYxd3pw5zd2FSXk2vGdn9igQU2PS8MuxrCOCl0FdY=
github.com/go-jose/go-jose/v4 v4.1.0/go.mod h1:GG/vqmYm3Von2nYiB2vGTXzdoNKE5tix5tuc6iAd+sw=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.2 h1:YtQM7lnr8iZ+j5q71MGKkNw9Mn7AjHM68uc9g5fXeUI=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc= github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc=
github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0= github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0=
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/gax-go/v2 v2.12.4 h1:9gWcmF85Wvq4ryPFvGFaOgPIs1AQX0d0bcbGw4Z96qg= github.com/googleapis/gax-go/v2 v2.14.2 h1:eBLnkZ9635krYIPD+ag1USrOAI0Nr0QYF3+/3GqO0k0=
github.com/googleapis/gax-go/v2 v2.12.4/go.mod h1:KYEYLorsnIGDi/rPC8b5TdlB9kbKoFubselGIoBMCwI= github.com/googleapis/gax-go/v2 v2.14.2/go.mod h1:ON64QhlJkhVtSqp4v1uaK92VyZ2gmvDQsweuyLV+8+w=
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/olebedev/when v1.0.0 h1:T2DZCj8HxUhOVxcqaLOmzuTr+iZLtMHsZEim7mjIA2w= github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
github.com/olebedev/when v1.0.0/go.mod h1:T0THb4kP9D3NNqlvCwIG4GyUioTAzEhB4RNVzig/43E= github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/olebedev/when v1.1.0 h1:dlpoRa7huImhNtEx4yl0WYfTHVEWmJmIWd7fEkTHayc=
github.com/olebedev/when v1.1.0/go.mod h1:T0THb4kP9D3NNqlvCwIG4GyUioTAzEhB4RNVzig/43E=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v1.19.1 h1:wZWJDwK+NameRJuPGDhlnFgx8e8HN3XHQeLaYJFJBOE= github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
github.com/prometheus/client_golang v1.19.1/go.mod h1:mP78NwGzrVks5S2H6ab8+ZZGJLZUq1hoULYBAYBw1Ho= github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= github.com/prometheus/common v0.64.0 h1:pdZeA+g617P7oGv1CzdTzyeShxAGrTBsolKNOLQPGO4=
github.com/prometheus/common v0.53.0 h1:U2pL9w9nmJwJDa4qqLQ3ZaePJ6ZTwt7cMD3AG3+aLCE= github.com/prometheus/common v0.64.0/go.mod h1:0gZns+BLRQ3V6NdaerOhMbwwRbNh9hkGINtQAsP5GS8=
github.com/prometheus/common v0.53.0/go.mod h1:BrxBKv3FWBIGXw89Mg1AeBq7FSyRzXWI3l3e7W3RN5U= github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
github.com/prometheus/procfs v0.14.0 h1:Lw4VdGGoKEZilJsayHf0B+9YgLGREba2C6xr+Fdfq6s= github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
github.com/prometheus/procfs v0.14.0/go.mod h1:XL+Iwz8k8ZabyZfMFHPiilCniixqQarAy5Mu67pHlNQ= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE=
github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stripe/stripe-go/v74 v74.30.0 h1:0Kf0KkeFnY7iRhOwvTerX0Ia1BRw+eV1CVJ51mGYAUY= github.com/stripe/stripe-go/v74 v74.30.0 h1:0Kf0KkeFnY7iRhOwvTerX0Ia1BRw+eV1CVJ51mGYAUY=
github.com/stripe/stripe-go/v74 v74.30.0/go.mod h1:f9L6LvaXa35ja7eyvP6GQswoaIPaBRvGAimAO+udbBw= github.com/stripe/stripe-go/v74 v74.30.0/go.mod h1:f9L6LvaXa35ja7eyvP6GQswoaIPaBRvGAimAO+udbBw=
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI= github.com/urfave/cli/v2 v2.27.6 h1:VdRdS98FNhKZ8/Az8B7MTyGQmpIr36O1EHybx/LaZ4g=
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM= github.com/urfave/cli/v2 v2.27.6/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk= github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM=
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0 h1:A3SayB3rNyt+1S6qpI9mHPkeHTZbD7XILEqWnYZb2l0= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.51.0/go.mod h1:27iA5uvhuRNmalO+iEUdVn5ZMj2qy10Mm+XRIpRmyuU= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0 h1:Xs2Ncz0gNihqu9iosIZ5SkBbWo5T8JhhLJFMQL1qmLI= go.opentelemetry.io/contrib/detectors/gcp v1.35.0 h1:bGvFt68+KTiAKFlacHW6AhA56GF2rS0bdD3aJYEnmzA=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.51.0/go.mod h1:vy+2G/6NvVMpwGX/NyLqcC41fxepnuKHk16E6IZUcJc= go.opentelemetry.io/contrib/detectors/gcp v1.35.0/go.mod h1:qGWP8/+ILwMRIUf9uIVLloR1uo5ZYAslM4O6OqUi1DA=
go.opentelemetry.io/otel v1.26.0 h1:LQwgL5s/1W7YiiRwxf03QGnWLb2HW4pLiAhaA5cZXBs= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
go.opentelemetry.io/otel v1.26.0/go.mod h1:UmLkJHUAidDval2EICqBMbnAd0/m2vmpf/dAM+fvFs4= go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
go.opentelemetry.io/otel/metric v1.26.0 h1:7S39CLuY5Jgg9CrnA9HHiEjGMF/X2VHvoXGgSllRz30= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
go.opentelemetry.io/otel/metric v1.26.0/go.mod h1:SY+rHOI4cEawI9a7N1A4nIg/nTQXe1ccCNWYOJUrpX4= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw= go.opentelemetry.io/otel v1.36.0 h1:UumtzIklRBY6cI/lllNZlALOF5nNIzJVb16APdvgTXg=
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg= go.opentelemetry.io/otel v1.36.0/go.mod h1:/TcFMXYjyRNh8khOAO9ybYkqaDBb/70aVwkNML4pP8E=
go.opentelemetry.io/otel/trace v1.26.0 h1:1ieeAUb4y0TE26jUFrCIXKpTuVK7uJGN9/Z/2LP5sQA= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 h1:PB3Zrjs1sG1GBX51SXyTSoOTqcDglmsk7nT6tkKPb/k=
go.opentelemetry.io/otel/trace v1.26.0/go.mod h1:4iDxvGDQuUkHve82hJJ8UqrwswHYsZuWCBllGV2U2y0= go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0/go.mod h1:U2R3XyVPzn0WX7wOIypPuptulsMcPDPs/oiSVOMVnHY=
go.opentelemetry.io/otel/metric v1.36.0 h1:MoWPKVhQvJ+eeXWHFBOPoBOi20jh6Iq2CcCREuTYufE=
go.opentelemetry.io/otel/metric v1.36.0/go.mod h1:zC7Ks+yeyJt4xig9DEw9kuUFe5C3zLbVjV2PzT6qzbs=
go.opentelemetry.io/otel/sdk v1.36.0 h1:b6SYIuLRs88ztox4EyrvRti80uXIFy+Sqzoh9kFULbs=
go.opentelemetry.io/otel/sdk v1.36.0/go.mod h1:+lC+mTgD+MUWfjJubi2vvXWcVxyr9rmlshZni72pXeY=
go.opentelemetry.io/otel/sdk/metric v1.36.0 h1:r0ntwwGosWGaa0CrSt8cuNuTcccMXERFwHX4dThiPis=
go.opentelemetry.io/otel/sdk/metric v1.36.0/go.mod h1:qTNOhFDfKRwX0yXOqJYegL5WRaW376QbB7P4Pb0qva4=
go.opentelemetry.io/otel/trace v1.36.0 h1:ahxWNuqZjpdiFAyrIoQ4GIiAIhxAunQR6MUoKrsNd4w=
go.opentelemetry.io/otel/trace v1.36.0/go.mod h1:gQ+OnDZzrybY4k4seLzPAWNwVBBVlF2szhehOBB/tGA=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo= golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -211,14 +218,23 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@@ -226,57 +242,38 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= google.golang.org/api v0.234.0 h1:d3sAmYq3E9gdr2mpmiWGbm9pHsA/KJmyiLkwKfHBqU4=
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= google.golang.org/api v0.234.0/go.mod h1:QpeJkemzkFKe5VCE/PMv7GsUfn9ZF+u+q1Q7w6ckxTg=
google.golang.org/api v0.180.0 h1:M2D87Yo0rGBPWpo1orwfCLehUUL6E7/TYe5gvMQWDh4=
google.golang.org/api v0.180.0/go.mod h1:51AiyoEg1MJPSZ9zvklA8VnRILPXxn1iVen9v25XHAE=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine/v2 v2.0.6 h1:LvPZLGuchSBslPBp+LAhihBeGSiRh1myRoYK4NtuBIw= google.golang.org/appengine/v2 v2.0.6 h1:LvPZLGuchSBslPBp+LAhihBeGSiRh1myRoYK4NtuBIw=
google.golang.org/appengine/v2 v2.0.6/go.mod h1:WoEXGoXNfa0mLvaH5sV3ZSGXwVmy8yf7Z1JKf3J3wLI= google.golang.org/appengine/v2 v2.0.6/go.mod h1:WoEXGoXNfa0mLvaH5sV3ZSGXwVmy8yf7Z1JKf3J3wLI=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20250519155744-55703ea1f237 h1:2zGWyk04EwQ3mmV4dd4M4U7P/igHi5p7CBJEg1rI6A8=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20250519155744-55703ea1f237/go.mod h1:LhI4bRmX3rqllzQ+BGneexULkEjBf2gsAfkbeCA8IbU=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237 h1:Kog3KlB4xevJlAcbbbzPfRG0+X9fdoGM+UBRKVz6Wr0=
google.golang.org/genproto v0.0.0-20240513163218-0867130af1f8 h1:XpH03M6PDRKTo1oGfZBXu2SzwcbfxUokgobVinuUZoU= google.golang.org/genproto/googleapis/api v0.0.0-20250519155744-55703ea1f237/go.mod h1:ezi0AVyMKDWy5xAncvjLWH7UcLBB5n7y2fQ8MzjJcto=
google.golang.org/genproto v0.0.0-20240513163218-0867130af1f8/go.mod h1:OLh2Ylz+WlYAJaSBRpJIJLP8iQP+8da+fpxbwNEAV/o= google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237 h1:cJfm9zPbe1e873mHJzmQ1nwVEeRDU/T1wXDK2kUSU34=
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8 h1:W5Xj/70xIA4x60O/IFyXivR5MGqblAb8R3w26pnD6No= google.golang.org/genproto/googleapis/rpc v0.0.0-20250519155744-55703ea1f237/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
google.golang.org/genproto/googleapis/api v0.0.0-20240513163218-0867130af1f8/go.mod h1:vPrPUTsDCYxXWjP7clS81mZ6/803D8K4iM9Ma27VKas= google.golang.org/grpc v1.72.1 h1:HR03wO6eyZ7lknl75XlxABNVLLFc2PAb6mHlYh756mA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8 h1:mxSlqyb8ZAHsYDCfiXN1EDdNTdvjUJSLY+OnAUtYNYA= google.golang.org/grpc v1.72.1/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240513163218-0867130af1f8/go.mod h1:I7Y+G38R2bu5j1aLzfFmQfTcU/WnFuqDwLZAbvKTKpM=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM=
google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
@@ -285,5 +282,3 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

View File

@@ -198,7 +198,7 @@ func (w *peekLogWriter) Write(p []byte) (n int, err error) {
if len(p) == 0 || p[0] == '{' || CurrentFormat() == TextFormat { if len(p) == 0 || p[0] == '{' || CurrentFormat() == TextFormat {
return w.w.Write(p) return w.w.Write(p)
} }
m := newEvent().Tag(tagStdLog).Render(InfoLevel, strings.TrimSpace(string(p))) m := newEvent().Tag(tagStdLog).Render(InfoLevel, "%s", strings.TrimSpace(string(p)))
if m == "" { if m == "" {
return 0, nil return 0, nil
} }

View File

@@ -23,7 +23,7 @@ If you want to chat, simply join the Discord server (https://discord.gg/cT7ECsZj
the Matrix room (https://matrix.to/#/#ntfy:matrix.org). the Matrix room (https://matrix.to/#/#ntfy:matrix.org).
ntfy %s (%s), runtime %s, built at %s ntfy %s (%s), runtime %s, built at %s
Copyright (C) 2022 Philipp C. Heckel, licensed under Apache License 2.0 & GPLv2 Copyright (C) Philipp C. Heckel, licensed under Apache License 2.0 & GPLv2
`, version, commit[:7], runtime.Version(), date) `, version, commit[:7], runtime.Version(), date)
app := cmd.New() app := cmd.New()

View File

@@ -413,7 +413,8 @@ func (s *Server) handleError(w http.ResponseWriter, r *http.Request, v *visitor,
} else { } else {
ev.Info("WebSocket error: %s", err.Error()) ev.Info("WebSocket error: %s", err.Error())
} }
return // Do not attempt to write to upgraded connection w.WriteHeader(httpErr.HTTPCode)
return // Do not attempt to write any body to upgraded connection
} }
if isNormalError { if isNormalError {
ev.Debug("Connection closed with HTTP %d (ntfy error %d)", httpErr.HTTPCode, httpErr.Code) ev.Debug("Connection closed with HTTP %d (ntfy error %d)", httpErr.HTTPCode, httpErr.Code)
@@ -1016,7 +1017,7 @@ func (s *Server) parsePublishParams(r *http.Request, m *message) (cache bool, fi
if actionsStr != "" { if actionsStr != "" {
m.Actions, e = parseActions(actionsStr) m.Actions, e = parseActions(actionsStr)
if e != nil { if e != nil {
return false, false, "", "", false, false, errHTTPBadRequestActionsInvalid.Wrap(e.Error()) return false, false, "", "", false, false, errHTTPBadRequestActionsInvalid.Wrap("%s", e.Error())
} }
} }
contentType, markdown := readParam(r, "content-type", "content_type"), readBoolParam(r, false, "x-markdown", "markdown", "md") contentType, markdown := readParam(r, "content-type", "content_type"), readBoolParam(r, false, "x-markdown", "markdown", "md")
@@ -1025,7 +1026,8 @@ func (s *Server) parsePublishParams(r *http.Request, m *message) (cache bool, fi
} }
template = readBoolParam(r, false, "x-template", "template", "tpl") template = readBoolParam(r, false, "x-template", "template", "tpl")
unifiedpush = readBoolParam(r, false, "x-unifiedpush", "unifiedpush", "up") // see GET too! unifiedpush = readBoolParam(r, false, "x-unifiedpush", "unifiedpush", "up") // see GET too!
if unifiedpush { contentEncoding := readParam(r, "content-encoding")
if unifiedpush || contentEncoding == "aes128gcm" {
firebase = false firebase = false
unifiedpush = true unifiedpush = true
} }
@@ -1828,7 +1830,7 @@ func (s *Server) transformBodyJSON(next handleFunc) handleFunc {
if m.Priority != 0 { if m.Priority != 0 {
r.Header.Set("X-Priority", fmt.Sprintf("%d", m.Priority)) r.Header.Set("X-Priority", fmt.Sprintf("%d", m.Priority))
} }
if m.Tags != nil && len(m.Tags) > 0 { if len(m.Tags) > 0 {
r.Header.Set("X-Tags", strings.Join(m.Tags, ",")) r.Header.Set("X-Tags", strings.Join(m.Tags, ","))
} }
if m.Attach != "" { if m.Attach != "" {
@@ -1885,14 +1887,14 @@ func (s *Server) transformMatrixJSON(next handleFunc) handleFunc {
} }
func (s *Server) authorizeTopicWrite(next handleFunc) handleFunc { func (s *Server) authorizeTopicWrite(next handleFunc) handleFunc {
return s.autorizeTopic(next, user.PermissionWrite) return s.authorizeTopic(next, user.PermissionWrite)
} }
func (s *Server) authorizeTopicRead(next handleFunc) handleFunc { func (s *Server) authorizeTopicRead(next handleFunc) handleFunc {
return s.autorizeTopic(next, user.PermissionRead) return s.authorizeTopic(next, user.PermissionRead)
} }
func (s *Server) autorizeTopic(next handleFunc, perm user.Permission) handleFunc { func (s *Server) authorizeTopic(next handleFunc, perm user.Permission) handleFunc {
return func(w http.ResponseWriter, r *http.Request, v *visitor) error { return func(w http.ResponseWriter, r *http.Request, v *visitor) error {
if s.userManager == nil { if s.userManager == nil {
return next(w, r, v) return next(w, r, v)

View File

@@ -1277,6 +1277,7 @@ func TestServer_PublishEmailNoMailer_Fail(t *testing.T) {
func TestServer_PublishAndExpungeTopicAfter16Hours(t *testing.T) { func TestServer_PublishAndExpungeTopicAfter16Hours(t *testing.T) {
t.Parallel() t.Parallel()
s := newTestServer(t, newTestConfig(t)) s := newTestServer(t, newTestConfig(t))
defer s.messageCache.Close()
subFn := func(v *visitor, msg *message) error { subFn := func(v *visitor, msg *message) error {
return nil return nil
@@ -1288,13 +1289,22 @@ func TestServer_PublishAndExpungeTopicAfter16Hours(t *testing.T) {
}) })
require.Equal(t, 200, response.Code) require.Equal(t, 200, response.Code)
waitFor(t, func() bool { waitFor(t, func() bool {
s.mu.Lock()
tp, exists := s.topics["mytopic"]
s.mu.Unlock()
if !exists {
return false
}
// .lastAccess set in t.Publish() -> t.Keepalive() in Goroutine // .lastAccess set in t.Publish() -> t.Keepalive() in Goroutine
s.topics["mytopic"].mu.RLock() tp.mu.RLock()
defer s.topics["mytopic"].mu.RUnlock() defer tp.mu.RUnlock()
return s.topics["mytopic"].lastAccess.Unix() >= time.Now().Unix()-2 && return tp.lastAccess.Unix() >= time.Now().Unix()-2 &&
s.topics["mytopic"].lastAccess.Unix() <= time.Now().Unix()+2 tp.lastAccess.Unix() <= time.Now().Unix()+2
}) })
// Hack!
time.Sleep(time.Second)
// Topic won't get pruned // Topic won't get pruned
s.execManager() s.execManager()
require.NotNil(t, s.topics["mytopic"]) require.NotNil(t, s.topics["mytopic"])

View File

@@ -110,9 +110,11 @@ func formatMail(baseURL, senderIP, from, to string, m *message) (string, error)
if trailer != "" { if trailer != "" {
message += "\n\n" + trailer message += "\n\n" + trailer
} }
date := time.Unix(m.Time, 0).UTC().Format(time.RFC1123Z)
subject = mime.BEncoding.Encode("utf-8", subject) subject = mime.BEncoding.Encode("utf-8", subject)
body := `From: "{shortTopicURL}" <{from}> body := `From: "{shortTopicURL}" <{from}>
To: {to} To: {to}
Date: {date}
Subject: {subject} Subject: {subject}
Content-Type: text/plain; charset="utf-8" Content-Type: text/plain; charset="utf-8"
@@ -122,6 +124,7 @@ Content-Type: text/plain; charset="utf-8"
This message was sent by {ip} at {time} via {topicURL}` This message was sent by {ip} at {time} via {topicURL}`
body = strings.ReplaceAll(body, "{from}", from) body = strings.ReplaceAll(body, "{from}", from)
body = strings.ReplaceAll(body, "{to}", to) body = strings.ReplaceAll(body, "{to}", to)
body = strings.ReplaceAll(body, "{date}", date)
body = strings.ReplaceAll(body, "{subject}", subject) body = strings.ReplaceAll(body, "{subject}", subject)
body = strings.ReplaceAll(body, "{message}", message) body = strings.ReplaceAll(body, "{message}", message)
body = strings.ReplaceAll(body, "{topicURL}", topicURL) body = strings.ReplaceAll(body, "{topicURL}", topicURL)

View File

@@ -15,6 +15,7 @@ func TestFormatMail_Basic(t *testing.T) {
}) })
expected := `From: "ntfy.sh/alerts" <ntfy@ntfy.sh> expected := `From: "ntfy.sh/alerts" <ntfy@ntfy.sh>
To: phil@example.com To: phil@example.com
Date: Fri, 24 Dec 2021 21:43:24 +0000
Subject: A simple message Subject: A simple message
Content-Type: text/plain; charset="utf-8" Content-Type: text/plain; charset="utf-8"
@@ -36,6 +37,7 @@ func TestFormatMail_JustEmojis(t *testing.T) {
}) })
expected := `From: "ntfy.sh/alerts" <ntfy@ntfy.sh> expected := `From: "ntfy.sh/alerts" <ntfy@ntfy.sh>
To: phil@example.com To: phil@example.com
Date: Fri, 24 Dec 2021 21:43:24 +0000
Subject: =?utf-8?b?8J+YgCBBIHNpbXBsZSBtZXNzYWdl?= Subject: =?utf-8?b?8J+YgCBBIHNpbXBsZSBtZXNzYWdl?=
Content-Type: text/plain; charset="utf-8" Content-Type: text/plain; charset="utf-8"
@@ -57,6 +59,7 @@ func TestFormatMail_JustOtherTags(t *testing.T) {
}) })
expected := `From: "ntfy.sh/alerts" <ntfy@ntfy.sh> expected := `From: "ntfy.sh/alerts" <ntfy@ntfy.sh>
To: phil@example.com To: phil@example.com
Date: Fri, 24 Dec 2021 21:43:24 +0000
Subject: A simple message Subject: A simple message
Content-Type: text/plain; charset="utf-8" Content-Type: text/plain; charset="utf-8"
@@ -80,6 +83,7 @@ func TestFormatMail_JustPriority(t *testing.T) {
}) })
expected := `From: "ntfy.sh/alerts" <ntfy@ntfy.sh> expected := `From: "ntfy.sh/alerts" <ntfy@ntfy.sh>
To: phil@example.com To: phil@example.com
Date: Fri, 24 Dec 2021 21:43:24 +0000
Subject: A simple message Subject: A simple message
Content-Type: text/plain; charset="utf-8" Content-Type: text/plain; charset="utf-8"
@@ -103,6 +107,7 @@ func TestFormatMail_UTF8Subject(t *testing.T) {
}) })
expected := `From: "ntfy.sh/alerts" <ntfy@ntfy.sh> expected := `From: "ntfy.sh/alerts" <ntfy@ntfy.sh>
To: phil@example.com To: phil@example.com
Date: Fri, 24 Dec 2021 21:43:24 +0000
Subject: =?utf-8?b?IDo6IEEgbm90IHNvIHNpbXBsZSB0aXRsZSDDtsOkw7zDnyDCoUhvbGEsIHNl?= =?utf-8?b?w7FvciE=?= Subject: =?utf-8?b?IDo6IEEgbm90IHNvIHNpbXBsZSB0aXRsZSDDtsOkw7zDnyDCoUhvbGEsIHNl?= =?utf-8?b?w7FvciE=?=
Content-Type: text/plain; charset="utf-8" Content-Type: text/plain; charset="utf-8"
@@ -126,6 +131,7 @@ func TestFormatMail_WithAllTheThings(t *testing.T) {
}) })
expected := `From: "ntfy.sh/alerts" <ntfy@ntfy.sh> expected := `From: "ntfy.sh/alerts" <ntfy@ntfy.sh>
To: phil@example.com To: phil@example.com
Date: Fri, 24 Dec 2021 21:43:24 +0000
Subject: =?utf-8?b?4pqg77iPIPCfkoAgT2ggbm8g8J+ZiCBUaGlzIGlzIGEgbWVzc2FnZSBhY3Jv?= =?utf-8?b?c3MgbXVsdGlwbGUgbGluZXM=?= Subject: =?utf-8?b?4pqg77iPIPCfkoAgT2ggbm8g8J+ZiCBUaGlzIGlzIGEgbWVzc2FnZSBhY3Jv?= =?utf-8?b?c3MgbXVsdGlwbGUgbGluZXM=?=
Content-Type: text/plain; charset="utf-8" Content-Type: text/plain; charset="utf-8"

View File

@@ -70,15 +70,19 @@ func (b *smtpBackend) Counts() (total int64, success int64, failure int64) {
// smtpSession is returned after EHLO. // smtpSession is returned after EHLO.
type smtpSession struct { type smtpSession struct {
backend *smtpBackend backend *smtpBackend
conn *smtp.Conn conn *smtp.Conn
topic string topic string
token string token string // If email address contains token, e.g. topic+token@domain
mu sync.Mutex basicAuth string // If SMTP AUTH PLAIN was used
mu sync.Mutex
} }
func (s *smtpSession) AuthPlain(username, _ string) error { func (s *smtpSession) AuthPlain(username, password string) error {
logem(s.conn).Field("smtp_username", username).Debug("AUTH PLAIN (with username %s)", username) logem(s.conn).Field("smtp_username", username).Debug("AUTH PLAIN (with username %s)", username)
s.mu.Lock()
s.basicAuth = base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password)))
s.mu.Unlock()
return nil return nil
} }
@@ -198,6 +202,8 @@ func (s *smtpSession) publishMessage(m *message) error {
} }
if s.token != "" { if s.token != "" {
req.Header.Add("Authorization", "Bearer "+s.token) req.Header.Add("Authorization", "Bearer "+s.token)
} else if s.basicAuth != "" {
req.Header.Add("Authorization", "Basic "+s.basicAuth)
} }
rr := httptest.NewRecorder() rr := httptest.NewRecorder()
s.backend.handler(rr, req) s.backend.handler(rr, req)
@@ -214,6 +220,9 @@ func (s *smtpSession) Reset() {
} }
func (s *smtpSession) Logout() error { func (s *smtpSession) Logout() error {
s.mu.Lock()
s.basicAuth = ""
s.mu.Unlock()
return nil return nil
} }

View File

@@ -1386,6 +1386,28 @@ what's up
writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued") writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued")
} }
func TestSmtpBackend_PlaintextWithPlainAuth(t *testing.T) {
email := `EHLO example.com
AUTH PLAIN dGVzdAB0ZXN0ADEyMzQ=
MAIL FROM: phil@example.com
RCPT TO: ntfy-mytopic@ntfy.sh
DATA
Subject: Very short mail
what's up
.
`
s, c, _, scanner := newTestSMTPServer(t, func(w http.ResponseWriter, r *http.Request) {
require.Equal(t, "/mytopic", r.URL.Path)
require.Equal(t, "Very short mail", r.Header.Get("Title"))
require.Equal(t, "Basic dGVzdDoxMjM0", r.Header.Get("Authorization"))
require.Equal(t, "what's up", readAll(t, r.Body))
})
defer s.Close()
defer c.Close()
writeAndReadUntilLine(t, email, c, scanner, "250 2.0.0 OK: queued")
}
type smtpHandlerFunc func(http.ResponseWriter, *http.Request) type smtpHandlerFunc func(http.ResponseWriter, *http.Request)
func newTestSMTPServer(t *testing.T, handler smtpHandlerFunc) (s *smtp.Server, c net.Conn, conf *Config, scanner *bufio.Scanner) { func newTestSMTPServer(t *testing.T, handler smtpHandlerFunc) (s *smtp.Server, c net.Conn, conf *Config, scanner *bufio.Scanner) {

View File

@@ -10,8 +10,6 @@ import (
) )
func TestTopic_CancelSubscribersExceptUser(t *testing.T) { func TestTopic_CancelSubscribersExceptUser(t *testing.T) {
t.Parallel()
subFn := func(v *visitor, msg *message) error { subFn := func(v *visitor, msg *message) error {
return nil return nil
} }

View File

@@ -82,7 +82,7 @@ func extractIPAddress(r *http.Request, behindProxy bool) netip.Addr {
ip, err = netip.ParseAddr(remoteAddr) ip, err = netip.ParseAddr(remoteAddr)
if err != nil { if err != nil {
ip = netip.IPv4Unspecified() ip = netip.IPv4Unspecified()
if remoteAddr != "@" || !behindProxy { // RemoteAddr is @ when unix socket is used if remoteAddr != "@" && !behindProxy { // RemoteAddr is @ when unix socket is used
logr(r).Err(err).Warn("unable to parse IP (%s), new visitor with unspecified IP (0.0.0.0) created", remoteAddr) logr(r).Err(err).Warn("unable to parse IP (%s), new visitor with unspecified IP (0.0.0.0) created", remoteAddr)
} }
} }

4449
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -15,7 +15,7 @@
"alert_notification_permission_required_description": "Udělte prohlížeči oprávnění k zobrazování oznámení na ploše.", "alert_notification_permission_required_description": "Udělte prohlížeči oprávnění k zobrazování oznámení na ploše.",
"alert_notification_permission_required_button": "Udělit nyní", "alert_notification_permission_required_button": "Udělit nyní",
"alert_not_supported_title": "Oznámení nejsou podporována", "alert_not_supported_title": "Oznámení nejsou podporována",
"alert_not_supported_description": "Oznámení nejsou ve vašem prohlížeči podporována.", "alert_not_supported_description": "Oznámení nejsou ve vašem prohlížeči podporována",
"notifications_copied_to_clipboard": "Zkopírováno do schránky", "notifications_copied_to_clipboard": "Zkopírováno do schránky",
"notifications_tags": "Značky", "notifications_tags": "Značky",
"notifications_attachment_copy_url_title": "Kopírovat URL přílohy do schránky", "notifications_attachment_copy_url_title": "Kopírovat URL přílohy do schránky",
@@ -380,5 +380,28 @@
"account_usage_calls_title": "Uskutečněné telefonáty", "account_usage_calls_title": "Uskutečněné telefonáty",
"account_upgrade_dialog_tier_features_no_calls": "Žádné telefonní hovory", "account_upgrade_dialog_tier_features_no_calls": "Žádné telefonní hovory",
"account_upgrade_dialog_tier_features_calls_one": "{{calls}} denní telefonní hovor", "account_upgrade_dialog_tier_features_calls_one": "{{calls}} denní telefonní hovor",
"account_upgrade_dialog_tier_features_calls_other": "{{calls}} denních telefonních hovorů" "account_upgrade_dialog_tier_features_calls_other": "{{calls}} denních telefonních hovorů",
"prefs_notifications_web_push_enabled": "Povoleno pro {{server}}",
"error_boundary_button_reload_ntfy": "Znovu načíst ntfy",
"web_push_subscription_expiring_body": "Otevřete ntfy a pokračujte v přijímání oznámení",
"action_bar_mute_notifications": "Ztlumit oznámení",
"action_bar_unmute_notifications": "Zrušit ztlumení oznámení",
"alert_notification_permission_denied_title": "Oznámení jsou blokována",
"alert_notification_permission_denied_description": "Prosím, znovu je povolte ve svém prohlížeči",
"alert_notification_ios_install_required_title": "Je vyžadována instalace iOS",
"alert_notification_ios_install_required_description": "Kliknutím na ikonu Sdílet a Přidat na domovskou obrazovku povolíte oznámení v systému iOS",
"notifications_actions_failed_notification": "Neúspěšná akce",
"publish_dialog_checkbox_markdown": "Formátovat jako Markdown",
"subscribe_dialog_subscribe_use_another_background_info": "Oznámení z jiných serverů nebudou přijímána, pokud není otevřena webová aplikace",
"prefs_notifications_web_push_title": "Oznámení na pozadí",
"prefs_notifications_web_push_enabled_description": "Oznámení jsou přijímána, i když webová aplikace není spuštěna (prostřednictvím Web Push)",
"prefs_notifications_web_push_disabled_description": "Oznámení jsou přijímána, když je webová aplikace spuštěna (přes WebSocket)",
"prefs_notifications_web_push_disabled": "Zakázáno",
"prefs_appearance_theme_title": "Motiv",
"prefs_appearance_theme_system": "Systém (výchozí)",
"prefs_appearance_theme_dark": "Tmavý režim",
"prefs_appearance_theme_light": "Světlý režim",
"web_push_subscription_expiring_title": "Oznámení budou pozastavena",
"web_push_unknown_notification_title": "Neznámé oznámení přijaté ze serveru",
"web_push_unknown_notification_body": "Možná bude nutné aktualizovat ntfy otevřením webové aplikace"
} }

View File

@@ -382,6 +382,6 @@
"account_usage_calls_none": "Noch keine Anrufe mit diesem Account getätigt", "account_usage_calls_none": "Noch keine Anrufe mit diesem Account getätigt",
"account_upgrade_dialog_tier_features_calls_one": "{{calls}} Telefonanrufe pro Tag", "account_upgrade_dialog_tier_features_calls_one": "{{calls}} Telefonanrufe pro Tag",
"action_bar_mute_notifications": "Benachrichtigungen stummschalten", "action_bar_mute_notifications": "Benachrichtigungen stummschalten",
"action_bar_unmute_notifications": "Benachrichtigungen lautschalten", "action_bar_unmute_notifications": "Benachrichtigungen laut schalten",
"alert_notification_permission_denied_title": "Benachrichtigungen sind blockiert" "alert_notification_permission_denied_title": "Benachrichtigungen sind blockiert"
} }

View File

@@ -22,7 +22,7 @@
"notifications_attachment_copy_url_button": "Copiar URL", "notifications_attachment_copy_url_button": "Copiar URL",
"notifications_attachment_open_title": "Ir a {{url}}", "notifications_attachment_open_title": "Ir a {{url}}",
"notifications_attachment_open_button": "Abrir archivo adjunto", "notifications_attachment_open_button": "Abrir archivo adjunto",
"notifications_attachment_link_expires": "el enlace expira el día {{fecha}}", "notifications_attachment_link_expires": "el enlace expira el día {{date}}",
"notifications_attachment_link_expired": "el enlace de descarga ha expirado", "notifications_attachment_link_expired": "el enlace de descarga ha expirado",
"notifications_click_copy_url_title": "Copiar la URL del enlace en el portapapeles", "notifications_click_copy_url_title": "Copiar la URL del enlace en el portapapeles",
"notifications_click_copy_url_button": "Copiar enlace", "notifications_click_copy_url_button": "Copiar enlace",
@@ -226,7 +226,7 @@
"account_basics_password_dialog_current_password_incorrect": "Contraseña incorrecta", "account_basics_password_dialog_current_password_incorrect": "Contraseña incorrecta",
"account_usage_unlimited": "Ilimitado", "account_usage_unlimited": "Ilimitado",
"account_usage_title": "Uso", "account_usage_title": "Uso",
"account_usage_of_limit": "de {{límite}}", "account_usage_of_limit": "de {{limit}}",
"account_usage_limits_reset_daily": "Los límites de uso se restablecen diariamente a la medianoche (UTC)", "account_usage_limits_reset_daily": "Los límites de uso se restablecen diariamente a la medianoche (UTC)",
"account_basics_tier_description": "Nivel de poder de tu cuenta", "account_basics_tier_description": "Nivel de poder de tu cuenta",
"account_basics_tier_admin": "Administrador", "account_basics_tier_admin": "Administrador",
@@ -247,7 +247,7 @@
"account_basics_tier_free": "Gratis", "account_basics_tier_free": "Gratis",
"account_basics_tier_upgrade_button": "Actualizar a Pro", "account_basics_tier_upgrade_button": "Actualizar a Pro",
"account_basics_tier_change_button": "Cambiar", "account_basics_tier_change_button": "Cambiar",
"account_basics_tier_paid_until": "Suscripción pagada hasta {{fecha}}, y se renovará automáticamente", "account_basics_tier_paid_until": "Suscripción pagada hasta {{date}}, y se renovará automáticamente",
"account_basics_tier_manage_billing_button": "Administrar la facturación", "account_basics_tier_manage_billing_button": "Administrar la facturación",
"account_basics_tier_title": "Tipo de cuenta", "account_basics_tier_title": "Tipo de cuenta",
"account_tokens_description": "Utilice tokens de acceso al publicar y suscribirse a través de la API de ntfy para no tener que enviar las credenciales de su cuenta. Consulte la <Link>documentación</Link> para obtener más información.", "account_tokens_description": "Utilice tokens de acceso al publicar y suscribirse a través de la API de ntfy para no tener que enviar las credenciales de su cuenta. Consulte la <Link>documentación</Link> para obtener más información.",
@@ -371,8 +371,8 @@
"account_basics_phone_numbers_dialog_channel_call": "Llamar", "account_basics_phone_numbers_dialog_channel_call": "Llamar",
"account_usage_calls_title": "Llamadas telefónicas realizadas", "account_usage_calls_title": "Llamadas telefónicas realizadas",
"account_usage_calls_none": "No se pueden hacer llamadas telefónicas con esta cuenta", "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_one": "{{calls}} llamadas telefónicas diarias",
"account_upgrade_dialog_tier_features_calls_other": "{{llamadas}} llamadas telefónicas diarias", "account_upgrade_dialog_tier_features_calls_other": "{{calls}} llamadas telefónicas diarias",
"account_upgrade_dialog_tier_features_no_calls": "No hay llamadas telefónicas", "account_upgrade_dialog_tier_features_no_calls": "No hay llamadas telefónicas",
"publish_dialog_call_reset": "Eliminar llamada telefónica", "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_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.",

View File

@@ -0,0 +1,26 @@
{
"signup_title": "Loo ntfy kasutajakonto",
"signup_form_username": "Kasutajanimi",
"signup_form_password": "Salasõna",
"signup_form_confirm_password": "Kinnita salasõna õigsust",
"signup_already_have_account": "Sul juba on kasutajakonto olemas? Siis logi sisse!",
"signup_disabled": "Kasutajakonto loomine pole hetkel lubatud",
"signup_error_username_taken": "Kasutajanimi {{username}} on juba olemas",
"signup_error_creation_limit_reached": "Kasutajakontode loomise ülempiir on käes",
"login_title": "Logi sisse oma ntfy kasutajakontole",
"login_form_button_submit": "Logi sisse",
"login_link_signup": "Liitu",
"login_disabled": "Sisselogimine pole hetkel kasutusel",
"action_bar_show_menu": "Näita menüüd",
"action_bar_logo_alt": "ntfy logo",
"action_bar_settings": "Seadistused",
"action_bar_change_display_name": "Muuda kuvatavat nime",
"common_cancel": "Katkesta",
"common_save": "Salvesta",
"common_back": "Tagasi",
"common_copy_to_clipboard": "Kopeeri lõikelauale",
"common_add": "Lisa",
"signup_form_button_submit": "Liitu",
"signup_form_toggle_password_visibility": "Vaheta salasõna nähtavust",
"action_bar_account": "Kasutajakonto"
}

View File

@@ -1,7 +1,7 @@
{ {
"publish_dialog_message_placeholder": "Kirjoita viesti tähän", "publish_dialog_message_placeholder": "Kirjoita viesti tähän",
"account_upgrade_dialog_tier_features_no_calls": "Ei puheluita", "account_upgrade_dialog_tier_features_no_calls": "Ei puheluita",
"account_upgrade_dialog_billing_contact_email": "Laskutukseen liittyvissä kysymyksissä <Link>contact us</Link> suoraan.", "account_upgrade_dialog_billing_contact_email": "Laskutukseen liittyvissä kysymyksissä <Link>ole yhteydessä</Link> .",
"account_tokens_dialog_title_create": "Luo käyttöoikeustunnus", "account_tokens_dialog_title_create": "Luo käyttöoikeustunnus",
"prefs_reservations_dialog_title_edit": "Muokkaa varattua topikkia", "prefs_reservations_dialog_title_edit": "Muokkaa varattua topikkia",
"account_basics_tier_interval_monthly": "Kuukausittain", "account_basics_tier_interval_monthly": "Kuukausittain",
@@ -12,7 +12,7 @@
"prefs_notifications_min_priority_title": "Vähimmäisprioriteetti", "prefs_notifications_min_priority_title": "Vähimmäisprioriteetti",
"account_upgrade_dialog_tier_features_calls_one": "{{calls}} päivittäisiä puheluja", "account_upgrade_dialog_tier_features_calls_one": "{{calls}} päivittäisiä puheluja",
"account_upgrade_dialog_tier_current_label": "Nykyinen", "account_upgrade_dialog_tier_current_label": "Nykyinen",
"action_bar_account": "Kirjautuminen", "action_bar_account": "Tili",
"publish_dialog_filename_placeholder": "Liitetiedoston nimi", "publish_dialog_filename_placeholder": "Liitetiedoston nimi",
"account_basics_password_dialog_current_password_incorrect": "Salasana virheellinen", "account_basics_password_dialog_current_password_incorrect": "Salasana virheellinen",
"account_tokens_table_token_header": "Token", "account_tokens_table_token_header": "Token",
@@ -33,7 +33,7 @@
"account_upgrade_dialog_proration_info": "<strong>Osuussuhde</strong>: Kun päivität maksullisten pakettien välillä, hintaero <strong>veloitetaan välittömästi</strong>. Kun siirryt alemmalle tasolle, saldoa käytetään tulevien laskutuskausien maksamiseen.", "account_upgrade_dialog_proration_info": "<strong>Osuussuhde</strong>: Kun päivität maksullisten pakettien välillä, hintaero <strong>veloitetaan välittömästi</strong>. Kun siirryt alemmalle tasolle, saldoa käytetään tulevien laskutuskausien maksamiseen.",
"prefs_reservations_dialog_access_label": "Oikeudet", "prefs_reservations_dialog_access_label": "Oikeudet",
"account_usage_attachment_storage_title": "Liiteiden säilytys", "account_usage_attachment_storage_title": "Liiteiden säilytys",
"prefs_users_dialog_username_label": "Username, esim pena", "prefs_users_dialog_username_label": "Käyttäjätunnus, esim. pentti",
"message_bar_error_publishing": "Virhe ilmoituksen julkaisemisessa", "message_bar_error_publishing": "Virhe ilmoituksen julkaisemisessa",
"publish_dialog_chip_delay_label": "Viivästytä toimitusta", "publish_dialog_chip_delay_label": "Viivästytä toimitusta",
"account_usage_messages_title": "Julkaistut viestit", "account_usage_messages_title": "Julkaistut viestit",
@@ -86,10 +86,10 @@
"prefs_reservations_dialog_title_delete": "Poista topikin varaus", "prefs_reservations_dialog_title_delete": "Poista topikin varaus",
"prefs_users_table": "Käyttäjätaulukko", "prefs_users_table": "Käyttäjätaulukko",
"prefs_reservations_table_topic_header": "Topikki", "prefs_reservations_table_topic_header": "Topikki",
"action_bar_toggle_mute": "Hiljennä/poista hiljennys", "action_bar_toggle_mute": "Mykistä/palauta ilmoitukset",
"reservation_delete_dialog_submit_button": "Poista varaus", "reservation_delete_dialog_submit_button": "Poista varaus",
"account_basics_title": "Tili", "account_basics_title": "Tili",
"nav_button_documentation": "Dokumentointi", "nav_button_documentation": "Dokumentaatio",
"prefs_reservations_limit_reached": "Olet saavuttanut varattujen topikkien rajan.", "prefs_reservations_limit_reached": "Olet saavuttanut varattujen topikkien rajan.",
"account_upgrade_dialog_interval_monthly": "Kuukausittain", "account_upgrade_dialog_interval_monthly": "Kuukausittain",
"prefs_users_add_button": "Lisää käyttäjä", "prefs_users_add_button": "Lisää käyttäjä",
@@ -116,8 +116,8 @@
"account_tokens_table_label_header": "Merkki", "account_tokens_table_label_header": "Merkki",
"notifications_attachment_file_document": "muu asiakirja", "notifications_attachment_file_document": "muu asiakirja",
"publish_dialog_button_cancel": "Peruuta", "publish_dialog_button_cancel": "Peruuta",
"account_upgrade_dialog_billing_contact_website": "Laskutukseen liittyvissä kysymyksissä käy sivulla <Link>website</Link>.", "account_upgrade_dialog_billing_contact_website": "Laskutukseen liittyvissä kysymyksissä käy <Link>verkkosivustolla</Link>.",
"signup_form_button_submit": "Kirjaudu linkki", "signup_form_button_submit": "Rekisteröidy",
"account_basics_username_admin_tooltip": "Olet pääkäyttäjä", "account_basics_username_admin_tooltip": "Olet pääkäyttäjä",
"prefs_notifications_delete_after_never_description": "Ilmoituksia ei koskaan poisteta automaattisesti", "prefs_notifications_delete_after_never_description": "Ilmoituksia ei koskaan poisteta automaattisesti",
"account_delete_dialog_description": "Tämä poistaa pysyvästi tilisi, mukaan lukien kaikki palvelimelle tallennetut tiedot. Poistamisen jälkeen käyttäjätunnuksesi on poissa käytöstä 7 päivään. Jos todella haluat jatkaa, vahvista salasanasi alla olevaan kenttään.", "account_delete_dialog_description": "Tämä poistaa pysyvästi tilisi, mukaan lukien kaikki palvelimelle tallennetut tiedot. Poistamisen jälkeen käyttäjätunnuksesi on poissa käytöstä 7 päivään. Jos todella haluat jatkaa, vahvista salasanasi alla olevaan kenttään.",
@@ -143,13 +143,13 @@
"prefs_users_description_no_sync": "Käyttäjiä ja salasanoja ei ole synkronoitu tiliisi.", "prefs_users_description_no_sync": "Käyttäjiä ja salasanoja ei ole synkronoitu tiliisi.",
"account_tokens_dialog_title_edit": "Muokkaa käyttöoikeustunnusta", "account_tokens_dialog_title_edit": "Muokkaa käyttöoikeustunnusta",
"nav_button_publish_message": "Julkaise ilmoitus", "nav_button_publish_message": "Julkaise ilmoitus",
"prefs_users_table_base_url_header": "Palvelin-URL", "prefs_users_table_base_url_header": "Palvelun URL",
"notifications_click_copy_url_title": "Kopioi linkin URL-osoite leikepöydälle", "notifications_click_copy_url_title": "Kopioi linkin URL-osoite leikepöydälle",
"publish_dialog_attach_reset": "Poista liitteen URL-osoite", "publish_dialog_attach_reset": "Poista liitteen URL-osoite",
"account_upgrade_dialog_tier_features_messages_one": "{{messages}} päivittäisiä viestejä", "account_upgrade_dialog_tier_features_messages_one": "{{messages}} päivittäisiä viestejä",
"account_upgrade_dialog_reservations_warning_one": "Valittu taso sallii vähemmän varattuja topikeita kuin nykyinen tasosi. Ennen kuin muutat tasosi, <strong>poista vähintään yksi varaus</strong>. Voit poistaa varauksia <Link>Asetuksista</Link>.", "account_upgrade_dialog_reservations_warning_one": "Valittu taso sallii vähemmän varattuja topikeita kuin nykyinen tasosi. Ennen kuin muutat tasosi, <strong>poista vähintään yksi varaus</strong>. Voit poistaa varauksia <Link>Asetuksista</Link>.",
"common_copy_to_clipboard": "Kopioi leikkelepöydälle", "common_copy_to_clipboard": "Kopioi leikepöydälle",
"alert_not_supported_description": "Selaimesi ei tue ilmoituksia.", "alert_not_supported_description": "Selaimesi ei tue ilmoituksia",
"subscribe_dialog_error_topic_already_reserved": "Topikki on jo varattu", "subscribe_dialog_error_topic_already_reserved": "Topikki on jo varattu",
"message_bar_publish": "Julkaise viesti", "message_bar_publish": "Julkaise viesti",
"alert_grant_description": "Myönnä selaimelle lupa näyttää työpöytäilmoituksia.", "alert_grant_description": "Myönnä selaimelle lupa näyttää työpöytäilmoituksia.",
@@ -179,7 +179,7 @@
"prefs_notifications_sound_title": "Ilmoitusääni", "prefs_notifications_sound_title": "Ilmoitusääni",
"prefs_notifications_min_priority_default_and_higher": "Oletusprioriteetti ja korkeammat", "prefs_notifications_min_priority_default_and_higher": "Oletusprioriteetti ja korkeammat",
"prefs_reservations_table_access_header": "Oikeudet", "prefs_reservations_table_access_header": "Oikeudet",
"action_bar_show_menu": "Näytä menu", "action_bar_show_menu": "Näytä valikko",
"action_bar_settings": "Asetukset", "action_bar_settings": "Asetukset",
"notifications_copied_to_clipboard": "Kopioitu leikepöydälle", "notifications_copied_to_clipboard": "Kopioitu leikepöydälle",
"account_delete_dialog_button_cancel": "Peruuta", "account_delete_dialog_button_cancel": "Peruuta",
@@ -196,15 +196,15 @@
"publish_dialog_call_label": "Puhelu", "publish_dialog_call_label": "Puhelu",
"account_usage_calls_title": "Soitetut puhelut", "account_usage_calls_title": "Soitetut puhelut",
"error_boundary_description": "Näin ei selvästikään pitäisi tapahtua. Pahoittelut tästä.<br/>Jos sinulla on hetki aikaa, <githubLink>ilmoita tästä GitHubissa</githubLink> tai ilmoita meille <discordLink>Discordin</discordLink> tai <matrixLink>Matrix</matrixLink> kautta.", "error_boundary_description": "Näin ei selvästikään pitäisi tapahtua. Pahoittelut tästä.<br/>Jos sinulla on hetki aikaa, <githubLink>ilmoita tästä GitHubissa</githubLink> tai ilmoita meille <discordLink>Discordin</discordLink> tai <matrixLink>Matrix</matrixLink> kautta.",
"signup_form_toggle_password_visibility": "Vaihda salasanan näkyvyys", "signup_form_toggle_password_visibility": "Näytä/piilota salasana",
"login_link_signup": "Kirjautumislinkki", "login_link_signup": "Rekisteröidy",
"publish_dialog_message_label": "Viesti", "publish_dialog_message_label": "Viesti",
"publish_dialog_attached_file_title": "Liitetiedosto:", "publish_dialog_attached_file_title": "Liitetiedosto:",
"priority_min": "min", "priority_min": "min",
"action_bar_sign_in": "Kirjaudu sisään", "action_bar_sign_in": "Kirjaudu sisään",
"action_bar_unsubscribe": "Peruuta tilaus", "action_bar_unsubscribe": "Peruuta tilaus",
"account_basics_tier_basic": "Perus", "account_basics_tier_basic": "Perus",
"signup_title": "Lisää ntfy tili", "signup_title": "Luo ntfy-tili",
"prefs_notifications_min_priority_description_any": "Näytetään kaikki ilmoitukset tärkeydestä riippumatta", "prefs_notifications_min_priority_description_any": "Näytetään kaikki ilmoitukset tärkeydestä riippumatta",
"error_boundary_gathering_info": "Kerää lisätietoja…", "error_boundary_gathering_info": "Kerää lisätietoja…",
"publish_dialog_priority_max": "Max. prioriteetti", "publish_dialog_priority_max": "Max. prioriteetti",
@@ -285,7 +285,7 @@
"account_basics_phone_numbers_title": "Puhelinnumerot", "account_basics_phone_numbers_title": "Puhelinnumerot",
"prefs_notifications_delete_after_title": "Poista ilmoitukset", "prefs_notifications_delete_after_title": "Poista ilmoitukset",
"account_upgrade_dialog_interval_yearly_discount_save": "säästä {{discount}}%", "account_upgrade_dialog_interval_yearly_discount_save": "säästä {{discount}}%",
"signup_disabled": "Kirjautuminen estetty", "signup_disabled": "Rekisteröityminen estetty",
"publish_dialog_drop_file_here": "Pudota tiedosto tähän", "publish_dialog_drop_file_here": "Pudota tiedosto tähän",
"prefs_users_dialog_title_edit": "Muokkaa käyttäjää", "prefs_users_dialog_title_edit": "Muokkaa käyttäjää",
"account_basics_password_dialog_current_password_label": "Nykyinen salasana", "account_basics_password_dialog_current_password_label": "Nykyinen salasana",
@@ -295,7 +295,7 @@
"account_upgrade_dialog_tier_features_attachment_total_size": "{{totalsize}} lopullinen tiedostokoko", "account_upgrade_dialog_tier_features_attachment_total_size": "{{totalsize}} lopullinen tiedostokoko",
"publish_dialog_title_label": "Otsikko", "publish_dialog_title_label": "Otsikko",
"prefs_reservations_table_everyone_write_only": "Minä voin julkaista ja tilata, kaikki voivat julkaista", "prefs_reservations_table_everyone_write_only": "Minä voin julkaista ja tilata, kaikki voivat julkaista",
"prefs_appearance_title": "Näkymä", "prefs_appearance_title": "Ulkoasu",
"publish_dialog_topic_reset": "Resetoi topikki", "publish_dialog_topic_reset": "Resetoi topikki",
"account_tokens_table_cannot_delete_or_edit": "Nykyistä istuntotunnusta ei voi muokata tai poistaa", "account_tokens_table_cannot_delete_or_edit": "Nykyistä istuntotunnusta ei voi muokata tai poistaa",
"notifications_tags": "Tagit", "notifications_tags": "Tagit",
@@ -338,7 +338,7 @@
"login_title": "Kirjaudu sisään ntfy-tilillesi", "login_title": "Kirjaudu sisään ntfy-tilillesi",
"notifications_list": "Ilmoitusluettelo", "notifications_list": "Ilmoitusluettelo",
"common_save": "Tallenna", "common_save": "Tallenna",
"prefs_users_dialog_base_url_label": "Palvelin URL, esim. https://ntfy.sh", "prefs_users_dialog_base_url_label": "Palvelun URL, esim. https://ntfy.sh",
"account_usage_emails_title": "Sähköpostit lähetetty", "account_usage_emails_title": "Sähköpostit lähetetty",
"account_basics_phone_numbers_dialog_channel_sms": "SMS", "account_basics_phone_numbers_dialog_channel_sms": "SMS",
"action_bar_reservation_add": "Varalla oleva aihe", "action_bar_reservation_add": "Varalla oleva aihe",
@@ -365,20 +365,40 @@
"notifications_no_subscriptions_title": "Näyttää siltä, että sinulla ei ole vielä tilauksia.", "notifications_no_subscriptions_title": "Näyttää siltä, että sinulla ei ole vielä tilauksia.",
"notifications_none_for_topic_title": "Et ole vielä saanut ilmoituksia tästä aiheesta.", "notifications_none_for_topic_title": "Et ole vielä saanut ilmoituksia tästä aiheesta.",
"notifications_actions_http_request_title": "Lähetä HTTP {{method}} osoitteeseen {{url}}", "notifications_actions_http_request_title": "Lähetä HTTP {{method}} osoitteeseen {{url}}",
"reserve_dialog_checkbox_label": "Käänteinen aihe ja aseta pääsy", "reserve_dialog_checkbox_label": "Varaa aihe ja aseta pääsy",
"publish_dialog_progress_uploading": "Lähetetään …", "publish_dialog_progress_uploading": "Lähetetään …",
"publish_dialog_title_no_topic": "Julkaise ilmoitus", "publish_dialog_title_no_topic": "Julkaise ilmoitus",
"notifications_example": "Esimerkki", "notifications_example": "Esimerkki",
"notifications_loading": "Ladataan ilmoituksia …", "notifications_loading": "Ladataan ilmoituksia…",
"notifications_no_subscriptions_description": "Klikkaa \"{{linktext}}\" linkkiä luodaksesi tai tilataksesi aihe. Sen jälkeen voit lähettää viestejä PUT tai POST metodeilla ja saat ilmoituksesi täällä.", "notifications_no_subscriptions_description": "Klikkaa \"{{linktext}}\" linkkiä luodaksesi tai tilataksesi aihe. Sen jälkeen voit lähettää viestejä PUT tai POST metodeilla ja saat ilmoituksesi täällä.",
"display_name_dialog_description": "Aseta vaihtoehtoinen nimi aiheelle, joka on näytetty tilaus-listassa. Tämä auttaa tunnistamaan aiheet helpommin, joilla on hankalat nimet.", "display_name_dialog_description": "Aseta vaihtoehtoinen nimi aiheelle, joka on näytetty tilaus-listassa. Tämä auttaa tunnistamaan aiheet helpommin, joilla on hankalat nimet.",
"publish_dialog_message_published": "Ilmoitus julkaistu", "publish_dialog_message_published": "Ilmoitus julkaistu",
"notifications_more_details": "Saadaksesi lisää tietoa, katso <websiteLink>nettisivu</websiteLink> tai <docsLink>documentointi</docsLink>.", "notifications_more_details": "Saadaksesi lisää tietoa, katso <websiteLink>verkkosivusto</websiteLink> tai <docsLink>dokumentaatio</docsLink>.",
"publish_dialog_attachment_limits_quota_reached": "ylittää kiintiön, {{remainingBytes}} jäljellä", "publish_dialog_attachment_limits_quota_reached": "ylittää kiintiön, {{remainingBytes}} jäljellä",
"publish_dialog_title_topic": "Julkaise aiheeseen {{topic}}", "publish_dialog_title_topic": "Julkaise aiheeseen {{topic}}",
"display_name_dialog_placeholder": "Näyttönimi", "display_name_dialog_placeholder": "Näyttönimi",
"publish_dialog_attachment_limits_file_and_quota_reached": "ylittää {{fileSizeLimit}} tiedostokoon rajan ja määrän, {{remainingBytes}} jäljellä", "publish_dialog_attachment_limits_file_and_quota_reached": "ylittää {{fileSizeLimit}} tiedostokoon rajan ja määrän, {{remainingBytes}} jäljellä",
"publish_dialog_attachment_limits_file_reached": "ylittää {{fileSizeLimit}} tiedostokoon rajan", "publish_dialog_attachment_limits_file_reached": "ylittää {{fileSizeLimit}} tiedostokoon rajan",
"publish_dialog_progress_uploading_detail": "Lähetetään {{loaded}}/{{total}} ({{percent}}%) …", "publish_dialog_progress_uploading_detail": "Lähetetään {{loaded}}/{{total}} ({{percent}}%) …",
"display_name_dialog_title": "Vaihda näyttönimi" "display_name_dialog_title": "Vaihda näyttönimi",
"action_bar_mute_notifications": "Mykistä ilmoitukset",
"action_bar_unmute_notifications": "Poista ilmoitusten mykistys",
"alert_notification_permission_required_title": "Ilmoitukset eivät ole käytössä",
"alert_notification_permission_required_description": "Anna selaimelle lupa näyttää työpöytäilmoituksia",
"alert_notification_permission_required_button": "Myönnä lupa nyt",
"alert_notification_permission_denied_title": "Ilmoitukset on estetty",
"alert_notification_ios_install_required_title": "iOS-asennus vaaditaan",
"publish_dialog_checkbox_markdown": "Muotoile Markdownina",
"prefs_notifications_web_push_title": "Taustailmoitukset",
"prefs_appearance_theme_system": "Järjestelmä (oletus)",
"alert_notification_permission_denied_description": "Ota ilmoitukset uudelleen käyttöön selaimessa",
"prefs_appearance_theme_title": "Teema",
"prefs_appearance_theme_light": "Vaalea tila",
"prefs_notifications_web_push_enabled": "Käytössä palvelimelle {{server}}",
"prefs_notifications_web_push_disabled": "Pois käytöstä",
"prefs_appearance_theme_dark": "Tumma tila",
"error_boundary_button_reload_ntfy": "Lataa ntfy uudelleen",
"web_push_subscription_expiring_title": "Ilmoitukset keskeytetään",
"web_push_subscription_expiring_body": "Avaa ntfy jatkaaksesi ilmoitusten vastaanottamista",
"web_push_unknown_notification_title": "Tuntematon ilmoitus vastaanotettu palvelimelta"
} }

View File

@@ -18,7 +18,7 @@
"alert_notification_permission_required_title": "Le notifiche sono disabilitate", "alert_notification_permission_required_title": "Le notifiche sono disabilitate",
"alert_notification_permission_required_button": "Concedi ora", "alert_notification_permission_required_button": "Concedi ora",
"notifications_list": "Elenco notifiche", "notifications_list": "Elenco notifiche",
"notifications_list_item": "Notifiche", "notifications_list_item": "Notifica",
"notifications_mark_read": "Segna come letto", "notifications_mark_read": "Segna come letto",
"notifications_delete": "Elimina", "notifications_delete": "Elimina",
"notifications_copied_to_clipboard": "Copiato negli appunti", "notifications_copied_to_clipboard": "Copiato negli appunti",
@@ -152,10 +152,10 @@
"error_boundary_unsupported_indexeddb_title": "Navigazione privata non supportata", "error_boundary_unsupported_indexeddb_title": "Navigazione privata non supportata",
"action_bar_show_menu": "Mostra menu", "action_bar_show_menu": "Mostra menu",
"action_bar_send_test_notification": "Inviare una notifica di prova", "action_bar_send_test_notification": "Inviare una notifica di prova",
"alert_not_supported_description": "Le notifiche non sono supportate nel tuo browser.", "alert_not_supported_description": "Le notifiche non sono supportate nel tuo browser",
"nav_button_documentation": "Documentazione", "nav_button_documentation": "Documentazione",
"notifications_actions_http_request_title": "Invia HTTP {{method}} a {{url}}", "notifications_actions_http_request_title": "Invia HTTP {{method}} a {{url}}",
"alert_notification_permission_required_description": "Concedi al tuo browser l'autorizzazione a visualizzare le notifiche sul desktop.", "alert_notification_permission_required_description": "Concedi al tuo browser l'autorizzazione a visualizzare le notifiche sul desktop",
"alert_not_supported_title": "Notifiche non supportate", "alert_not_supported_title": "Notifiche non supportate",
"notifications_attachment_file_app": "file app Android", "notifications_attachment_file_app": "file app Android",
"notifications_no_subscriptions_description": "Fai clic sul link \"{{linktext}}\" per creare o iscriverti a un topic. Successivamente, puoi inviare messaggi tramite PUT o POST e riceverai le notifiche qui.", "notifications_no_subscriptions_description": "Fai clic sul link \"{{linktext}}\" per creare o iscriverti a un topic. Successivamente, puoi inviare messaggi tramite PUT o POST e riceverai le notifiche qui.",
@@ -307,5 +307,14 @@
"account_delete_dialog_label": "Password", "account_delete_dialog_label": "Password",
"account_upgrade_dialog_tier_features_no_reservations": "Nessun argomento riservato", "account_upgrade_dialog_tier_features_no_reservations": "Nessun argomento riservato",
"account_upgrade_dialog_tier_features_messages_one": "{{messages}} messaggi giornalieri", "account_upgrade_dialog_tier_features_messages_one": "{{messages}} messaggi giornalieri",
"account_upgrade_dialog_reservations_warning_one": "Il livello selezionato consente meno argomenti riservati rispetto al livello corrente. Prima di cambiare il livello, <strong> si prega di eliminare almeno una prenotazione</strong>. È possibile rimuovere le prenotazioni nel <Link>Impostazioni</Link>." "account_upgrade_dialog_reservations_warning_one": "Il livello selezionato consente meno argomenti riservati rispetto al livello corrente. Prima di cambiare il livello, <strong> si prega di eliminare almeno una prenotazione</strong>. È possibile rimuovere le prenotazioni nel <Link>Impostazioni</Link>.",
"alert_notification_permission_denied_title": "Le notifiche sono bloccate",
"alert_notification_permission_denied_description": "Per favore riabilitale nel tuo browser",
"subscribe_dialog_subscribe_use_another_background_info": "Le notifiche dagli altri server non saranno ricevute quando la web app non è in esecuzione",
"error_boundary_button_reload_ntfy": "Ricarica ntfy",
"action_bar_mute_notifications": "Silenzia notifiche",
"action_bar_unmute_notifications": "Riattiva audio notifiche",
"alert_notification_ios_install_required_title": "E' richiesta l'installazione di iOS",
"alert_notification_ios_install_required_description": "Fare clic sull'icona Condividi e Aggiungi alla schermata home per abilitare le notifiche su iOS",
"publish_dialog_checkbox_markdown": "Formatta come markdown"
} }

View File

@@ -0,0 +1,190 @@
{
"signup_disabled": "Pendaftaran dilumpuhkan",
"signup_error_username_taken": "Nama pengguna {{username}} telah digunakan",
"signup_error_creation_limit_reached": "Pendaftaran sudah melebihi had",
"login_form_button_submit": "Log masuk",
"login_disabled": "Log masuk dilumpuhkan",
"action_bar_show_menu": "Tunjuk menu",
"action_bar_logo_alt": "logo ntfy",
"action_bar_settings": "Tetapan",
"action_bar_account": "Akaun",
"action_bar_change_display_name": "Tukar nama paparan",
"action_bar_reservation_add": "Tempah topik",
"action_bar_reservation_edit": "Tukar tempahan",
"action_bar_reservation_delete": "Batalkan tempahan",
"action_bar_reservation_limit_reached": "Melebihi had",
"action_bar_mute_notifications": "Senyapkan notifikasi",
"action_bar_toggle_action_menu": "Buka/tutup menu aksi",
"action_bar_profile_settings": "Tetapan",
"action_bar_profile_logout": "Log keluar",
"action_bar_sign_in": "Log masuk",
"action_bar_sign_up": "Daftar",
"message_bar_type_message": "Tulis mesej disini",
"message_bar_show_dialog": "Tunjuk dialog terterbit",
"message_bar_publish": "Hantar mesej",
"nav_topics_title": "Topik terlanggan",
"nav_button_all_notifications": "Semua notifikasi",
"nav_button_account": "Akaun",
"nav_button_settings": "Tetapan",
"nav_button_documentation": "Dokumentasi",
"nav_button_publish_message": "Terbitkan notifikasi",
"nav_button_subscribe": "Melanggan topik",
"nav_button_muted": "Notifikasi disenyapkan",
"nav_button_connecting": "menyambung",
"nav_upgrade_banner_label": "Naik taraf kepada ntfy Pro",
"nav_upgrade_banner_description": "Tempah topik, lebih banyak mesej & e-mel dan lampiran yang lebih besar",
"alert_notification_permission_required_button": "Benarkan",
"alert_notification_permission_denied_description": "Sila benarkan semula di pelayar anda",
"alert_notification_ios_install_required_title": "Perlukan muatan iOS",
"notifications_tags": "Tag",
"notifications_priority_x": "Keutamaan {{priority}}",
"notifications_new_indicator": "Notifikasi baharu",
"notifications_attachment_copy_url_button": "Salin URL",
"notifications_attachment_link_expires": "pautan tamat tempoh pada {{date}}",
"notifications_attachment_link_expired": "link muat turun telah tamat tempoh",
"notifications_attachment_file_image": "fail imej",
"notifications_attachment_file_video": "fail video",
"notifications_attachment_file_audio": "fail audio",
"notifications_attachment_file_app": "Fail aplikasi Android",
"notifications_attachment_file_document": "lain-lain dokumen",
"notifications_click_copy_url_title": "Salin pautan URL ke papan klip",
"notifications_click_copy_url_button": "Salin pautan",
"notifications_click_open_button": "Buka pautan",
"notifications_actions_open_url_title": "Pergi ke {{url}}",
"notifications_actions_not_supported": "Tindakan tidak disokong di aplikasi web",
"notifications_actions_http_request_title": "Hantar {{method}} HTTP ke {{url}}",
"notifications_actions_failed_notification": "Tindakan tidak berjaya",
"notifications_none_for_topic_title": "Anda belum menerima sebarang pemberitahuan untuk topik ini lagi.",
"notifications_example": "Contoh",
"display_name_dialog_title": "Tukar nama paparan",
"display_name_dialog_placeholder": "Nama paparan",
"common_cancel": "Batal",
"common_back": "Kembali",
"common_save": "Simpan",
"common_add": "Tambah",
"signup_form_toggle_password_visibility": "Tunjuk/sembunyikan kata laluan",
"action_bar_send_test_notification": "Hantar notifikasi percubaan",
"action_bar_toggle_mute": "Senyap/nyahsenyapkan notifikasi",
"common_copy_to_clipboard": "Salin ke papan klip",
"signup_title": "Cipta akaun baru ntfy",
"login_link_signup": "Daftar",
"signup_form_username": "Nama pengguna",
"signup_form_confirm_password": "Pengesahan kata laluan",
"signup_already_have_account": "Sudah daftar? Log masuk disini!",
"action_bar_clear_notifications": "Padam semua notifikasi",
"signup_form_password": "Kata laluan",
"signup_form_button_submit": "Daftar",
"login_title": "Log masuk ke akaun ntfy",
"action_bar_unmute_notifications": "Nyahsenyapkan notifikasi",
"action_bar_unsubscribe": "Nyahlanggan",
"action_bar_profile_title": "Profil",
"message_bar_error_publishing": "Ralat menerbitkan notifikasi",
"alert_notification_permission_required_title": "Notifikasi telah dinyahkan",
"notifications_mark_read": "Tanda sebagai telah dibaca",
"alert_notification_permission_required_description": "Berikan kebenaran pelayar anda untuk memaparkan pemberitahuan desktop",
"alert_notification_permission_denied_title": "Notifikasi disekat",
"notifications_delete": "Padam",
"notifications_copied_to_clipboard": "Salin ke papan klip",
"notifications_attachment_image": "Imej lampiran",
"alert_notification_ios_install_required_description": "Klik pada ikon Kongsi dan Tambah ke Skrin Utama untuk membenarkan pemberitahuan pada iOS",
"alert_not_supported_title": "Notifikasi tidak disokong",
"alert_not_supported_description": "Notifikasi tidak disokong di pelayar anda",
"notifications_list": "Senarai notifikasi",
"notifications_list_item": "Notifikasi",
"notifications_attachment_copy_url_title": "Salin URL lampiran ke papan klip",
"notifications_attachment_open_title": "Pergi ke {{url}}",
"notifications_attachment_open_button": "Buka lampiran",
"notifications_none_for_topic_description": "Untuk menghantar pemberitahuan kepada topik ini, hanya PUT atau POST ke URL topik.",
"notifications_no_subscriptions_title": "Nampaknya anda belum mempunyai sebarang langganan lagi.",
"notifications_none_for_any_title": "Anda tidak menerima sebarang notifikasi.",
"notifications_none_for_any_description": "Untuk menghantar pemberitahuan kepada topik, hanya PUT atau POST ke URL topik. Berikut ialah contoh menggunakan salah satu topik anda.",
"account_basics_phone_numbers_copied_to_clipboard": "Nombor telefon disalin ke papan klip",
"account_basics_phone_numbers_dialog_verify_button_sms": "Hantar SMS",
"account_basics_phone_numbers_dialog_verify_button_call": "Telefon diri sendiri",
"account_basics_phone_numbers_dialog_code_label": "Kod verifikasi",
"account_basics_phone_numbers_dialog_channel_call": "Panggil",
"account_usage_title": "Penggunaan",
"account_usage_of_limit": ": {{limit}}",
"account_usage_unlimited": "Tanpa had",
"account_usage_limits_reset_daily": "Had penggunaan akan di set semula pada tengah malam (UTC)",
"account_basics_tier_title": "Jenis akaun",
"account_basics_tier_description": "Tahap kekuatan akaun anda",
"account_basics_tier_admin_suffix_with_tier": "(dengan peringkat {{tier}})",
"account_basics_tier_admin_suffix_no_tier": "(tiada peringkat)",
"account_basics_tier_basic": "Asas",
"account_basics_tier_free": "Percuma",
"account_basics_tier_change_button": "Ubah",
"account_delete_title": "Padam akaun",
"account_upgrade_dialog_tier_features_calls_other": "{{calls}} paggilan harian",
"account_upgrade_dialog_tier_features_no_calls": "Tiada panggilan",
"account_upgrade_dialog_tier_price_per_month": "bulan",
"account_tokens_table_token_header": "Token",
"account_tokens_table_label_header": "Tahap",
"account_tokens_table_never_expires": "Tidak pernah luput",
"account_tokens_table_expires_header": "Luput",
"account_tokens_table_current_session": "Sesi pelayar semasa",
"account_tokens_table_copied_to_clipboard": "Token akses telah disalin",
"account_tokens_table_cannot_delete_or_edit": "TIdak boleh ubah atau padam token sesi semasa",
"account_basics_phone_numbers_dialog_title": "Tambah nombor telefon",
"account_basics_phone_numbers_dialog_number_label": "Nombor telefon",
"account_basics_phone_numbers_dialog_number_placeholder": "cth: +1222333444",
"account_basics_phone_numbers_dialog_code_placeholder": "cth: 123456",
"account_basics_tier_admin": "Pengurus",
"account_basics_phone_numbers_dialog_check_verification_button": "Kod pengesahan",
"account_basics_phone_numbers_dialog_channel_sms": "SMS",
"account_basics_tier_interval_monthly": "bulanan",
"account_basics_tier_interval_yearly": "tahunan",
"account_basics_tier_upgrade_button": "Naik taraf ke Pro",
"account_basics_tier_manage_billing_button": "Urus cara pembayaran",
"account_basics_tier_paid_until": "Langganan telah dibayar sehingga {{date}}, dan akan diperbaharui secara automatik",
"account_basics_tier_payment_overdue": "Bayaran anda tertunggak. Sila kemas kini kaedah pembayaran anda atau akaun anda akan diturunkan tidak lama lagi.",
"account_basics_tier_canceled_subscription": "Langganan anda telah dibatalkan dan akan diturunkan taraf kepada akaun percuma pada {{date}}.",
"account_usage_attachment_storage_description": "{{filesize}} setiap fail, akan dipadam selepas {{expiry}}",
"account_upgrade_dialog_interval_monthly": "Bulanan",
"account_usage_messages_title": "Mesej yang telah diterbitkan",
"account_usage_emails_title": "Email telah dihantar",
"account_usage_calls_title": "Panggilan telefon",
"account_usage_calls_none": "Tiada panggilan telefon boleh dibuat dengan akaun ini",
"account_usage_reservations_none": "Tiada topik simpanan untuk akaun ini",
"account_usage_reservations_title": "Topik simpanan",
"account_usage_attachment_storage_title": "Simpanan lampiran",
"account_delete_dialog_button_cancel": "Batal",
"account_usage_cannot_create_portal_session": "Tidak dapat membuka portal pengebilan",
"account_delete_description": "Padam akaun selamanya",
"account_delete_dialog_label": "Kata laluan",
"account_delete_dialog_button_submit": "Padamkan akaun secara kekal",
"account_upgrade_dialog_title": "Tukar peringkat akaun",
"account_delete_dialog_description": "Ini akan memadamkan akaun anda secara kekal, termasuk semua data yang disimpan pada pelayan. Selepas pemadaman, nama pengguna anda tidak akan tersedia selama 7 hari. Jika anda benar-benar mahu meneruskan, sila sahkan dengan kata laluan anda dalam kotak di bawah.",
"account_upgrade_dialog_interval_yearly": "Tahunan",
"account_delete_dialog_billing_warning": "Memadamkan akaun anda turut membatalkan langganan pengebilan anda serta-merta. Anda tidak akan mempunyai akses kepada papan pemuka pengebilan lagi.",
"account_upgrade_dialog_interval_yearly_discount_save": "jimat {{discount}}%",
"account_upgrade_dialog_interval_yearly_discount_save_up_to": "jimat sehingga {{discount}}%",
"account_upgrade_dialog_cancel_warning": "Ini akan <strong>membatalkan langganan anda</strong> dan menurunkan taraf akaun anda pada {{date}}. Pada tarikh tersebut, tempahan topik serta mesej yang dicache pada pelayan <strong>akan dipadamkan</strong>.",
"account_upgrade_dialog_tier_features_emails_one": "{{emails}} email harian",
"account_upgrade_dialog_proration_info": "<strong>Tambahan</strong>: Apabila menaik taraf antara pelan berbayar, perbezaan harga akan <strong>caj serta-merta</strong>. Apabila menurunkan taraf kepada peringkat yang lebih rendah, baki akan digunakan untuk membayar bagi tempoh pengebilan akan datang.",
"account_tokens_table_create_token_button": "Cipta token akses",
"account_tokens_table_last_origin_tooltip": "Daripada alamat IP {{ip}}, klik untuk mencari",
"account_upgrade_dialog_tier_features_reservations_one": "{{reservation}} topik tersimpan",
"account_upgrade_dialog_tier_features_messages_one": "{{messages}} mesej harian",
"account_upgrade_dialog_tier_features_reservations_other": "{{reservation}} topik tersimpan",
"account_upgrade_dialog_tier_features_messages_other": "{{messages}} mesej harian",
"account_upgrade_dialog_tier_features_no_reservations": "Tiada topik tersimpan",
"account_upgrade_dialog_tier_features_emails_other": "{{emails}} email harian",
"account_upgrade_dialog_tier_features_attachment_file_size": "{{filesize}} setiap fail",
"account_upgrade_dialog_tier_features_calls_one": "{{calls}} paggilan harian",
"account_upgrade_dialog_tier_features_attachment_total_size": "{{totalsize}} jumlah simpanan",
"account_upgrade_dialog_tier_price_billed_monthly": "{{price}} setahun. Dibilkan setiap bulan.",
"account_upgrade_dialog_tier_selected_label": "Pilih",
"account_upgrade_dialog_tier_price_billed_yearly": "{{price}} dibilkan setiap tahun. Jimat {{simpan}}.",
"account_upgrade_dialog_tier_current_label": "Semasa",
"account_upgrade_dialog_billing_contact_website": "Untuk pertanyaan pengebilan, sila rujuk <Link>laman web</Link> kami.",
"account_upgrade_dialog_button_cancel": "Batal",
"account_upgrade_dialog_billing_contact_email": "Untuk pertanyaan pengebilan, sila <Link>hubungi kami</Link> secara terus.",
"account_upgrade_dialog_button_redirect_signup": "Daftar sekarang",
"account_upgrade_dialog_button_cancel_subscription": "Batalkan langganan",
"account_upgrade_dialog_button_update_subscription": "Kemas kini langganan",
"account_upgrade_dialog_button_pay_now": "Bayar sekarang dan langgan",
"account_tokens_title": "Token akses",
"account_tokens_description": "Gunakan token akses semasa menerbitkan dan melanggan melalui API ntfy, jadi anda tidak perlu menghantar bukti kelayakan akaun anda. Lihat <Link>dokumentasi</Link> untuk mengetahui lebih lanjut.",
"account_tokens_table_last_access_header": "Akses terakhir"
}

View File

@@ -19,7 +19,7 @@
"alert_notification_permission_required_description": "Conceder permissão ao seu navegador para mostrar notificações.", "alert_notification_permission_required_description": "Conceder permissão ao seu navegador para mostrar notificações.",
"alert_not_supported_title": "Notificações não suportadas", "alert_not_supported_title": "Notificações não suportadas",
"notifications_list": "Lista de notificações", "notifications_list": "Lista de notificações",
"alert_not_supported_description": "As notificações não são suportadas pelo seu navegador.", "alert_not_supported_description": "As notificações não são suportadas pelo seu navegador",
"notifications_list_item": "Notificação", "notifications_list_item": "Notificação",
"notifications_mark_read": "Marcar como lido", "notifications_mark_read": "Marcar como lido",
"notifications_delete": "Apagar", "notifications_delete": "Apagar",
@@ -226,5 +226,69 @@
"publish_dialog_call_placeholder": "Número de telefone para ligar com a mensagem, ex: +12223334444, ou 'Sim'", "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_call_reset": "Remover chamada telefônica",
"publish_dialog_chip_call_label": "Chamada telefônica", "publish_dialog_chip_call_label": "Chamada telefônica",
"subscribe_dialog_subscribe_button_generate_topic_name": "Gerar nome" "subscribe_dialog_subscribe_button_generate_topic_name": "Gerar nome",
"action_bar_unmute_notifications": "Restaurar notificações",
"alert_notification_ios_install_required_description": "Clique no ícone Compartilhar e Adicionar à Tela Inicial para ativar as notificações no iOS",
"publish_dialog_checkbox_markdown": "Formatar como Markdown",
"publish_dialog_chip_call_no_verified_numbers_tooltip": "Números de telefone não verificados",
"subscribe_dialog_error_topic_already_reserved": "Tópico já está reservado",
"action_bar_mute_notifications": "Silenciar notificações",
"alert_notification_permission_denied_title": "Notificações estão bloqueadas",
"alert_notification_permission_denied_description": "Por favor reative-as em seu navegador",
"alert_notification_ios_install_required_title": "Requer instalação em iOS",
"notifications_actions_failed_notification": "Houve uma falha na ação",
"publish_dialog_call_item": "Ligar para o número {{number}}",
"subscribe_dialog_subscribe_use_another_background_info": "Notificações de outros servidores não serão recebidas enquanto o aplicativo web não estiver aberto",
"account_basics_username_description": "Olá, é você ❤",
"account_basics_password_dialog_new_password_label": "Nova senha",
"account_basics_password_dialog_current_password_incorrect": "Senha incorreta",
"account_basics_phone_numbers_title": "Números de telefone",
"account_basics_phone_numbers_dialog_description": "Para utilizar o recurso de notificação por ligação, você precisa adicionar e verificar pelo menos um número de telefone. A verificação poderá ser feita via SMS ou ligação telefônica.",
"account_basics_phone_numbers_dialog_title": "Adicionar número de telefone",
"account_basics_phone_numbers_dialog_verify_button_call": "Ligue me",
"account_basics_phone_numbers_dialog_number_label": "Número de telefone",
"account_basics_phone_numbers_dialog_number_placeholder": "ex.: +1222333444",
"account_basics_phone_numbers_dialog_verify_button_sms": "Enviar SMS",
"account_basics_phone_numbers_dialog_code_placeholder": "ex.: 123456",
"account_basics_phone_numbers_dialog_code_label": "Código de verificação",
"account_basics_phone_numbers_dialog_check_verification_button": "Código de confirmação",
"account_basics_phone_numbers_dialog_channel_call": "Ligação",
"account_basics_tier_canceled_subscription": "Sua assinatura foi cancelada e será rebaixada para uma conta gratuita em {[data}}.",
"account_basics_tier_manage_billing_button": "Gerenciar cobrança",
"account_usage_reservations_none": "Esta conta não possui tópicos reservados",
"account_usage_attachment_storage_title": "Armazenamento de anexos",
"account_usage_emails_title": "E-mails enviados",
"account_basics_password_description": "Alterar a senha da sua conta",
"account_basics_password_dialog_title": "Alterar a senha",
"account_basics_phone_numbers_description": "Para notificações por ligação",
"account_basics_tier_paid_until": "Assinatura paga até {{date}}, e será renovada automaticamente",
"account_basics_password_dialog_confirm_password_label": "Confirmar senha",
"account_basics_password_dialog_button_submit": "Alterar senha",
"account_basics_title": "Conta",
"account_basics_username_admin_tooltip": "Você é Administrador",
"account_basics_password_title": "Senha",
"account_basics_password_dialog_current_password_label": "Senha atual",
"account_basics_phone_numbers_no_phone_numbers_yet": "Nenhum número de telefone",
"account_basics_phone_numbers_copied_to_clipboard": "Telefones copiados para área de transferência",
"account_basics_phone_numbers_dialog_channel_sms": "SMS",
"account_usage_title": "Uso",
"account_usage_of_limit": "de {{limit}}",
"account_usage_unlimited": "Ilimitado",
"account_usage_limits_reset_daily": "Limites de uso são resetados diariamente à meia noite (UTC)",
"account_basics_tier_title": "Tipo de conta",
"account_basics_tier_description": "Nível da sua conta",
"account_basics_tier_admin": "Administrador",
"account_basics_tier_admin_suffix_with_tier": "(com {{tier}} classe)",
"account_basics_tier_admin_suffix_no_tier": "(sem classe)",
"account_basics_tier_basic": "Básico",
"account_basics_tier_free": "Grátis",
"account_basics_tier_interval_monthly": "Mensalmente",
"account_basics_tier_interval_yearly": "anualmente",
"account_basics_tier_upgrade_button": "Atualizar para o Pro",
"account_basics_tier_change_button": "Alterar",
"account_basics_tier_payment_overdue": "Seu pagamento está em atraso. Por favor atualize seu método de pagamento, ou sua conta será rebaixada em breve.",
"account_usage_messages_title": "Mensagens publicadas",
"account_usage_calls_title": "Ligações realizadas",
"account_usage_calls_none": "Esta conta não pode realizar ligações",
"account_usage_reservations_title": "Tópicos reservados"
} }

View File

@@ -11,7 +11,7 @@
"alert_notification_permission_required_description": "Conceder ao navegador permissão para mostrar notificações.", "alert_notification_permission_required_description": "Conceder ao navegador permissão para mostrar notificações.",
"alert_notification_permission_required_button": "Conceder agora", "alert_notification_permission_required_button": "Conceder agora",
"alert_not_supported_title": "Notificações não são suportadas", "alert_not_supported_title": "Notificações não são suportadas",
"alert_not_supported_description": "Notificações não são suportadas pelo seu navagador.", "alert_not_supported_description": "Notificações não são suportadas pelo seu navegador.",
"notifications_copied_to_clipboard": "Copiado para a área de transferência", "notifications_copied_to_clipboard": "Copiado para a área de transferência",
"notifications_tags": "Etiquetas", "notifications_tags": "Etiquetas",
"notifications_attachment_copy_url_title": "Copiar URL do anexo para a área de transferência", "notifications_attachment_copy_url_title": "Copiar URL do anexo para a área de transferência",
@@ -317,5 +317,9 @@
"account_upgrade_dialog_tier_features_reservations_one": "{{reservations}} tópico reservado", "account_upgrade_dialog_tier_features_reservations_one": "{{reservations}} tópico reservado",
"account_upgrade_dialog_tier_features_reservations_other": "{{reservations}} tópicos reservados", "account_upgrade_dialog_tier_features_reservations_other": "{{reservations}} tópicos reservados",
"account_upgrade_dialog_tier_features_emails_other": "{{emails}} emails diários", "account_upgrade_dialog_tier_features_emails_other": "{{emails}} emails diários",
"account_upgrade_dialog_tier_features_messages_other": "{{messages}} mensagens diárias" "account_upgrade_dialog_tier_features_messages_other": "{{messages}} mensagens diárias",
"account_upgrade_dialog_tier_current_label": "Atual",
"account_upgrade_dialog_tier_price_per_month": "mês",
"account_upgrade_dialog_button_cancel": "Cancelar",
"account_upgrade_dialog_tier_selected_label": "Selecionado"
} }

View File

@@ -38,8 +38,8 @@
"notifications_attachment_link_expires": "länken utgår {{date}}", "notifications_attachment_link_expires": "länken utgår {{date}}",
"notifications_attachment_file_image": "bildfil", "notifications_attachment_file_image": "bildfil",
"notifications_attachment_file_audio": "ljudfil", "notifications_attachment_file_audio": "ljudfil",
"alert_notification_permission_required_description": "Ge din webbläsare behörighet att visa skrivbordsnotiser.", "alert_notification_permission_required_description": "Ge din webbläsare behörighet att visa skrivbordsnotiser",
"alert_not_supported_description": "Notiser stöds inte i din webbläsare.", "alert_not_supported_description": "Notiser stöds inte i din webbläsare",
"notifications_mark_read": "Markera som läst", "notifications_mark_read": "Markera som läst",
"notifications_attachment_file_video": "videofil", "notifications_attachment_file_video": "videofil",
"notifications_click_copy_url_button": "Kopiera länk", "notifications_click_copy_url_button": "Kopiera länk",
@@ -387,5 +387,21 @@
"alert_notification_ios_install_required_title": "iOS installation krävs", "alert_notification_ios_install_required_title": "iOS installation krävs",
"notifications_actions_failed_notification": "Misslyckad åtgärd", "notifications_actions_failed_notification": "Misslyckad åtgärd",
"alert_notification_permission_denied_title": "Notifieringar är blockerade", "alert_notification_permission_denied_title": "Notifieringar är blockerade",
"alert_notification_ios_install_required_description": "Klicka på delaikonen och Lägg till på hemskärmen för att aktivera notifieringarna i iOS" "alert_notification_ios_install_required_description": "Klicka på delaikonen och Lägg till på hemskärmen för att aktivera notifieringarna i iOS",
"publish_dialog_checkbox_markdown": "Formatera som Markdown",
"subscribe_dialog_subscribe_use_another_background_info": "Meddelanden från andra servrar kommer inte att tas emot när webbappen inte är öppen",
"prefs_notifications_web_push_title": "Bakgrundsnotifikationer",
"prefs_notifications_web_push_enabled_description": "Meddelanden tas emot även när webbappen inte körs (via Web Push)",
"prefs_notifications_web_push_enabled": "Aktivera för {{server}}",
"prefs_notifications_web_push_disabled": "Avaktivera",
"prefs_appearance_theme_title": "Tema",
"prefs_appearance_theme_system": "System (basinställning)",
"prefs_appearance_theme_dark": "Mörkt läge",
"prefs_appearance_theme_light": "Ljust läge",
"error_boundary_button_reload_ntfy": "Ladda om ntfy",
"web_push_subscription_expiring_title": "Notifikationer kommer att pausas",
"web_push_subscription_expiring_body": "Öppna ntfy för att fortsätta ta emot notifikationer",
"web_push_unknown_notification_body": "Du kan behöva uppdatera ntfy genom att öppna webbappen",
"prefs_notifications_web_push_disabled_description": "Meddelanden tas emot när webbappen körs (via WebSocket)",
"web_push_unknown_notification_title": "Okänd notifikation mottagen från server"
} }