Compare commits

...

21 Commits

Author SHA1 Message Date
Philipp Heckel
fe96110e6b macOS universal binaries, install instructions for Windows and macOS 2022-05-10 22:10:38 -04:00
Philipp Heckel
5a8818ac92 "make update" target 2022-05-10 11:50:48 -04:00
Philipp Heckel
3baa93a0d4 Merge branch 'main' into windows 2022-05-10 10:16:49 -04:00
Philipp Heckel
72ec2f9988 Additional thanks 2022-05-10 10:16:37 -04:00
Philipp Heckel
ae3d063c2d Typo 2022-05-10 10:13:33 -04:00
Philipp Heckel
d0bb27cf0c Added Portuguese/Brazil to web app 2022-05-10 10:13:04 -04:00
Philipp Heckel
67be8e3ff8 Merge branch 'main' of https://hosted.weblate.org/git/ntfy/web into main 2022-05-10 10:04:59 -04:00
Tiago Esperança Triques
4571ba1c24 Translated using Weblate (Portuguese (Brazil))
Currently translated at 100.0% (154 of 154 strings)

Translation: ntfy/Web app
Translate-URL: https://hosted.weblate.org/projects/ntfy/web/pt_BR/
2022-05-10 16:04:53 +02:00
Philipp Heckel
6d601ad141 macOS 2022-05-09 21:25:00 -04:00
Philipp Heckel
f63b15ba5a Merge branch 'main' into windows 2022-05-09 19:48:11 -04:00
Philipp Heckel
5c01d13fe3 Secrets 2022-05-09 19:48:01 -04:00
Philipp Heckel
19d2a46457 Build for Windows 2022-05-09 19:46:32 -04:00
Philipp Heckel
613348d37e Continued work on Windows CLI 2022-05-09 16:22:52 -04:00
Philipp Heckel
7d473488de Working Windows build 2022-05-09 11:03:40 -04:00
Philipp Heckel
6e4b31b4e9 Changelog 2022-05-09 10:33:17 -04:00
Philipp Heckel
88474957a2 Merge branch 'main' of https://hosted.weblate.org/git/ntfy/web into main 2022-05-09 10:32:54 -04:00
Dániel Agócs
9dc532de30 Translated using Weblate (Hungarian)
Currently translated at 100.0% (154 of 154 strings)

Translation: ntfy/Web app
Translate-URL: https://hosted.weblate.org/projects/ntfy/web/hu/
2022-05-08 16:32:59 +02:00
Shoshin Akamine
fe37258bc2 Translated using Weblate (Japanese)
Currently translated at 100.0% (154 of 154 strings)

Translation: ntfy/Web app
Translate-URL: https://hosted.weblate.org/projects/ntfy/web/ja/
2022-05-08 16:32:59 +02:00
Philipp Heckel
5291e9be7f Merge branch 'main' of github.com:binwiederhier/ntfy into main 2022-05-07 22:39:03 -04:00
Philipp Heckel
6ab02a31a2 npm update 2022-05-07 22:38:51 -04:00
Philipp C. Heckel
14d9d120e6 Create codeql-analysis.yml 2022-05-07 22:36:28 -04:00
30 changed files with 2056 additions and 1105 deletions

72
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,72 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '21 10 * * 5'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'go', 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

1
.gitignore vendored
View File

@@ -5,5 +5,6 @@ server/docs/
server/site/ server/site/
tools/fbsend/fbsend tools/fbsend/fbsend
playground/ playground/
secrets/
*.iml *.iml
node_modules/ node_modules/

View File

@@ -4,7 +4,7 @@ before:
- go mod tidy - go mod tidy
builds: builds:
- -
id: ntfy_amd64 id: ntfy_linux_amd64
binary: ntfy binary: ntfy
env: env:
- CGO_ENABLED=1 # required for go-sqlite3 - CGO_ENABLED=1 # required for go-sqlite3
@@ -17,7 +17,7 @@ builds:
post: post:
- upx "{{ .Path }}" # apt install upx - upx "{{ .Path }}" # apt install upx
- -
id: ntfy_armv6 id: ntfy_linux_armv6
binary: ntfy binary: ntfy
env: env:
- CGO_ENABLED=1 # required for go-sqlite3 - CGO_ENABLED=1 # required for go-sqlite3
@@ -28,10 +28,9 @@ builds:
goos: [linux] goos: [linux]
goarch: [arm] goarch: [arm]
goarm: [6] goarm: [6]
# No "upx", since it causes random core dumps, see # No "upx" for ARM, see https://github.com/binwiederhier/ntfy/issues/191#issuecomment-1083406546
# https://github.com/binwiederhier/ntfy/issues/191#issuecomment-1083406546
- -
id: ntfy_armv7 id: ntfy_linux_armv7
binary: ntfy binary: ntfy
env: env:
- CGO_ENABLED=1 # required for go-sqlite3 - CGO_ENABLED=1 # required for go-sqlite3
@@ -42,10 +41,9 @@ builds:
goos: [linux] goos: [linux]
goarch: [arm] goarch: [arm]
goarm: [7] goarm: [7]
# No "upx", since it causes random core dumps, see # No "upx" for ARM, see https://github.com/binwiederhier/ntfy/issues/191#issuecomment-1083406546
# https://github.com/binwiederhier/ntfy/issues/191#issuecomment-1083406546
- -
id: ntfy_arm64 id: ntfy_linux_arm64
binary: ntfy binary: ntfy
env: env:
- CGO_ENABLED=1 # required for go-sqlite3 - CGO_ENABLED=1 # required for go-sqlite3
@@ -55,8 +53,28 @@ builds:
- "-linkmode=external -extldflags=-static -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}" - "-linkmode=external -extldflags=-static -s -w -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}"
goos: [linux] goos: [linux]
goarch: [arm64] goarch: [arm64]
# No "upx", since it causes random core dumps, see # No "upx" for ARM, see https://github.com/binwiederhier/ntfy/issues/191#issuecomment-1083406546
# https://github.com/binwiederhier/ntfy/issues/191#issuecomment-1083406546 -
id: ntfy_windows_amd64
binary: ntfy
env:
- CGO_ENABLED=0 # explicitly disable, since we don't need go-sqlite3
ldflags:
- "-X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}"
goos: [windows]
goarch: [amd64]
hooks:
post:
- upx "{{ .Path }}" # apt install upx
-
id: ntfy_darwin_all
binary: ntfy
env:
- CGO_ENABLED=0 # explicitly disable, since we don't need go-sqlite3
ldflags:
- "-X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.Date}}"
goos: [darwin]
goarch: [amd64, arm64] # will be combined to "universal binary" (see below)
nfpms: nfpms:
- -
package_name: ntfy package_name: ntfy
@@ -94,6 +112,12 @@ nfpms:
postremove: "scripts/postrm.sh" postremove: "scripts/postrm.sh"
archives: archives:
- -
id: ntfy_linux
builds:
- ntfy_linux_amd64
- ntfy_linux_armv6
- ntfy_linux_armv7
- ntfy_linux_arm64
wrap_in_directory: true wrap_in_directory: true
files: files:
- LICENSE - LICENSE
@@ -103,8 +127,34 @@ archives:
- client/client.yml - client/client.yml
- client/ntfy-client.service - client/ntfy-client.service
replacements: replacements:
386: i386
amd64: x86_64 amd64: x86_64
-
id: ntfy_windows
builds:
- ntfy_windows_amd64
format: zip
wrap_in_directory: true
files:
- LICENSE
- README.md
- client/client.yml
replacements:
amd64: x86_64
-
id: ntfy_darwin
builds:
- ntfy_darwin_all
wrap_in_directory: true
files:
- LICENSE
- README.md
- client/client.yml
replacements:
darwin: macOS
universal_binaries:
-
id: ntfy_darwin_all
replace: true
checksum: checksum:
name_template: 'checksums.txt' name_template: 'checksums.txt'
snapshot: snapshot:

110
Makefile
View File

@@ -5,8 +5,8 @@ VERSION := $(shell git describe --tag)
help: help:
@echo "Typical commands (more see below):" @echo "Typical commands (more see below):"
@echo " make build - Build web app, documentation and server/client (sloowwww)" @echo " make build - Build web app, documentation and server/client (sloowwww)"
@echo " make server-amd64 - Build server/client binary (amd64, no web app or docs)" @echo " make cli-linux-amd64 - Build server/client binary (amd64, no web app or docs)"
@echo " make install-amd64 - Install ntfy binary to /usr/bin/ntfy (amd64)" @echo " make install-linux-amd64 - Install ntfy binary to /usr/bin/ntfy (amd64)"
@echo " make web - Build the web app" @echo " make web - Build the web app"
@echo " make docs - Build the documentation" @echo " make docs - Build the documentation"
@echo " make check - Run all tests, vetting/formatting checks and linters" @echo " make check - Run all tests, vetting/formatting checks and linters"
@@ -16,11 +16,13 @@ help:
@echo " make clean - Clean build/dist folders" @echo " make clean - Clean build/dist folders"
@echo @echo
@echo "Build server & client (not release version):" @echo "Build server & client (not release version):"
@echo " make server - Build server & client (all architectures)" @echo " make cli - Build server & client (all architectures)"
@echo " make server-amd64 - Build server & client (amd64 only)" @echo " make cli-linux-amd64 - Build server & client (Linux, amd64 only)"
@echo " make server-armv6 - Build server & client (armv6 only)" @echo " make cli-linux-armv6 - Build server & client (Linux, armv6 only)"
@echo " make server-armv7 - Build server & client (armv7 only)" @echo " make cli-linux-armv7 - Build server & client (Linux, armv7 only)"
@echo " make server-arm64 - Build server & client (arm64 only)" @echo " make cli-linux-arm64 - Build server & client (Linux, arm64 only)"
@echo " make cli-windows-amd64 - Build client (Windows, amd64 only)"
@echo " make cli-darwin-amd64 - Build client (macOS, amd64 only)"
@echo @echo
@echo "Build web app:" @echo "Build web app:"
@echo " make web - Build the web app" @echo " make web - Build the web app"
@@ -51,14 +53,14 @@ help:
@echo " make release-snapshot - Create a test release" @echo " make release-snapshot - Create a test release"
@echo @echo
@echo "Install locally (requires sudo):" @echo "Install locally (requires sudo):"
@echo " make install-amd64 - Copy amd64 binary from dist/ to /usr/bin/ntfy" @echo " make install-linux-amd64 - Copy amd64 binary from dist/ to /usr/bin/ntfy"
@echo " make install-armv6 - Copy armv6 binary from dist/ to /usr/bin/ntfy" @echo " make install-linux-armv6 - Copy armv6 binary from dist/ to /usr/bin/ntfy"
@echo " make install-armv7 - Copy armv7 binary from dist/ to /usr/bin/ntfy" @echo " make install-linux-armv7 - Copy armv7 binary from dist/ to /usr/bin/ntfy"
@echo " make install-arm64 - Copy arm64 binary from dist/ to /usr/bin/ntfy" @echo " make install-linux-arm64 - Copy arm64 binary from dist/ to /usr/bin/ntfy"
@echo " make install-deb-amd64 - Install .deb from dist/ (amd64 only)" @echo " make install-linux-deb-amd64 - Install .deb from dist/ (amd64 only)"
@echo " make install-deb-armv6 - Install .deb from dist/ (armv6 only)" @echo " make install-linux-deb-armv6 - Install .deb from dist/ (armv6 only)"
@echo " make install-deb-armv7 - Install .deb from dist/ (armv7 only)" @echo " make install-linux-deb-armv7 - Install .deb from dist/ (armv7 only)"
@echo " make install-deb-arm64 - Install .deb from dist/ (arm64 only)" @echo " make install-linux-deb-arm64 - Install .deb from dist/ (arm64 only)"
# Building everything # Building everything
@@ -68,26 +70,27 @@ clean: .PHONY
build: web docs server build: web docs server
update: web-deps-update cli-deps-update docs-deps-update
# Documentation # Documentation
docs: docs-deps docs-build docs: docs-deps docs-build
docs-build: .PHONY
mkdocs build
docs-deps: .PHONY docs-deps: .PHONY
pip3 install -r requirements.txt pip3 install -r requirements.txt
docs-build: .PHONY docs-deps-update: .PHONY
mkdocs build pip3 install -r requirements.txt --upgrade
# Web app # Web app
web: web-deps web-build web: web-deps web-build
web-deps:
cd web && npm install
# If this fails for .svg files, optimizes them with svgo
web-build: web-build:
cd web \ cd web \
&& npm run build \ && npm run build \
@@ -98,41 +101,56 @@ web-build:
../server/site/config.js \ ../server/site/config.js \
../server/site/asset-manifest.json ../server/site/asset-manifest.json
web-deps:
cd web && npm install
# If this fails for .svg files, optimize them with svgo
web-deps-update:
cd web && npm update
# Main server/client build # Main server/client build
server: server-deps cli: cli-deps
goreleaser build --snapshot --rm-dist --debug goreleaser build --snapshot --rm-dist --debug
server-amd64: server-deps-static-sites cli-linux-amd64: cli-deps-static-sites
goreleaser build --snapshot --rm-dist --debug --id ntfy_amd64 goreleaser build --snapshot --rm-dist --debug --id ntfy_linux_amd64
server-armv6: server-deps-static-sites server-deps-gcc-armv6-armv7 cli-linux-armv6: cli-deps-static-sites cli-deps-gcc-armv6-armv7
goreleaser build --snapshot --rm-dist --debug --id ntfy_armv6 goreleaser build --snapshot --rm-dist --debug --id ntfy_linux_armv6
server-armv7: server-deps-static-sites server-deps-gcc-armv6-armv7 cli-linux-armv7: cli-deps-static-sites cli-deps-gcc-armv6-armv7
goreleaser build --snapshot --rm-dist --debug --id ntfy_armv7 goreleaser build --snapshot --rm-dist --debug --id ntfy_linux_armv7
server-arm64: server-deps-static-sites server-deps-gcc-arm64 cli-linux-arm64: cli-deps-static-sites cli-deps-gcc-arm64
goreleaser build --snapshot --rm-dist --debug --id ntfy_arm64 goreleaser build --snapshot --rm-dist --debug --id ntfy_linux_arm64
server-deps: server-deps-static-sites server-deps-all server-deps-gcc cli-windows-amd64: cli-deps-static-sites
goreleaser build --snapshot --rm-dist --debug --id ntfy_windows_amd64
server-deps-gcc: server-deps-gcc-armv6-armv7 server-deps-gcc-arm64 cli-darwin-all: cli-deps-static-sites
goreleaser build --snapshot --rm-dist --debug --id ntfy_darwin_all
server-deps-static-sites: cli-deps: cli-deps-static-sites cli-deps-all cli-deps-gcc
cli-deps-gcc: cli-deps-gcc-armv6-armv7 cli-deps-gcc-arm64
cli-deps-static-sites:
mkdir -p server/docs server/site mkdir -p server/docs server/site
touch server/docs/index.html server/site/app.html touch server/docs/index.html server/site/app.html
server-deps-all: cli-deps-all:
which upx || { echo "ERROR: upx not installed. On Ubuntu, run: apt install upx"; exit 1; } which upx || { echo "ERROR: upx not installed. On Ubuntu, run: apt install upx"; exit 1; }
server-deps-gcc-armv6-armv7: cli-deps-gcc-armv6-armv7:
which arm-linux-gnueabi-gcc || { echo "ERROR: ARMv6/ARMv7 cross compiler not installed. On Ubuntu, run: apt install gcc-arm-linux-gnueabi"; exit 1; } which arm-linux-gnueabi-gcc || { echo "ERROR: ARMv6/ARMv7 cross compiler not installed. On Ubuntu, run: apt install gcc-arm-linux-gnueabi"; exit 1; }
server-deps-gcc-arm64: cli-deps-gcc-arm64:
which aarch64-linux-gnu-gcc || { echo "ERROR: ARM64 cross compiler not installed. On Ubuntu, run: apt install gcc-aarch64-linux-gnu"; exit 1; } which aarch64-linux-gnu-gcc || { echo "ERROR: ARM64 cross compiler not installed. On Ubuntu, run: apt install gcc-aarch64-linux-gnu"; exit 1; }
cli-deps-update:
go get -u
go install honnef.co/go/tools/cmd/staticcheck@latest
# Test/check targets # Test/check targets
@@ -184,10 +202,10 @@ staticcheck: .PHONY
# Releasing targets # Releasing targets
release: clean server-deps release-check-tags docs web check release: clean update cli-deps release-check-tags docs web check
goreleaser release --rm-dist --debug goreleaser release --rm-dist --debug
release-snapshot: clean server-deps docs web check release-snapshot: clean update cli-deps docs web check
goreleaser release --snapshot --skip-publish --rm-dist --debug goreleaser release --snapshot --skip-publish --rm-dist --debug
release-check-tags: release-check-tags:
@@ -204,31 +222,31 @@ release-check-tags:
# Installing targets # Installing targets
install-amd64: remove-binary install-linux-amd64: remove-binary
sudo cp -a dist/ntfy_amd64_linux_amd64_v1/ntfy /usr/bin/ntfy sudo cp -a dist/ntfy_amd64_linux_amd64_v1/ntfy /usr/bin/ntfy
install-armv6: remove-binary install-linux-armv6: remove-binary
sudo cp -a dist/ntfy_armv6_linux_arm_6/ntfy /usr/bin/ntfy sudo cp -a dist/ntfy_armv6_linux_arm_6/ntfy /usr/bin/ntfy
install-armv7: remove-binary install-linux-armv7: remove-binary
sudo cp -a dist/ntfy_armv7_linux_arm_7/ntfy /usr/bin/ntfy sudo cp -a dist/ntfy_armv7_linux_arm_7/ntfy /usr/bin/ntfy
install-arm64: remove-binary install-linux-arm64: remove-binary
sudo cp -a dist/ntfy_arm64_linux_arm64/ntfy /usr/bin/ntfy sudo cp -a dist/ntfy_arm64_linux_arm64/ntfy /usr/bin/ntfy
remove-binary: remove-binary:
sudo rm -f /usr/bin/ntfy sudo rm -f /usr/bin/ntfy
install-amd64-deb: purge-package install-linux-amd64-deb: purge-package
sudo dpkg -i dist/ntfy_*_linux_amd64.deb sudo dpkg -i dist/ntfy_*_linux_amd64.deb
install-armv6-deb: purge-package install-linux-armv6-deb: purge-package
sudo dpkg -i dist/ntfy_*_linux_armv6.deb sudo dpkg -i dist/ntfy_*_linux_armv6.deb
install-armv7-deb: purge-package install-linux-armv7-deb: purge-package
sudo dpkg -i dist/ntfy_*_linux_armv7.deb sudo dpkg -i dist/ntfy_*_linux_armv7.deb
install-arm64-deb: purge-package install-linux-arm64-deb: purge-package
sudo dpkg -i dist/ntfy_*_linux_arm64.deb sudo dpkg -i dist/ntfy_*_linux_arm64.deb
purge-package: purge-package:

View File

@@ -8,6 +8,10 @@ import (
"heckel.io/ntfy/util" "heckel.io/ntfy/util"
) )
func init() {
commands = append(commands, cmdAccess)
}
const ( const (
userEveryone = "everyone" userEveryone = "everyone"
) )

View File

@@ -9,16 +9,13 @@ import (
"os" "os"
) )
var (
defaultClientRootConfigFile = "/etc/ntfy/client.yml"
defaultClientUserConfigFile = "~/.config/ntfy/client.yml"
)
const ( const (
categoryClient = "Client commands" categoryClient = "Client commands"
categoryServer = "Server commands" categoryServer = "Server commands"
) )
var commands = make([]*cli.Command, 0)
// New creates a new CLI application // New creates a new CLI application
func New() *cli.App { func New() *cli.App {
return &cli.App{ return &cli.App{
@@ -30,16 +27,7 @@ func New() *cli.App {
Reader: os.Stdin, Reader: os.Stdin,
Writer: os.Stdout, Writer: os.Stdout,
ErrWriter: os.Stderr, ErrWriter: os.Stderr,
Commands: []*cli.Command{ Commands: commands,
// Server commands
cmdServe,
cmdUser,
cmdAccess,
// Client commands
cmdPublish,
cmdSubscribe,
},
} }
} }

View File

@@ -12,6 +12,10 @@ import (
"strings" "strings"
) )
func init() {
commands = append(commands, cmdPublish)
}
var cmdPublish = &cli.Command{ var cmdPublish = &cli.Command{
Name: "publish", Name: "publish",
Aliases: []string{"pub", "send", "trigger"}, Aliases: []string{"pub", "send", "trigger"},
@@ -59,8 +63,7 @@ Examples:
Please also check out the docs on publishing messages. Especially for the --tags and --delay options, Please also check out the docs on publishing messages. Especially for the --tags and --delay options,
it has incredibly useful information: https://ntfy.sh/docs/publish/. it has incredibly useful information: https://ntfy.sh/docs/publish/.
The default config file for all client commands is /etc/ntfy/client.yml (if root user), ` + clientCommandDescriptionSuffix,
or ~/.config/ntfy/client.yml for all other users.`,
} }
func execPublish(c *cli.Context) error { func execPublish(c *cli.Context) error {

View File

@@ -14,6 +14,10 @@ import (
"time" "time"
) )
func init() {
commands = append(commands, cmdServe)
}
var flagsServe = []cli.Flag{ var flagsServe = []cli.Flag{
&cli.StringFlag{Name: "config", Aliases: []string{"c"}, EnvVars: []string{"NTFY_CONFIG_FILE"}, Value: "/etc/ntfy/server.yml", DefaultText: "/etc/ntfy/server.yml", Usage: "config file"}, &cli.StringFlag{Name: "config", Aliases: []string{"c"}, EnvVars: []string{"NTFY_CONFIG_FILE"}, Value: "/etc/ntfy/server.yml", DefaultText: "/etc/ntfy/server.yml", Usage: "config file"},
altsrc.NewStringFlag(&cli.StringFlag{Name: "base-url", Aliases: []string{"B"}, EnvVars: []string{"NTFY_BASE_URL"}, Usage: "externally visible base URL for this host (e.g. https://ntfy.sh)"}), altsrc.NewStringFlag(&cli.StringFlag{Name: "base-url", Aliases: []string{"B"}, EnvVars: []string{"NTFY_BASE_URL"}, Usage: "externally visible base URL for this host (e.g. https://ntfy.sh)"}),

View File

@@ -10,9 +10,20 @@ import (
"os" "os"
"os/exec" "os/exec"
"os/user" "os/user"
"path/filepath"
"strings" "strings"
) )
func init() {
commands = append(commands, cmdSubscribe)
}
const (
clientRootConfigFileUnixAbsolute = "/etc/ntfy/client.yml"
clientUserConfigFileUnixRelative = "ntfy/client.yml"
clientUserConfigFileWindowsRelative = "ntfy\\client.yml"
)
var cmdSubscribe = &cli.Command{ var cmdSubscribe = &cli.Command{
Name: "subscribe", Name: "subscribe",
Aliases: []string{"sub"}, Aliases: []string{"sub"},
@@ -60,19 +71,17 @@ ntfy subscribe TOPIC COMMAND
Examples: Examples:
ntfy sub mytopic 'notify-send "$m"' # Execute command for incoming messages ntfy sub mytopic 'notify-send "$m"' # Execute command for incoming messages
ntfy sub topic1 /my/script.sh # Execute script for incoming messages ntfy sub topic1 myscript.sh # Execute script for incoming messages
ntfy subscribe --from-config ntfy subscribe --from-config
Service mode (used in ntfy-client.service). This reads the config file (/etc/ntfy/client.yml Service mode (used in ntfy-client.service). This reads the config file and sets up
or ~/.config/ntfy/client.yml) and sets up subscriptions for every topic in the "subscribe:" subscriptions for every topic in the "subscribe:" block (see config file).
block (see config file).
Examples: Examples:
ntfy sub --from-config # Read topics from config file ntfy sub --from-config # Read topics from config file
ntfy sub --config=/my/client.yml --from-config # Read topics from alternate config file ntfy sub --config=myclient.yml --from-config # Read topics from alternate config file
The default config file for all client commands is /etc/ntfy/client.yml (if root user), ` + clientCommandDescriptionSuffix,
or ~/.config/ntfy/client.yml for all other users.`,
} }
func execSubscribe(c *cli.Context) error { func execSubscribe(c *cli.Context) error {
@@ -156,8 +165,8 @@ func doPollSingle(c *cli.Context, cl *client.Client, topic, command string, opti
} }
func doSubscribe(c *cli.Context, cl *client.Client, conf *client.Config, topic, command string, options ...client.SubscribeOption) error { func doSubscribe(c *cli.Context, cl *client.Client, conf *client.Config, topic, command string, options ...client.SubscribeOption) error {
commands := make(map[string]string) // Subscription ID -> command cmds := make(map[string]string) // Subscription ID -> command
for _, s := range conf.Subscribe { // May be nil for _, s := range conf.Subscribe { // May be nil
topicOptions := append(make([]client.SubscribeOption, 0), options...) topicOptions := append(make([]client.SubscribeOption, 0), options...)
for filter, value := range s.If { for filter, value := range s.If {
topicOptions = append(topicOptions, client.WithFilter(filter, value)) topicOptions = append(topicOptions, client.WithFilter(filter, value))
@@ -166,18 +175,18 @@ func doSubscribe(c *cli.Context, cl *client.Client, conf *client.Config, topic,
topicOptions = append(topicOptions, client.WithBasicAuth(s.User, s.Password)) topicOptions = append(topicOptions, client.WithBasicAuth(s.User, s.Password))
} }
subscriptionID := cl.Subscribe(s.Topic, topicOptions...) subscriptionID := cl.Subscribe(s.Topic, topicOptions...)
commands[subscriptionID] = s.Command cmds[subscriptionID] = s.Command
} }
if topic != "" { if topic != "" {
subscriptionID := cl.Subscribe(topic, options...) subscriptionID := cl.Subscribe(topic, options...)
commands[subscriptionID] = command cmds[subscriptionID] = command
} }
for m := range cl.Messages { for m := range cl.Messages {
command, ok := commands[m.SubscriptionID] cmd, ok := cmds[m.SubscriptionID]
if !ok { if !ok {
continue continue
} }
printMessageOrRunCommand(c, m, command) printMessageOrRunCommand(c, m, cmd)
} }
return nil return nil
} }
@@ -196,17 +205,17 @@ func runCommand(c *cli.Context, command string, m *client.Message) {
} }
} }
func runCommandInternal(c *cli.Context, command string, m *client.Message) error { func runCommandInternal(c *cli.Context, script string, m *client.Message) error {
scriptFile, err := createTmpScript(command) scriptFile := fmt.Sprintf("%s/ntfy-subscribe-%s.%s", os.TempDir(), util.RandomString(10), scriptExt)
if err != nil { if err := os.WriteFile(scriptFile, []byte(scriptHeader+script), 0700); err != nil {
return err return err
} }
defer os.Remove(scriptFile) defer os.Remove(scriptFile)
verbose := c.Bool("verbose") verbose := c.Bool("verbose")
if verbose { if verbose {
log.Printf("[%s] Executing: %s (for message: %s)", util.ShortTopicURL(m.TopicURL), command, m.Raw) log.Printf("[%s] Executing: %s (for message: %s)", util.ShortTopicURL(m.TopicURL), script, m.Raw)
} }
cmd := exec.Command("sh", "-c", scriptFile) cmd := exec.Command(scriptLauncher[0], append(scriptLauncher[1:], scriptFile)...)
cmd.Stdin = c.App.Reader cmd.Stdin = c.App.Reader
cmd.Stdout = c.App.Writer cmd.Stdout = c.App.Writer
cmd.Stderr = c.App.ErrWriter cmd.Stderr = c.App.ErrWriter
@@ -214,15 +223,6 @@ func runCommandInternal(c *cli.Context, command string, m *client.Message) error
return cmd.Run() return cmd.Run()
} }
func createTmpScript(command string) (string, error) {
scriptFile := fmt.Sprintf("%s/ntfy-subscribe-%s.sh.tmp", os.TempDir(), util.RandomString(10))
script := fmt.Sprintf("#!/bin/sh\n%s", command)
if err := os.WriteFile(scriptFile, []byte(script), 0700); err != nil {
return "", err
}
return scriptFile, nil
}
func envVars(m *client.Message) []string { func envVars(m *client.Message) []string {
env := os.Environ() env := os.Environ()
env = append(env, envVar(m.ID, "NTFY_ID", "id")...) env = append(env, envVar(m.ID, "NTFY_ID", "id")...)
@@ -249,13 +249,26 @@ func loadConfig(c *cli.Context) (*client.Config, error) {
if filename != "" { if filename != "" {
return client.LoadConfig(filename) return client.LoadConfig(filename)
} }
u, _ := user.Current() configFile := defaultConfigFile()
configFile := defaultClientRootConfigFile
if u.Uid != "0" {
configFile = util.ExpandHome(defaultClientUserConfigFile)
}
if s, _ := os.Stat(configFile); s != nil { if s, _ := os.Stat(configFile); s != nil {
return client.LoadConfig(configFile) return client.LoadConfig(configFile)
} }
return client.NewConfig(), nil return client.NewConfig(), nil
} }
//lint:ignore U1000 Conditionally used in different builds
func defaultConfigFileUnix() string {
u, _ := user.Current()
configFile := clientRootConfigFileUnixAbsolute
if u.Uid != "0" {
homeDir, _ := os.UserConfigDir()
return filepath.Join(homeDir, clientUserConfigFileUnixRelative)
}
return configFile
}
//lint:ignore U1000 Conditionally used in different builds
func defaultConfigFileWindows() string {
homeDir, _ := os.UserConfigDir()
return filepath.Join(homeDir, clientUserConfigFileWindowsRelative)
}

16
cmd/subscribe_darwin.go Normal file
View File

@@ -0,0 +1,16 @@
package cmd
const (
scriptExt = "sh"
scriptHeader = "#!/bin/sh\n"
clientCommandDescriptionSuffix = `The default config file for all client commands is /etc/ntfy/client.yml (if root user),
or "~/Library/Application Support/ntfy/client.yml" for all other users.`
)
var (
scriptLauncher = []string{"sh", "-c"}
)
func defaultConfigFile() string {
return defaultConfigFileUnix()
}

16
cmd/subscribe_linux.go Normal file
View File

@@ -0,0 +1,16 @@
package cmd
const (
scriptExt = "sh"
scriptHeader = "#!/bin/sh\n"
clientCommandDescriptionSuffix = `The default config file for all client commands is /etc/ntfy/client.yml (if root user),
or ~/.config/ntfy/client.yml for all other users.`
)
var (
scriptLauncher = []string{"sh", "-c"}
)
func defaultConfigFile() string {
return defaultConfigFileUnix()
}

15
cmd/subscribe_windows.go Normal file
View File

@@ -0,0 +1,15 @@
package cmd
const (
scriptExt = "bat"
scriptHeader = ""
clientCommandDescriptionSuffix = `The default config file for all client commands is %AppData%\ntfy\client.yml.`
)
var (
scriptLauncher = []string{"cmd.exe", "/Q", "/C"}
)
func defaultConfigFile() string {
return defaultConfigFileWindows()
}

View File

@@ -11,7 +11,12 @@ import (
"strings" "strings"
) )
func init() {
commands = append(commands, cmdUser)
}
var flagsUser = userCommandFlags() var flagsUser = userCommandFlags()
var cmdUser = &cli.Command{ var cmdUser = &cli.Command{
Name: "user", Name: "user",
Usage: "Manage/show users", Usage: "Manage/show users",

View File

@@ -112,8 +112,8 @@ by typing `make`:
$ make $ make
Typical commands (more see below): Typical commands (more see below):
make build - Build web app, documentation and server/client (sloowwww) make build - Build web app, documentation and server/client (sloowwww)
make server-amd64 - Build server/client binary (amd64, no web app or docs) make cli-linux-amd64 - Build server/client binary (amd64, no web app or docs)
make install-amd64 - Install ntfy binary to /usr/bin/ntfy (amd64) make install-linux-amd64 - Install ntfy binary to /usr/bin/ntfy (amd64)
make web - Build the web app make web - Build the web app
make docs - Build the documentation make docs - Build the documentation
make check - Run all tests, vetting/formatting checks and linters make check - Run all tests, vetting/formatting checks and linters
@@ -158,45 +158,47 @@ $ make release-snapshot
During development, you may want to be more picky and build only certain things. Here are a few examples. During development, you may want to be more picky and build only certain things. Here are a few examples.
### Build the ntfy binary ### Build the ntfy binary
To build only the `ntfy` binary **without the web app or documentation**, use the `make server-...` targets: To build only the `ntfy` binary **without the web app or documentation**, use the `make cli-...` targets:
``` shell ``` shell
$ make $ make
Build server & client (not release version): Build server & client (not release version):
make server - Build server & client (all architectures) make cli - Build server & client (all architectures)
make server-amd64 - Build server & client (amd64 only) make cli-linux-amd64 - Build server & client (Linux, amd64 only)
make server-armv7 - Build server & client (armv7 only) make cli-linux-armv6 - Build server & client (Linux, armv6 only)
make server-arm64 - Build server & client (arm64 only) make cli-linux-armv7 - Build server & client (Linux, armv7 only)
make cli-linux-arm64 - Build server & client (Linux, arm64 only)
make cli-windows-amd64 - Build client (Windows, amd64 only)
``` ```
So if you're on an amd64/x86_64-based machine, you may just want to run `make server-amd64` during testing. On a modern So if you're on an amd64/x86_64-based machine, you may just want to run `make cli-linux-amd64` during testing. On a modern
system, this shouldn't take longer than 5-10 seconds. I often combine it with `install-amd64` so I can run the binary system, this shouldn't take longer than 5-10 seconds. I often combine it with `install-linux-amd64` so I can run the binary
right away: right away:
``` shell ``` shell
$ make server-amd64 install-amd64 $ make cli-linux-amd64 install-linux-amd64
$ ntfy serve $ ntfy serve
``` ```
**During development of the main app, you can also just use `go run main.go`**, as long as you run **During development of the main app, you can also just use `go run main.go`**, as long as you run
`make server-deps-static-sites`at least once and `CGO_ENABLED=1`: `make cli-deps-static-sites`at least once and `CGO_ENABLED=1`:
``` shell ``` shell
$ export CGO_ENABLED=1 $ export CGO_ENABLED=1
$ make server-deps-static-sites $ make cli-deps-static-sites
$ go run main.go serve $ go run main.go serve
2022/03/18 08:43:55 Listening on :2586[http] 2022/03/18 08:43:55 Listening on :2586[http]
... ...
``` ```
If you don't run `server-deps-static-sites`, you may see an error *`pattern ...: no matching files found`*: If you don't run `cli-deps-static-sites`, you may see an error *`pattern ...: no matching files found`*:
``` ```
$ go run main.go serve $ go run main.go serve
server/server.go:85:13: pattern docs: no matching files found server/server.go:85:13: pattern docs: no matching files found
``` ```
This is because we use `go:embed` to embed the documentation and web app, so the Go code expects files to be This is because we use `go:embed` to embed the documentation and web app, so the Go code expects files to be
present at `server/docs` and `server/site`. If they are not, you'll see the above error. The `server-deps-static-sites` present at `server/docs` and `server/site`. If they are not, you'll see the above error. The `cli-deps-static-sites`
target creates dummy files that ensures that you'll be able to build. target creates dummy files that ensures that you'll be able to build.
@@ -210,7 +212,7 @@ $ make web
``` ```
This will build the web app using Create React App and then **copy the production build to the `server/site` folder**, so This will build the web app using Create React App and then **copy the production build to the `server/site` folder**, so
that when you `make server` (or `make server-amd64`, ...), you will have the web app included in the `ntfy` binary. that when you `make cli` (or `make cli-linux-amd64`, ...), you will have the web app included in the `ntfy` binary.
If you're developing on the web app, it's best to just `cd web` and run `npm start` manually. This will open your browser If you're developing on the web app, it's best to just `cd web` and run `npm start` manually. This will open your browser
at `http://127.0.0.1:3000` with the web app, and as you edit the source files, they will be recompiled and the browser at `http://127.0.0.1:3000` with the web app, and as you edit the source files, they will be recompiled and the browser

View File

@@ -13,14 +13,14 @@ The ntfy server comes as a statically linked binary and is shipped as tarball, d
We support amd64, armv7 and arm64. We support amd64, armv7 and arm64.
1. Install ntfy using one of the methods described below 1. Install ntfy using one of the methods described below
2. Then (optionally) edit `/etc/ntfy/server.yml` for the server (see [configuration](config.md) or [sample server.yml](https://github.com/binwiederhier/ntfy/blob/main/server/server.yml)) 2. Then (optionally) edit `/etc/ntfy/server.yml` for the server (Linux only, see [configuration](config.md) or [sample server.yml](https://github.com/binwiederhier/ntfy/blob/main/server/server.yml))
3. Or (optionally) create/edit `~/.config/ntfy/client.yml` (or `/etc/ntfy/client.yml`, see [sample client.yml](https://github.com/binwiederhier/ntfy/blob/main/client/client.yml)) 3. Or (optionally) create/edit `~/.config/ntfy/client.yml` (or `/etc/ntfy/client.yml`, see [sample client.yml](https://github.com/binwiederhier/ntfy/blob/main/client/client.yml))
To run the ntfy server, then just run `ntfy serve` (or `systemctl start ntfy` when using the deb/rpm). To run the ntfy server, then just run `ntfy serve` (or `systemctl start ntfy` when using the deb/rpm).
To send messages, use `ntfy publish`. To subscribe to topics, use `ntfy subscribe` (see [subscribing via CLI][subscribe/cli.md] To send messages, use `ntfy publish`. To subscribe to topics, use `ntfy subscribe` (see [subscribing via CLI][subscribe/cli.md]
for details). for details).
## Binaries and packages ## Linux binaries
Please check out the [releases page](https://github.com/binwiederhier/ntfy/releases) for binaries and Please check out the [releases page](https://github.com/binwiederhier/ntfy/releases) for binaries and
deb/rpm packages. deb/rpm packages.
@@ -176,6 +176,37 @@ cd ntfysh-bin
makepkg -si makepkg -si
``` ```
## macOS
The [ntfy CLI](subscribe/cli.md) (`ntfy publish` and `ntfy subscribe` only) is supported on macOS as well.
To install, please download the tarball, extract it and place it somewhere in your `PATH` (e.g. `/usr/local/bin/ntfy`).
If run as `root`, ntfy will look for its config at `/etc/ntfy/client.yml`. For all other users, it'll look for it at
`~/Library/Application Support/ntfy/client.yml` (sample included in the tarball).
```bash
curl https://github.com/binwiederhier/ntfy/releases/download/v1.22.0/ntfy_v1.22.0_macOS_all.tar.gz > ntfy_v1.22.0_macOS_all.tar.gz
tar zxvf ntfy_v1.22.0_macOS_all.tar.gz
sudo cp -a ntfy_v1.22.0_macOS_all/ntfy /usr/local/bin/ntfy
mkdir ~/Library/Application\ Support/ntfy
cp ntfy_v1.22.0_macOS_all/client/client.yml ~/Library/Application\ Support/ntfy/client.yml
ntfy --help
```
!!! info
If there is a desire to install ntfy via [Homebrew](https://brew.sh/), please create a
[GitHub issue](https://github.com/binwiederhier/ntfy/issues) to let me know.
## Windows
The [ntfy CLI](subscribe/cli.md) (`ntfy publish` and `ntfy subscribe` only) is supported on Windows as well.
To install, please [download the latest ZIP](https://github.com/binwiederhier/ntfy/releases/download/v1.22.0/ntfy_v1.22.0-next_windows_x86_64.zip),
extract it and place the `ntfy.exe` binary somewhere in your `%Path%`.
The default path for the client config file is at `%AppData%\ntfy\client.yml` (not created automatically, sample in the ZIP file).
!!! info
There is currently no installer for Windows, and the binary is not signed. If this is desired, please create a
[GitHub issue](https://github.com/binwiederhier/ntfy/issues) to let me know.
## Docker ## Docker
The [ntfy image](https://hub.docker.com/r/binwiederhier/ntfy) is available for amd64, armv6, armv7 and arm64. It should The [ntfy image](https://hub.docker.com/r/binwiederhier/ntfy) is available for amd64, armv6, armv7 and arm64. It should
be pretty straight forward to use. be pretty straight forward to use.

View File

@@ -38,7 +38,7 @@ Here's an example showing how to publish a simple message using a POST request:
=== "PowerShell" === "PowerShell"
``` powershell ``` powershell
Invoke-RestMethod -Method 'Post' -Uri https://ntfy.sh/topic -Body "Backup successful 😀" -UseBasicParsing Invoke-RestMethod -Method 'Post' -Uri https://ntfy.sh/mytopic -Body "Backup successful" -UseBasicParsing
``` ```
=== "Python" === "Python"

View File

@@ -4,11 +4,22 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
<!-- <!--
## ntfy server v1.23.0 (UNRELEASED)
**Features:**
* [Windows](https://ntfy.sh/docs/install/#windows) and [macOS](https://ntfy.sh/docs/install/#macos) builds for the [ntfy CLI](https://ntfy.sh/docs/subscribe/cli/) ([#112](https://github.com/binwiederhier/ntfy/issues/112))
**Additional translations:**
* Portuguese/Brazil (thanks to [@tiagotriques](https://hosted.weblate.org/user/tiagotriques/))
## ntfy Android app v1.13.0 (UNRELEASED) ## ntfy Android app v1.13.0 (UNRELEASED)
**Features:** **Features:**
* Cards in notification detail view ([#175](https://github.com/binwiederhier/ntfy/issues/224), thanks to [@cmeis](https://github.com/cmeis) for reporting) * Per-subscription settings, custom subscription icons ([#155](https://github.com/binwiederhier/ntfy/issues/155), thanks to [@mztiq](https://github.com/mztiq) for reporting)
* Cards in notification detail view ([#175](https://github.com/binwiederhier/ntfy/issues/175), thanks to [@cmeis](https://github.com/cmeis) for reporting)
**Bugs:** **Bugs:**
@@ -18,16 +29,16 @@ and the [ntfy Android app](https://github.com/binwiederhier/ntfy-android/release
* Fix app icon on old Android versions ([#128](https://github.com/binwiederhier/ntfy/issues/128), thanks to [@shadow00](https://github.com/shadow00) for reporting) * Fix app icon on old Android versions ([#128](https://github.com/binwiederhier/ntfy/issues/128), thanks to [@shadow00](https://github.com/shadow00) for reporting)
* Fix races in UnifiedPush registration ([#230](https://github.com/binwiederhier/ntfy/issues/230), thanks to @Jakob for reporting) * Fix races in UnifiedPush registration ([#230](https://github.com/binwiederhier/ntfy/issues/230), thanks to @Jakob for reporting)
* Prevent view action from crashing the app ([#233](https://github.com/binwiederhier/ntfy/issues/233)) * Prevent view action from crashing the app ([#233](https://github.com/binwiederhier/ntfy/issues/233))
* Prevent long topic names and icons from overlappng ([#240](https://github.com/binwiederhier/ntfy/issues/240), thanks to [@cmeis](https://github.com/cmeis) for reporting) * Prevent long topic names and icons from overlapping ([#240](https://github.com/binwiederhier/ntfy/issues/240), thanks to [@cmeis](https://github.com/cmeis) for reporting)
**Additional translations:** **Additional translations:**
* Dutch (*incomplete*, thanks to [@diony](https://hosted.weblate.org/user/diony/)) * Dutch (*incomplete*, thanks to [@diony](https://hosted.weblate.org/user/diony/))
**Thanks for testing:** **Thank you:**
Thanks to [@cmeis](https://github.com/cmeis), [@StoyanDimitrov](https://github.com/StoyanDimitrov), [@Fallenbagel](https://github.com/Fallenbagel) for testing, and Thanks to [@cmeis](https://github.com/cmeis), [@StoyanDimitrov](https://github.com/StoyanDimitrov), [@Fallenbagel](https://github.com/Fallenbagel) for testing, and
to [@Joeharrison94](https://github.com/Joeharrison94) for the input. to [@Joeharrison94](https://github.com/Joeharrison94) for the input. And thank you very much to all the translators for catching up so quickly.
--> -->

View File

@@ -123,7 +123,7 @@ which will read the `subscribe` config from the config file. Please also check o
Here's an example config file that subscribes to three different topics, executing a different command for each of them: Here's an example config file that subscribes to three different topics, executing a different command for each of them:
=== "~/.config/ntfy/client.yml" === "~/.config/ntfy/client.yml (Linux)"
```yaml ```yaml
subscribe: subscribe:
- topic: echo-this - topic: echo-this
@@ -145,12 +145,42 @@ Here's an example config file that subscribes to three different topics, executi
fi fi
``` ```
=== "~/Library/Application Support/ntfy/client.yml (macOS)"
```yaml
subscribe:
- topic: echo-this
command: 'echo "Message received: $message"'
- topic: alerts
command: osascript -e "display notification \"$message\""
if:
priority: high,urgent
- topic: calc
command: open -a Calculator
```
=== "%AppData%\ntfy\client.yml (Windows)"
```yaml
subscribe:
- topic: echo-this
command: 'echo Message received: %message%'
- topic: alerts
command: |
notifu /m "%NTFY_MESSAGE%"
exit 0
if:
priority: high,urgent
- topic: calc
command: calc
```
In this example, when `ntfy subscribe --from-config` is executed: In this example, when `ntfy subscribe --from-config` is executed:
* Messages to `echo-this` simply echos to standard out * Messages to `echo-this` simply echos to standard out
* Messages to `alerts` display as desktop notification for high priority messages using [notify-send](https://manpages.ubuntu.com/manpages/focal/man1/notify-send.1.html) * Messages to `alerts` display as desktop notification for high priority messages using [notify-send](https://manpages.ubuntu.com/manpages/focal/man1/notify-send.1.html) (Linux),
* Messages to `calc` open the gnome calculator 😀 (*because, why not*) [notifu](https://www.paralint.com/projects/notifu/) (Windows) or `osascript` (macOS)
* Messages to `print-temp` execute an inline script and print the CPU temperature * Messages to `calc` open the calculator 😀 (*because, why not*)
* Messages to `print-temp` execute an inline script and print the CPU temperature (Linux version only)
I hope this shows how powerful this command is. Here's a short video that demonstrates the above example: I hope this shows how powerful this command is. Here's a short video that demonstrates the above example:

18
go.mod
View File

@@ -7,27 +7,27 @@ require (
cloud.google.com/go/storage v1.22.0 // indirect cloud.google.com/go/storage v1.22.0 // indirect
firebase.google.com/go v3.13.0+incompatible firebase.google.com/go v3.13.0+incompatible
github.com/BurntSushi/toml v1.1.0 // indirect github.com/BurntSushi/toml v1.1.0 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.1 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/emersion/go-smtp v0.15.0 github.com/emersion/go-smtp v0.15.0
github.com/gabriel-vasile/mimetype v1.4.0 github.com/gabriel-vasile/mimetype v1.4.0
github.com/gorilla/websocket v1.5.0 github.com/gorilla/websocket v1.5.0
github.com/mattn/go-sqlite3 v1.14.12 github.com/mattn/go-sqlite3 v1.14.12
github.com/olebedev/when v0.0.0-20211212231525-59bd4edcf9d6 github.com/olebedev/when v0.0.0-20211212231525-59bd4edcf9d6
github.com/stretchr/testify v1.7.0 github.com/stretchr/testify v1.7.0
github.com/urfave/cli/v2 v2.4.7 github.com/urfave/cli/v2 v2.6.0
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5 // indirect
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 golang.org/x/term v0.0.0-20220411215600-e5f449aeb171
golang.org/x/time v0.0.0-20220411224347-583f2d630306 golang.org/x/time v0.0.0-20220411224347-583f2d630306
google.golang.org/api v0.75.0 google.golang.org/api v0.79.0
gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v2 v2.4.0
) )
require github.com/pkg/errors v0.9.1 // indirect require github.com/pkg/errors v0.9.1 // indirect
require ( require (
cloud.google.com/go v0.101.0 // indirect cloud.google.com/go v0.101.1 // indirect
cloud.google.com/go/compute v1.6.1 // indirect cloud.google.com/go/compute v1.6.1 // indirect
cloud.google.com/go/iam v0.3.0 // indirect cloud.google.com/go/iam v0.3.0 // indirect
github.com/AlekSi/pointer v1.2.0 // indirect github.com/AlekSi/pointer v1.2.0 // indirect
@@ -35,18 +35,18 @@ require (
github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac // indirect github.com/emersion/go-sasl v0.0.0-20211008083017-0b9dcfb154ac // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.7 // indirect github.com/google/go-cmp v0.5.8 // indirect
github.com/googleapis/gax-go/v2 v2.3.0 // indirect github.com/googleapis/gax-go/v2 v2.3.0 // indirect
github.com/googleapis/go-type-adapters v1.0.0 // indirect github.com/googleapis/go-type-adapters v1.0.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect
go.opencensus.io v0.23.0 // indirect go.opencensus.io v0.23.0 // indirect
golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 // indirect golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.7 // indirect
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220422154200-b37d22cd5731 // indirect google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3 // indirect
google.golang.org/grpc v1.46.0 // indirect google.golang.org/grpc v1.46.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c // indirect

35
go.sum
View File

@@ -27,8 +27,8 @@ cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc= cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA= cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A= cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
cloud.google.com/go v0.101.0 h1:g+LL+JvpvdyGtcaD2xw2mSByE/6F9s471eJSoaysM84= cloud.google.com/go v0.101.1 h1:3+/0TAm9JD/PyhkrDWQWi2L197h3euCsM+H+J4iYTR8=
cloud.google.com/go v0.101.0/go.mod h1:hEiddgDb77jDQ+I80tURYNJEnuwPzFU8awCFFRLKjW0= cloud.google.com/go v0.101.1/go.mod h1:55HwjsGW4CHD3JrNuMdZtSDsgTs0CuCB/bBTugD+7AA=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@@ -86,8 +86,9 @@ github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cpuguy83/go-md2man/v2 v2.0.1 h1:r/myEWzV9lfsM1tFLgDyu0atFtJ1fXn261LKYj/3DxU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
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=
@@ -160,8 +161,9 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/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.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no= github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
@@ -231,8 +233,8 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
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/urfave/cli/v2 v2.4.7 h1:nUgKLTC/InVYwUx26HZUBGIBZaptiW97W8vVlhuYawo= github.com/urfave/cli/v2 v2.6.0 h1:yj2Drkflh8X/zUrkWlWlUjZYHyWN7WMmpVxyxXIUyv8=
github.com/urfave/cli/v2 v2.4.7/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs= github.com/urfave/cli/v2 v2.6.0/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -252,8 +254,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 h1:kUhD7nTDoI3fVd9G4ORWrbV5NY0liEs/Jg2pv5f+bBA= golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122 h1:NvGWuYG8dkDHFSKksI1P9faiVJ9rayE6l0+ouWVIDs8=
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -330,8 +332,8 @@ golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220421235706-1d1ef9303861 h1:yssD99+7tqHWO5Gwh81phT+67hg+KttniBr6UnEXOY8= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA=
golang.org/x/net v0.0.0-20220421235706-1d1ef9303861/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -420,8 +422,8 @@ golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6 h1:nonptSpoQ4vQjyraW20DXPAglgQfVnM9ZC6MmNLMR60=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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.0.0-20220411215600-e5f449aeb171 h1:EH1Deb8WZJ0xc0WK//leUHXcX9aLE5SymusoTmMZye8= golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 h1:EH1Deb8WZJ0xc0WK//leUHXcX9aLE5SymusoTmMZye8=
@@ -534,8 +536,10 @@ google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQ
google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA= google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8= google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs= google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
google.golang.org/api v0.75.0 h1:0AYh/ae6l9TDUvIQrDw5QRpM100P6oHgD+o3dYHMzJg=
google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA= google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
google.golang.org/api v0.77.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
google.golang.org/api v0.79.0 h1:vaOcm0WdXvhGkci9a0+CcQVZqSRjN8ksSBlWv99f8Pg=
google.golang.org/api v0.79.0/go.mod h1:xY3nI94gbvBrE0J6NHXhxOmW97HG7Khjkku6AFB3Hyg=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 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 v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -619,8 +623,9 @@ google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX
google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220422154200-b37d22cd5731 h1:nquqdM9+ps0JZcIiI70+tqoaIFS5Ql4ZuK8UXnz3HfE= google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/genproto v0.0.0-20220422154200-b37d22cd5731/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo= google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3 h1:q1kiSVscqoDeqTF27eQ2NnLLDmqF0I373qQNXYMy0fo=
google.golang.org/genproto v0.0.0-20220505152158-f39f71e6c8f3/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=

View File

@@ -183,11 +183,6 @@ func PriorityString(priority int) (string, error) {
} }
} }
// ExpandHome replaces "~" with the user's home directory
func ExpandHome(path string) string {
return os.ExpandEnv(strings.ReplaceAll(path, "~", "$HOME"))
}
// ShortTopicURL shortens the topic URL to be human-friendly, removing the http:// or https:// // ShortTopicURL shortens the topic URL to be human-friendly, removing the http:// or https://
func ShortTopicURL(s string) string { func ShortTopicURL(s string) string {
return strings.TrimPrefix(strings.TrimPrefix(s, "https://"), "http://") return strings.TrimPrefix(strings.TrimPrefix(s, "https://"), "http://")

View File

@@ -3,7 +3,6 @@ package util
import ( import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"io/ioutil" "io/ioutil"
"os"
"path/filepath" "path/filepath"
"testing" "testing"
"time" "time"
@@ -75,14 +74,6 @@ func TestSplitNoEmpty(t *testing.T) {
require.Equal(t, []string{"tag1", "tag2"}, SplitNoEmpty("tag1,tag2,", ",")) require.Equal(t, []string{"tag1", "tag2"}, SplitNoEmpty("tag1,tag2,", ","))
} }
func TestExpandHome_WithTilde(t *testing.T) {
require.Equal(t, os.Getenv("HOME")+"/this/is/a/path", ExpandHome("~/this/is/a/path"))
}
func TestExpandHome_NoTilde(t *testing.T) {
require.Equal(t, "/this/is/an/absolute/path", ExpandHome("/this/is/an/absolute/path"))
}
func TestParsePriority(t *testing.T) { func TestParsePriority(t *testing.T) {
priorities := []string{"", "1", "2", "3", "4", "5", "min", "LOW", " default ", "HIgh", "max", "urgent"} priorities := []string{"", "1", "2", "3", "4", "5", "min", "LOW", " default ", "HIgh", "max", "urgent"}
expected := []int{0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 5} expected := []int{0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 5}

2405
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -23,7 +23,7 @@
"notifications_attachment_open_button": "Csatolmány megnyitása", "notifications_attachment_open_button": "Csatolmány megnyitása",
"notifications_attachment_link_expired": "A letöltési hivatkozás lejárt", "notifications_attachment_link_expired": "A letöltési hivatkozás lejárt",
"notifications_attachment_link_expires": "A hivatkozás {{date}}-kor jár le", "notifications_attachment_link_expires": "A hivatkozás {{date}}-kor jár le",
"nav_button_subscribe": "Feliratkozás a témára", "nav_button_subscribe": "Feliratkozás témára",
"notifications_click_copy_url_title": "Másolja vágólapra a hivatkozás URL-ét", "notifications_click_copy_url_title": "Másolja vágólapra a hivatkozás URL-ét",
"notifications_actions_open_url_title": "Menjen a(z) {{url}} címre", "notifications_actions_open_url_title": "Menjen a(z) {{url}} címre",
"notifications_actions_not_supported": "A művelet nem támogatott a webes alkalmazásban", "notifications_actions_not_supported": "A művelet nem támogatott a webes alkalmazásban",
@@ -34,7 +34,7 @@
"notifications_no_subscriptions_title": "Úgy tűnik, még nem iratkoztál fel egy témára sem.", "notifications_no_subscriptions_title": "Úgy tűnik, még nem iratkoztál fel egy témára sem.",
"publish_dialog_message_published": "Értesítés elküldve", "publish_dialog_message_published": "Értesítés elküldve",
"notifications_example": "Példa", "notifications_example": "Példa",
"notifications_no_subscriptions_description": "Kattints a \"{{linktext}}\" linkre egy téma létrehozásához, vagy rá feliratkozáshoz. Ezután PUT, vagy POST kéréssel lehet értesítéseket küldeni rá, amik itt fognak megjelenni.", "notifications_no_subscriptions_description": "Kattints a \"{{linktext}}\" linkre egy téma létrehozásához, vagy rá feliratkozáshoz. Ezután PUT, vagy POST kéréssel fogsz tudni értesítéseket küldeni rá, amik utána meg fognak itt jelenni.",
"publish_dialog_priority_low": "Alacsony prioritás", "publish_dialog_priority_low": "Alacsony prioritás",
"publish_dialog_priority_default": "Közepes prioritás", "publish_dialog_priority_default": "Közepes prioritás",
"publish_dialog_priority_high": "Magas prioritás", "publish_dialog_priority_high": "Magas prioritás",
@@ -47,7 +47,7 @@
"publish_dialog_base_url_placeholder": "A szolgáltatás URL-e, pl: https://example.com", "publish_dialog_base_url_placeholder": "A szolgáltatás URL-e, pl: https://example.com",
"publish_dialog_topic_label": "Téma neve", "publish_dialog_topic_label": "Téma neve",
"publish_dialog_priority_max": "Legmagasabb prioritás", "publish_dialog_priority_max": "Legmagasabb prioritás",
"publish_dialog_topic_placeholder": "Téma neve, pl: józsi_riasztásai", "publish_dialog_topic_placeholder": "Téma neve, pl: jozsi_riasztasai",
"publish_dialog_title_label": "Cím", "publish_dialog_title_label": "Cím",
"publish_dialog_title_placeholder": "Értesítés címe, pl: Fogy a szabad hely", "publish_dialog_title_placeholder": "Értesítés címe, pl: Fogy a szabad hely",
"publish_dialog_message_label": "Üzenet", "publish_dialog_message_label": "Üzenet",
@@ -58,7 +58,7 @@
"publish_dialog_click_label": "URL", "publish_dialog_click_label": "URL",
"publish_dialog_click_placeholder": "Webcím, ami megnyílik, ha az értesítésre kattintanak", "publish_dialog_click_placeholder": "Webcím, ami megnyílik, ha az értesítésre kattintanak",
"publish_dialog_email_label": "Email", "publish_dialog_email_label": "Email",
"publish_dialog_email_placeholder": "Email cím, amire továbbítjuk az értesítést, pl: fulop@example.com", "publish_dialog_email_placeholder": "Email cím, amire továbbítjuk az értesítést, pl: jozsi@example.com",
"publish_dialog_attach_label": "Csatolmány URL-e", "publish_dialog_attach_label": "Csatolmány URL-e",
"publish_dialog_filename_label": "Fájlnév", "publish_dialog_filename_label": "Fájlnév",
"publish_dialog_filename_placeholder": "Csatolmány fájlneve", "publish_dialog_filename_placeholder": "Csatolmány fájlneve",
@@ -89,7 +89,7 @@
"subscribe_dialog_error_user_anonymous": "névtelen", "subscribe_dialog_error_user_anonymous": "névtelen",
"subscribe_dialog_error_user_not_authorized": "A(z) {{username}} felhasználónak nincs hozzáférése", "subscribe_dialog_error_user_not_authorized": "A(z) {{username}} felhasználónak nincs hozzáférése",
"prefs_notifications_min_priority_description_any": "Minden értesítést mutat, prioritástól függetlenül", "prefs_notifications_min_priority_description_any": "Minden értesítést mutat, prioritástól függetlenül",
"prefs_notifications_min_priority_description_max": "Csak az 5-ös (Legmagasabb) prioritású értesítések jelennek meg", "prefs_notifications_min_priority_description_max": "Csak az 5-ös (legmagasabb) prioritású értesítések jelennek meg",
"prefs_notifications_min_priority_any": "Bármilyen prioritás", "prefs_notifications_min_priority_any": "Bármilyen prioritás",
"prefs_notifications_min_priority_low_and_higher": "Alacsony prioritás, vagy magasabb", "prefs_notifications_min_priority_low_and_higher": "Alacsony prioritás, vagy magasabb",
"prefs_notifications_min_priority_high_and_higher": "Magas, vagy legmagasabb prioritás", "prefs_notifications_min_priority_high_and_higher": "Magas, vagy legmagasabb prioritás",
@@ -114,7 +114,7 @@
"publish_dialog_progress_uploading": "Feltöltés …", "publish_dialog_progress_uploading": "Feltöltés …",
"notifications_click_copy_url_button": "Hivatkozás másolása", "notifications_click_copy_url_button": "Hivatkozás másolása",
"notifications_click_open_button": "Hivatkozás megnyitása", "notifications_click_open_button": "Hivatkozás megnyitása",
"publish_dialog_progress_uploading_detail": "Feltöltés folyamatban: {{loaded}}/{{total}} ({{percent}}%)", "publish_dialog_progress_uploading_detail": "Feltöltés folyamatban: {{loaded}}/{{total}} ({{percent}}%)",
"notifications_none_for_topic_description": "Értesítés beküldéséhez csak küldj egy PUT, vagy POST kérést a téma URL-ére.", "notifications_none_for_topic_description": "Értesítés beküldéséhez csak küldj egy PUT, vagy POST kérést a téma URL-ére.",
"prefs_notifications_delete_after_one_day": "1 nap után", "prefs_notifications_delete_after_one_day": "1 nap után",
"publish_dialog_attach_placeholder": "Csatolandó fájl címe, pl: https://f-droid.org/F-Droid.apk", "publish_dialog_attach_placeholder": "Csatolandó fájl címe, pl: https://f-droid.org/F-Droid.apk",
@@ -123,12 +123,12 @@
"publish_dialog_button_send": "Küldés", "publish_dialog_button_send": "Küldés",
"subscribe_dialog_subscribe_title": "Feliratkozás témára", "subscribe_dialog_subscribe_title": "Feliratkozás témára",
"subscribe_dialog_subscribe_button_cancel": "Mégsem", "subscribe_dialog_subscribe_button_cancel": "Mégsem",
"prefs_notifications_min_priority_title": "Legkisebb piroritás", "prefs_notifications_min_priority_title": "Legkisebb megjelenítendő prioritás",
"prefs_notifications_min_priority_description_x_or_higher": "Csak akkor jelenik meg egy értesítés, ha a prioritása {{number}} ({{name}}), vagy fontosabb", "prefs_notifications_min_priority_description_x_or_higher": "Csak akkor jelenik meg egy értesítés, ha a prioritása {{number}} ({{name}}), vagy fontosabb",
"prefs_notifications_min_priority_default_and_higher": "Közepes prioritás, vagy magasabb", "prefs_notifications_min_priority_default_and_higher": "Közepes prioritás, vagy magasabb",
"prefs_notifications_delete_after_one_week_description": "Az egy hétnél régebbi értesítések automatikus törlése", "prefs_notifications_delete_after_one_week_description": "Az egy hétnél régebbi értesítések automatikus törlése",
"prefs_users_add_button": "Felhasználó hozzáadása", "prefs_users_add_button": "Felhasználó hozzáadása",
"subscribe_dialog_subscribe_topic_placeholder": "Téma neve, pl: józsi_riasztásai", "subscribe_dialog_subscribe_topic_placeholder": "Téma neve, pl: jozsi_riasztasai",
"prefs_notifications_title": "Értesítések", "prefs_notifications_title": "Értesítések",
"error_boundary_button_copy_stack_trace": "Verem nyomkövetés másolása", "error_boundary_button_copy_stack_trace": "Verem nyomkövetés másolása",
"prefs_notifications_delete_after_title": "Régi értesítések törlése", "prefs_notifications_delete_after_title": "Régi értesítések törlése",

View File

@@ -129,7 +129,7 @@
"prefs_users_table_base_url_header": "サービスURL", "prefs_users_table_base_url_header": "サービスURL",
"prefs_users_dialog_username_label": "ユーザー名, 例) phil", "prefs_users_dialog_username_label": "ユーザー名, 例) phil",
"prefs_users_dialog_password_label": "パスワード", "prefs_users_dialog_password_label": "パスワード",
"error_boundary_title": "ああ、ntfyがクラッシュしました", "error_boundary_title": "おっと、ntfyがクラッシュしました",
"error_boundary_button_copy_stack_trace": "スタックトレースをコピー", "error_boundary_button_copy_stack_trace": "スタックトレースをコピー",
"error_boundary_stack_trace": "スタックトレース", "error_boundary_stack_trace": "スタックトレース",
"error_boundary_gathering_info": "更に情報を集める…", "error_boundary_gathering_info": "更に情報を集める…",
@@ -150,5 +150,7 @@
"priority_default": "通常", "priority_default": "通常",
"prefs_notifications_delete_after_three_hours_description": "通知は3時間後に自動的に削除されます", "prefs_notifications_delete_after_three_hours_description": "通知は3時間後に自動的に削除されます",
"priority_low": "低", "priority_low": "低",
"priority_min": "最低" "priority_min": "最低",
"notifications_actions_not_supported": "このアクションはWebアプリではサポートされていません",
"notifications_actions_http_request_title": "{{url}}にHTTP {{method}}を送信"
} }

View File

@@ -34,5 +34,124 @@
"notifications_attachment_link_expires": "link expira em {{date}}", "notifications_attachment_link_expires": "link expira em {{date}}",
"notifications_attachment_copy_url_button": "Copiar URL", "notifications_attachment_copy_url_button": "Copiar URL",
"notifications_attachment_link_expired": "link para transferência expirado", "notifications_attachment_link_expired": "link para transferência expirado",
"notifications_example": "Exemplo" "notifications_example": "Exemplo",
"notifications_more_details": "Para mais informações, confira <websiteLink>site</websiteLink> ou <docsLink>documentação</docsLink>.",
"notifications_loading": "Carregando notificações…",
"subscribe_dialog_error_user_anonymous": "anônimo",
"prefs_notifications_delete_after_three_hours": "Após três horas",
"prefs_notifications_delete_after_one_day": "Após um dia",
"prefs_notifications_delete_after_one_week": "Após uma semana",
"prefs_notifications_delete_after_one_month": "Após um mês",
"notifications_actions_not_supported": "Ação não suportada no aplicativo web",
"notifications_actions_http_request_title": "Enviar HTTP {{method}} para {{url}}",
"notifications_actions_open_url_title": "Ir para {{url}}",
"publish_dialog_title_topic": "Publicar em {{topic}}",
"publish_dialog_title_no_topic": "Publicar notificação",
"publish_dialog_progress_uploading": "Enviando …",
"publish_dialog_progress_uploading_detail": "Fazendo upload de {{loaded}}/{{total}} ({{percent}}%)…",
"publish_dialog_message_published": "Notificação publicada",
"publish_dialog_attachment_limits_file_reached": "excede o limite de arquivo {{fileSizeLimit}}",
"publish_dialog_priority_min": "Prioridade mínima",
"publish_dialog_priority_low": "Baixa prioridade",
"publish_dialog_priority_default": "Prioridade padrão",
"publish_dialog_base_url_label": "URL de serviço",
"publish_dialog_base_url_placeholder": "URL de serviço, por exemplo https://example.com",
"publish_dialog_topic_label": "Nome do tópico",
"publish_dialog_topic_placeholder": "Nome do tópico, por exemplo, phil_alerts",
"publish_dialog_title_label": "Título",
"publish_dialog_title_placeholder": "Título da notificação, por exemplo Alerta de espaço em disco",
"publish_dialog_message_label": "Mensagem",
"publish_dialog_message_placeholder": "Digite uma mensagem aqui",
"publish_dialog_tags_label": "Etiquetas",
"publish_dialog_tags_placeholder": "Lista de etiquetas, separadas por vírgula, por exemplo: srv1-backup",
"publish_dialog_priority_label": "Prioridade",
"publish_dialog_click_label": "Clique em URL",
"publish_dialog_click_placeholder": "URL que é aberto quando a notificação é clicada",
"publish_dialog_email_label": "Email",
"publish_dialog_email_placeholder": "Email para encaminhar a notificação, por exemplo phil@example.com",
"publish_dialog_filename_label": "Nome do arquivo",
"publish_dialog_filename_placeholder": "Nome do arquivo anexado",
"publish_dialog_delay_label": "Atraso",
"publish_dialog_delay_placeholder": "Atraso na entrega, por exemplo {{{unixTimestamp}}, {{relativeTime}}, ou \"{{naturalLanguage}}\" (apenas em inglês)",
"publish_dialog_other_features": "Outros recursos:",
"publish_dialog_chip_click_label": "Clique em URL",
"publish_dialog_chip_attach_file_label": "Anexar arquivo local",
"publish_dialog_chip_delay_label": "Atraso na entrega",
"publish_dialog_chip_topic_label": "Alterar tópico",
"publish_dialog_button_cancel_sending": "Cancelar o envio",
"publish_dialog_attached_file_filename_placeholder": "Nome do arquivo anexado",
"publish_dialog_drop_file_here": "Solte o arquivo aqui",
"emoji_picker_search_placeholder": "Pesquisar emoji",
"subscribe_dialog_subscribe_title": "Inscrever no tópico",
"subscribe_dialog_subscribe_use_another_label": "Usar outro servidor",
"subscribe_dialog_subscribe_description": "Os tópicos podem não ser protegidos por senha, então escolha um nome que não seja fácil de adivinhar. Uma vez inscrito, você pode PUT/POST notificações.",
"subscribe_dialog_subscribe_topic_placeholder": "Nome do tópico, por exemplo phil_alerts",
"subscribe_dialog_subscribe_button_cancel": "Cancelar",
"subscribe_dialog_subscribe_button_subscribe": "Inscrever",
"prefs_notifications_min_priority_description_max": "Mostrar notificações se prioridade for 5 (máxima)",
"prefs_notifications_min_priority_any": "Qualquer prioridade",
"prefs_notifications_min_priority_low_and_higher": "Baixa prioridade e acima",
"prefs_notifications_min_priority_default_and_higher": "Prioridade padrão e acima",
"subscribe_dialog_login_password_label": "Senha",
"subscribe_dialog_login_button_back": "Voltar",
"prefs_notifications_min_priority_high_and_higher": "Alta prioridade e acima",
"prefs_notifications_min_priority_max_only": "Apenas prioridade máxima",
"prefs_notifications_delete_after_title": "Apagar notificações",
"prefs_notifications_delete_after_never": "Nunca",
"prefs_notifications_delete_after_never_description": "Notificações nunca serão auto excluídas",
"prefs_users_description": "Adicionar/remover usuários em seus tópicos protegidos. Note que o usuário e senha são salvos no armazenamento local do navegador.",
"prefs_users_add_button": "Adicionar usuário",
"prefs_users_table_user_header": "Usuário",
"prefs_users_table_base_url_header": "URL de serviço",
"prefs_users_dialog_title_add": "Adicionar usuário",
"prefs_users_dialog_title_edit": "Editar usuário",
"prefs_users_dialog_base_url_label": "URL de serviço, exemplo https://ntfy.sh",
"prefs_users_dialog_username_label": "Usuário, por exemplo phil",
"prefs_users_dialog_password_label": "Senha",
"prefs_users_dialog_button_cancel": "Cancelar",
"prefs_users_dialog_button_add": "Adicionar",
"prefs_users_dialog_button_save": "Salvar",
"prefs_appearance_title": "Aparência",
"prefs_appearance_language_title": "LInguagem",
"priority_min": "minima",
"priority_low": "baixa",
"priority_default": "padrão",
"priority_high": "alta",
"priority_max": "máxima",
"error_boundary_title": "Ah não, ntfy parou de funcionar",
"error_boundary_gathering_info": "Coletar mais informações …",
"error_boundary_description": "Isto obviamente não deveria ter acontecido. Lamentamos muito por isto.<br/>Se tiver um minuto, por favor <githubLink> relate isto no GitHub</githubLink>, ou informe-nos através de <discordLink>Discord</discordLink> ou <matrixLink>Matrix</matrixLink>.",
"error_boundary_button_copy_stack_trace": "Copiar rastreamento de pilha",
"error_boundary_stack_trace": "Rastreamento de pilha",
"publish_dialog_attachment_limits_file_and_quota_reached": "excede {{fileSizeLimit}} limite de arquivo e cota, {{remainingBytes}} restante",
"publish_dialog_attachment_limits_quota_reached": "excede a cota, {{remainingBytes}} restantes",
"publish_dialog_priority_high": "Alta prioridade",
"publish_dialog_priority_max": "Prioridade máxima",
"publish_dialog_button_send": "Enviar",
"publish_dialog_attached_file_title": "Arquivo anexado:",
"publish_dialog_attach_label": "URL de anexo",
"publish_dialog_chip_attach_url_label": "Anexar arquivo por URL",
"publish_dialog_attach_placeholder": "Anexar arquivo por URL, por exemplo, https://f-droid.org/F-Droid.apk",
"publish_dialog_chip_email_label": "Encaminhar para email",
"publish_dialog_checkbox_publish_another": "Publicar outro",
"publish_dialog_details_examples_description": "Para obter exemplos e uma descrição detalhada de todos os recursos de envio, consulte a <docsLink>documentação</docsLink>.",
"publish_dialog_button_cancel": "Cancelar",
"prefs_notifications_delete_after_one_day_description": "Notificações são automaticamente excluídas após um dia",
"prefs_notifications_delete_after_one_month_description": "Notificações são automaticamente excluídas após um mês",
"prefs_users_title": "Gerenciar usuários",
"subscribe_dialog_error_user_not_authorized": "Usuário {{username}} não autorizado",
"prefs_notifications_title": "Notificações",
"prefs_notifications_sound_no_sound": "Sem som",
"subscribe_dialog_login_title": "Login necessário",
"prefs_notifications_sound_title": "Som de notificações",
"prefs_notifications_min_priority_title": "Mínima prioridade",
"prefs_notifications_min_priority_description_any": "Mostrando todas as notificações, independente da prioridade",
"prefs_notifications_delete_after_one_week_description": "Notificações são automaticamente excluídas após uma semana",
"subscribe_dialog_login_description": "Esse tópico é protegido por senha. Por favor digite o nome de usuário e senha para inscrever.",
"subscribe_dialog_login_username_label": "Nome, por exemplo phil",
"subscribe_dialog_login_button_login": "Login",
"prefs_notifications_sound_description_none": "Notificações não reproduzem nenhum som quando chegam",
"prefs_notifications_sound_description_some": "Notificações reproduzem som {{sound}} quando chegam",
"prefs_notifications_min_priority_description_x_or_higher": "Mostrar notificações se prioridade for {{number}} ({{name}}) ou acima",
"prefs_notifications_delete_after_three_hours_description": "Notificações são automaticamente excluídas após três horas"
} }

View File

@@ -436,7 +436,7 @@ const Appearance = () => {
const Language = () => { const Language = () => {
const { t, i18n } = useTranslation(); const { t, i18n } = useTranslation();
const labelId = "prefLanguage"; const labelId = "prefLanguage";
const randomFlags = shuffle(["🇬🇧", "🇺🇸", "🇪🇸", "🇫🇷", "🇧🇬", "🇨🇿", "🇩🇪", "🇭🇺", "🇮🇩", "🇯🇵", "🇷🇺", "🇹🇷"]).slice(0, 3); const randomFlags = shuffle(["🇬🇧", "🇺🇸", "🇪🇸", "🇫🇷", "🇧🇬", "🇨🇿", "🇩🇪", "🇭🇺", "🇧🇷", "🇮🇩", "🇯🇵", "🇷🇺", "🇹🇷"]).slice(0, 3);
const title = t("prefs_appearance_language_title") + " " + randomFlags.join(" "); const title = t("prefs_appearance_language_title") + " " + randomFlags.join(" ");
const lang = i18n.language ?? "en"; const lang = i18n.language ?? "en";
@@ -458,6 +458,7 @@ const Language = () => {
<MenuItem value="id">Bahasa Indonesia</MenuItem> <MenuItem value="id">Bahasa Indonesia</MenuItem>
<MenuItem value="ja">日本語</MenuItem> <MenuItem value="ja">日本語</MenuItem>
<MenuItem value="nb_NO">Norsk bokmål</MenuItem> <MenuItem value="nb_NO">Norsk bokmål</MenuItem>
<MenuItem value="pt_BR">Português</MenuItem>
<MenuItem value="ru">Русский</MenuItem> <MenuItem value="ru">Русский</MenuItem>
<MenuItem value="tr">Türkçe</MenuItem> <MenuItem value="tr">Türkçe</MenuItem>
</Select> </Select>