Compare commits

...

10 Commits

Author SHA1 Message Date
Thomas Miceli
9b0c06d98b v1.7.2 2024-05-05 00:56:56 +02:00
Thomas Miceli
0757c4e7fb Use go 1.22 and update deps (#244) 2024-05-05 00:38:06 +02:00
Thomas Miceli
1ec77590e9 Translations update from Weblate (#271)
* Translated using Weblate (Czech)

Currently translated at 67.2% (162 of 241 strings)

Translation: Opengist/Opengist
Translate-URL: http://tr.opengist.io/projects/_/opengist/cs/

* Translated using Weblate (Czech)

Currently translated at 67.2% (162 of 241 strings)

Translation: Opengist/Opengist
Translate-URL: http://tr.opengist.io/projects/_/opengist/cs/

* Translated using Weblate (Spanish)

Currently translated at 64.7% (156 of 241 strings)

Translation: Opengist/Opengist
Translate-URL: http://tr.opengist.io/projects/_/opengist/es/

* Translated using Weblate (French)

Currently translated at 73.8% (178 of 241 strings)

Translation: Opengist/Opengist
Translate-URL: http://tr.opengist.io/projects/_/opengist/fr/

* Translated using Weblate (Hungarian)

Currently translated at 73.0% (176 of 241 strings)

Translation: Opengist/Opengist
Translate-URL: http://tr.opengist.io/projects/_/opengist/hu/

* Translated using Weblate (Portuguese (Brazil))

Currently translated at 64.7% (156 of 241 strings)

Translation: Opengist/Opengist
Translate-URL: http://tr.opengist.io/projects/_/opengist/pt_BR/

* Translated using Weblate (Russian)

Currently translated at 65.1% (157 of 241 strings)

Translation: Opengist/Opengist
Translate-URL: http://tr.opengist.io/projects/_/opengist/ru/

* Translated using Weblate (Chinese (Simplified))

Currently translated at 65.1% (157 of 241 strings)

Translation: Opengist/Opengist
Translate-URL: http://tr.opengist.io/projects/_/opengist/zh_Hans/

* Translated using Weblate (Chinese (Traditional))

Currently translated at 73.8% (178 of 241 strings)

Translation: Opengist/Opengist
Translate-URL: http://tr.opengist.io/projects/_/opengist/zh_Hant/

* Translated using Weblate (German)

Currently translated at 73.4% (177 of 241 strings)

Translation: Opengist/Opengist
Translate-URL: http://tr.opengist.io/projects/_/opengist/de/

---------

Co-authored-by: Anonymous <noreply@weblate.org>
Co-authored-by: Jiří Štefka <jiri@stefka.eu>
2024-05-05 00:37:10 +02:00
Thomas Miceli
e439d96e43 Add translation strings (#269) 2024-05-05 00:24:25 +02:00
Thomas Miceli
1aa94292db Frontend fixes (#267)
* Fix mermaid display

* Move Login/Register buttons on mobile

* Min width on avatar
2024-04-28 02:54:18 +02:00
Thomas Miceli
3551fd745a Set Opengist version from git tags (#261)
* Set Opengist version from git tags

* Add volume for docker dev container
2024-04-27 02:53:48 +02:00
Thomas Miceli
785d89d6ab Rework git log parsing and truncating (#260) 2024-04-27 01:49:53 +02:00
Dennis
6a8759e21e fix missing preview button when editing .md gist (#259)
Co-authored-by: Dennis Sumser <dennis.sumser@schmolck.de>
2024-04-24 21:02:21 +02:00
Guilhem Lettron
a3a3d367ea feat: add kubernetes deployment with kustomize (#258)
Signed-off-by: Guilhem Lettron <guilhem@barpilot.io>
2024-04-24 21:01:17 +02:00
TehPeGaSuS
e4bbd756f0 Update run-with-systemd.md (#254)
Add documention how to use systemd without root access
2024-04-23 23:43:26 +02:00
48 changed files with 1565 additions and 778 deletions

View File

@@ -15,10 +15,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Go 1.21
- name: Set up Go 1.22
uses: actions/setup-go@v4
with:
go-version: "1.21"
go-version: "1.22"
- name: Lint
uses: golangci/golangci-lint-action@v3
@@ -36,10 +36,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Go 1.21
- name: Set up Go 1.22
uses: actions/setup-go@v4
with:
go-version: "1.21"
go-version: "1.22"
- name: Check
run: make go_mod check_changes
@@ -49,7 +49,7 @@ jobs:
fail-fast: false
matrix:
os: ["ubuntu-latest", "macOS-latest", "windows-latest"]
go: ["1.21"]
go: ["1.22"]
runs-on: ${{ matrix.os }}
steps:
- name: Checkout

View File

@@ -13,10 +13,10 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Go 1.21
- name: Set up Go 1.22
uses: actions/setup-go@v4
with:
go-version: "1.21"
go-version: "1.22"
- name: Cross compile build
run: make all_crosscompile

View File

@@ -1,5 +1,28 @@
# Changelog
## [1.7.2](https://github.com/thomiceli/opengist/compare/v1.7.1...v1.7.2) - 2024-05-05
See here how to [update](/docs/update.md) Opengist.
### Added
- Docs:
- Run with systemd as a normal user (#254)
- Kubernetes deployment (#258)
- More translation strings (#269) (#271)
### Changed
- Rework git log parsing and truncating (#260)
- Set Opengist version from git tags (#261)
### Fixed
- Missing preview button when editing .md gist (#259)
- Frontend (#267)
- Fix mermaid display
- Move Login/Register buttons on mobile
- Set minimum width on avatar
### Other
- Use go 1.22 and update deps (#244)
## [1.7.1](https://github.com/thomiceli/opengist/compare/v1.7.0...v1.7.1) - 2024-04-05
See here how to [update](/docs/update.md) Opengist.

View File

@@ -15,7 +15,7 @@ RUN apk update && \
musl-dev \
libstdc++
COPY --from=golang:1.21-alpine /usr/local/go/ /usr/local/go/
COPY --from=golang:1.22-alpine /usr/local/go/ /usr/local/go/
ENV PATH="/usr/local/go/bin:${PATH}"
ENV CGO_ENABLED=0
@@ -33,6 +33,8 @@ FROM base AS dev
EXPOSE 6157 2222 16157
VOLUME /opengist
RUN git config --global --add safe.directory /opengist
CMD ["make", "watch"]

View File

@@ -2,6 +2,8 @@
# Specify the name of your Go binary output
BINARY_NAME := opengist
GIT_TAG := $(shell git describe --tags)
VERSION_PKG := github.com/thomiceli/opengist/internal/config.OpengistVersion
all: clean install build
@@ -20,7 +22,7 @@ build_frontend:
build_backend:
@echo "Building Opengist binary..."
go build -tags fs_embed -o $(BINARY_NAME) .
go build -tags fs_embed -ldflags "-X $(VERSION_PKG)=$(GIT_TAG)" -o $(BINARY_NAME) .
build: build_frontend build_backend
@@ -36,7 +38,7 @@ build_dev_docker:
docker build -t $(BINARY_NAME)-dev:latest --target dev .
run_dev_docker:
docker run -v .:/opengist -p 6157:6157 -p 16157:16157 $(BINARY_NAME)-dev:latest
docker run -v .:/opengist -p 6157:6157 -p 16157:16157 -v $(HOME)/.opengist-dev:/root/.opengist --rm $(BINARY_NAME)-dev:latest
watch_frontend:
@echo "Building frontend assets..."
@@ -44,7 +46,7 @@ watch_frontend:
watch_backend:
@echo "Building Opengist binary..."
OG_DEV=1 npx nodemon --watch '**/*' -e html,yml,go,js --signal SIGTERM --exec 'go run . --config config.yml'
OG_DEV=1 npx nodemon --watch '**/*' -e html,yml,go,js --signal SIGTERM --exec 'go run -ldflags "-X $(VERSION_PKG)=$(GIT_TAG)" . --config config.yml'
watch:
@sh ./scripts/watch.sh

View File

@@ -6,7 +6,7 @@ Opengist is a **self-hosted** pastebin **powered by Git**. All snippets are stor
read and/or modified using standard Git commands, or with the web interface.
It is similiar to [GitHub Gist](https://gist.github.com/), but open-source and could be self-hosted.
[Documentation](/docs) • [Demo](https://opengist.thomice.li)
[Documentation](/docs) • [Discord](https://discord.gg/9Pm3X5scZT) • [Demo](https://demo.opengist.io)
![GitHub release (latest SemVer)](https://img.shields.io/github/v/release/thomiceli/opengist?sort=semver)
@@ -78,9 +78,9 @@ Download the archive for your system from the release page [here](https://github
```shell
# example for linux amd64
wget https://github.com/thomiceli/opengist/releases/download/v1.7.1/opengist1.7.1-linux-amd64.tar.gz
wget https://github.com/thomiceli/opengist/releases/download/v1.7.2/opengist1.7.2-linux-amd64.tar.gz
tar xzvf opengist1.7.1-linux-amd64.tar.gz
tar xzvf opengist1.7.2-linux-amd64.tar.gz
cd opengist
chmod +x opengist
./opengist # with or without `--config config.yml`
@@ -90,7 +90,7 @@ Opengist is now running on port 6157, you can browse http://localhost:6157
### From source
Requirements: [Git](https://git-scm.com/downloads) (2.28+), [Go](https://go.dev/doc/install) (1.21+), [Node.js](https://nodejs.org/en/download/) (16+), [Make](https://linux.die.net/man/1/make) (optional, but easier)
Requirements: [Git](https://git-scm.com/downloads) (2.28+), [Go](https://go.dev/doc/install) (1.22+), [Node.js](https://nodejs.org/en/download/) (16+), [Make](https://linux.die.net/man/1/make) (optional, but easier)
```shell
git clone https://github.com/thomiceli/opengist

75
deploy/README.md Normal file
View File

@@ -0,0 +1,75 @@
# kustomize
## Simple
`kustomization.yaml`:
```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
metadata:
name: opengist
resources:
- https://github.com/thomiceli/opengist/deploy/
```
## Full example
`kustomization.yaml`:
```yaml
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
metadata:
name: opengist
namespace: opengist
resources:
- namespace.yaml
- https://github.com/thomiceli/opengist/deploy/?ref:v1.7.2
images:
- name: ghcr.io/thomiceli/opengist
newTag: 1.7.2
patches:
# Add your ingress
- path: ingress.yaml
- patch: |-
- op: add
path: /spec/rules/0/host
value: opengist.mydomain.com
target:
group: networking.k8s.io
version: v1
kind: Ingress
name: opengist
```
`namespace.yaml`:
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: opengist
```
`ingress.yaml`:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: opengist
annotations:
cert-manager.io/cluster-issuer: letsencrypt-production
spec:
ingressClassName: nginx
tls:
- hosts:
- opengist.mydomain.com
secretName: opengist-tls
```

29
deploy/deployment.yaml Normal file
View File

@@ -0,0 +1,29 @@
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: opengist
spec:
selector:
matchLabels:
app.kubernetes.io/name: opengist
template:
metadata:
labels:
app.kubernetes.io/name: opengist
spec:
containers:
- name: opengist
image: ghcr.io/thomiceli/opengist
ports:
- name: http
containerPort: 6157
- name: ssh
containerPort: 2222
volumeMounts:
- mountPath: /opengist
name: data
volumes:
- name: data
persistentVolumeClaim:
claimName: opengist-data

20
deploy/ingress.yaml Normal file
View File

@@ -0,0 +1,20 @@
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: opengist
labels:
app.kubernetes.io/name: opengist
app.kubernetes.io/component: ingress
spec:
rules:
- host: opengist.local
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: opengist
port:
name: http

11
deploy/kustomization.yaml Normal file
View File

@@ -0,0 +1,11 @@
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
metadata:
name: opengist
resources:
- deployment.yaml
- pvc.yaml
- ingress.yaml
- service.yaml

15
deploy/pvc.yaml Normal file
View File

@@ -0,0 +1,15 @@
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: opengist-data
labels:
app.kubernetes.io/name: opengist
app.kubernetes.io/component: data
spec:
resources:
requests:
storage: 1Gi
volumeMode: Filesystem
accessModes:
- ReadWriteOnce

14
deploy/service.yaml Normal file
View File

@@ -0,0 +1,14 @@
---
apiVersion: v1
kind: Service
metadata:
name: opengist
labels:
app.kubernetes.io/name: opengist
spec:
selector:
app.kubernetes.io/name: opengist
ports:
- port: 80
targetPort: http
name: http

View File

@@ -2,6 +2,7 @@
For non-Docker users, you could run Opengist as a systemd service.
## As root
On Unix distributions with systemd, place the Opengist binary like:
```shell
@@ -45,3 +46,47 @@ systemctl daemon-reload
systemctl enable --now opengist
systemctl status opengist
```
----
## As a normal user
**NOTE: This was tested on Ubuntu 20.04 and newer. For other distros, please check the respective documentation**
#### For the purpose of this documentation, we will assume that:
- You've followed the instructions on how to run opengist [from source](https://github.com/thomiceli/opengist?tab=readme-ov-file#from-source)
- Your shell user is named `pastebin`
- All commands are being executed as the `pastebin` user
_If none of the above is true, then adapt the commands and paths to fit your needs._
Enable lingering for the user:
```shell
loginctl enable-linger
```
Create the user systemd folder:
```
mkdir -p /home/pastebin/.config/systemd/user
```
Then create a service file at `/home/pastebin/.config/systemd/user/opengist.service`:
```ini
[Unit]
Description=opengist Server
After=network.target
[Service]
Type=simple
ExecStart=/home/pastebin/opengist/opengist --config /home/pastebin/opengist/config.yml
Restart=on-failure
[Install]
WantedBy=default.target
```
Finally, start the service:
```shell
systemctl --user daemon-reload
systemctl --user enable --now opengist
systemctl --user status opengist
```

View File

@@ -25,7 +25,7 @@ Opengist is now running on port 6157, you can browse http://localhost:6157
Requirements:
* [Git](https://git-scm.com/downloads) (2.28+)
* [Go](https://go.dev/doc/install) (1.21+)
* [Go](https://go.dev/doc/install) (1.22+)
* [Node.js](https://nodejs.org/en/download/) (16+)
* [Make](https://linux.die.net/man/1/make) (optional, but easier)

View File

@@ -47,9 +47,9 @@ Download the archive for your system from the release page [here](https://github
```shell
# example for linux amd64
wget https://github.com/thomiceli/opengist/releases/download/v1.7.1/opengist1.7.1-linux-amd64.tar.gz
wget https://github.com/thomiceli/opengist/releases/download/v1.7.2/opengist1.7.2-linux-amd64.tar.gz
tar xzvf opengist1.7.1-linux-amd64.tar.gz
tar xzvf opengist1.7.2-linux-amd64.tar.gz
cd opengist
chmod +x opengist
./opengist # with or without `--config config.yml`
@@ -60,7 +60,7 @@ chmod +x opengist
Requirements:
* [Git](https://git-scm.com/downloads) (2.28+)
* [Go](https://go.dev/doc/install) (1.21+)
* [Go](https://go.dev/doc/install) (1.22+)
* [Node.js](https://nodejs.org/en/download/) (16+)
* [Make](https://linux.die.net/man/1/make) (optional, but easier)

View File

@@ -27,9 +27,9 @@ Stop the running instance; then like your first installation of Opengist, downlo
```shell
# example for linux amd64
wget https://github.com/thomiceli/opengist/releases/download/v1.7.1/opengist1.7.1-linux-amd64.tar.gz
wget https://github.com/thomiceli/opengist/releases/download/v1.7.2/opengist1.7.2-linux-amd64.tar.gz
tar xzvf opengist1.7.1-linux-amd64.tar.gz
tar xzvf opengist1.7.2-linux-amd64.tar.gz
cd opengist
chmod +x opengist
./opengist # with or without `--config config.yml`

71
go.mod
View File

@@ -1,43 +1,44 @@
module github.com/thomiceli/opengist
go 1.21
go 1.22
require (
github.com/Kunde21/markdownfmt/v3 v3.1.0
github.com/alecthomas/chroma/v2 v2.12.0
github.com/blevesearch/bleve/v2 v2.3.10
github.com/alecthomas/chroma/v2 v2.13.0
github.com/blevesearch/bleve/v2 v2.4.0
github.com/dustin/go-humanize v1.0.1
github.com/glebarez/go-sqlite v1.22.0
github.com/glebarez/sqlite v1.10.0
github.com/go-playground/validator/v10 v10.16.0
github.com/google/uuid v1.5.0
github.com/glebarez/sqlite v1.11.0
github.com/go-playground/validator/v10 v10.20.0
github.com/google/uuid v1.6.0
github.com/gorilla/securecookie v1.1.2
github.com/gorilla/sessions v1.2.2
github.com/hashicorp/go-memdb v1.3.4
github.com/labstack/echo/v4 v4.11.4
github.com/markbates/goth v1.78.0
github.com/rs/zerolog v1.31.0
github.com/stretchr/testify v1.8.4
github.com/urfave/cli/v2 v2.27.1
github.com/yuin/goldmark v1.6.0
github.com/labstack/echo/v4 v4.12.0
github.com/markbates/goth v1.79.0
github.com/rs/zerolog v1.32.0
github.com/stretchr/testify v1.9.0
github.com/urfave/cli/v2 v2.27.2
github.com/yuin/goldmark v1.7.1
github.com/yuin/goldmark-emoji v1.0.2
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc
go.abhg.dev/goldmark/mermaid v0.5.0
golang.org/x/crypto v0.17.0
golang.org/x/text v0.14.0
golang.org/x/crypto v0.22.0
golang.org/x/text v0.15.0
gopkg.in/yaml.v3 v3.0.1
gorm.io/gorm v1.25.5
gorm.io/gorm v1.25.10
)
require (
github.com/RoaringBitmap/roaring v1.7.0 // indirect
github.com/RoaringBitmap/roaring v1.9.3 // indirect
github.com/bits-and-blooms/bitset v1.13.0 // indirect
github.com/blevesearch/bleve_index_api v1.1.4 // indirect
github.com/blevesearch/geo v0.1.18 // indirect
github.com/blevesearch/bleve_index_api v1.1.6 // indirect
github.com/blevesearch/geo v0.1.20 // indirect
github.com/blevesearch/go-faiss v1.0.15 // indirect
github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
github.com/blevesearch/gtreap v0.1.1 // indirect
github.com/blevesearch/mmap-go v1.0.4 // indirect
github.com/blevesearch/scorch_segment_api/v2 v2.2.5 // indirect
github.com/blevesearch/scorch_segment_api/v2 v2.2.11 // indirect
github.com/blevesearch/segment v0.9.1 // indirect
github.com/blevesearch/snowballstem v0.9.0 // indirect
github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
@@ -47,15 +48,16 @@ require (
github.com/blevesearch/zapx/v13 v13.3.10 // indirect
github.com/blevesearch/zapx/v14 v14.3.10 // indirect
github.com/blevesearch/zapx/v15 v15.3.13 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/blevesearch/zapx/v16 v16.0.12 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dlclark/regexp2 v1.10.0 // indirect
github.com/dlclark/regexp2 v1.11.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang/geo v0.0.0-20230421003525-6adc56603217 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/gorilla/mux v1.8.1 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
@@ -63,30 +65,31 @@ require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/labstack/gommon v0.4.2 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mschoch/smat v0.2.0 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/rivo/uniseg v0.4.7 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasttemplate v1.2.2 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.etcd.io/bbolt v1.3.8 // indirect
golang.org/x/net v0.19.0 // indirect
golang.org/x/oauth2 v0.15.0 // indirect
golang.org/x/sys v0.15.0 // indirect
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
go.etcd.io/bbolt v1.3.9 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/oauth2 v0.20.0 // indirect
golang.org/x/sys v0.20.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/protobuf v1.32.0 // indirect
modernc.org/libc v1.38.0 // indirect
google.golang.org/protobuf v1.34.0 // indirect
modernc.org/libc v1.50.5 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.7.2 // indirect
modernc.org/sqlite v1.28.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/sqlite v1.29.8 // indirect
)

597
go.sum
View File

@@ -1,68 +1,34 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.67.0/go.mod h1:YNan/mUhNZFrYUor0vqrsQ0Ffl7Xtm/ACOy/vsTS858=
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.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Kunde21/markdownfmt/v3 v3.1.0 h1:KiZu9LKs+wFFBQKhrZJrFZwtLnCCWJahL+S+E/3VnM0=
github.com/Kunde21/markdownfmt/v3 v3.1.0/go.mod h1:tPXN1RTyOzJwhfHoon9wUr4HGYmWgVxSQN6VBJDkrVc=
github.com/RoaringBitmap/roaring v1.7.0 h1:OZF303tJCER1Tj3x+aArx/S5X7hrT186ri6JjrGvG68=
github.com/RoaringBitmap/roaring v1.7.0/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
github.com/alecthomas/assert/v2 v2.2.1 h1:XivOgYcduV98QCahG8T5XTezV5bylXe+lBxLG2K2ink=
github.com/alecthomas/assert/v2 v2.2.1/go.mod h1:pXcQ2Asjp247dahGEmsZ6ru0UVwnkhktn7S0bBDLxvQ=
github.com/RoaringBitmap/roaring v1.9.3 h1:t4EbC5qQwnisr5PrP9nt0IRhRTb9gMUgQF4t4S2OByM=
github.com/RoaringBitmap/roaring v1.9.3/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
github.com/alecthomas/assert/v2 v2.6.0 h1:o3WJwILtexrEUk3cUVal3oiQY2tfgr/FHWiz/v2n4FU=
github.com/alecthomas/assert/v2 v2.6.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
github.com/alecthomas/chroma/v2 v2.2.0/go.mod h1:vf4zrexSH54oEjJ7EdB65tGNHmH3pGZmVkgTP5RHvAs=
github.com/alecthomas/chroma/v2 v2.12.0 h1:Wh8qLEgMMsN7mgyG8/qIpegky2Hvzr4By6gEF7cmWgw=
github.com/alecthomas/chroma/v2 v2.12.0/go.mod h1:4TQu7gdfuPjSh76j78ietmqh9LiurGF0EpseFXdKMBw=
github.com/alecthomas/chroma/v2 v2.13.0 h1:VP72+99Fb2zEcYM0MeaWJmV+xQvz5v5cxRHd+ooU1lI=
github.com/alecthomas/chroma/v2 v2.13.0/go.mod h1:BUGjjsD+ndS6eX37YgTchSEG+Jg9Jv1GiZs9sqPqztk=
github.com/alecthomas/repr v0.0.0-20220113201626-b1b626ac65ae/go.mod h1:2kn6fqh/zIyPLmm3ugklbEi5hg5wS435eygvNfaDQL8=
github.com/alecthomas/repr v0.2.0 h1:HAzS41CIzNW5syS8Mf9UwXhNH1J9aix/BvDRf1Ml2Yk=
github.com/alecthomas/repr v0.2.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
github.com/blevesearch/bleve/v2 v2.3.10 h1:z8V0wwGoL4rp7nG/O3qVVLYxUqCbEwskMt4iRJsPLgg=
github.com/blevesearch/bleve/v2 v2.3.10/go.mod h1:RJzeoeHC+vNHsoLR54+crS1HmOWpnH87fL70HAUCzIA=
github.com/blevesearch/bleve_index_api v1.1.4 h1:n9Ilxlb80g9DAhchR95IcVrzohamDSri0wPnkKnva50=
github.com/blevesearch/bleve_index_api v1.1.4/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8=
github.com/blevesearch/geo v0.1.18 h1:Np8jycHTZ5scFe7VEPLrDoHnnb9C4j636ue/CGrhtDw=
github.com/blevesearch/geo v0.1.18/go.mod h1:uRMGWG0HJYfWfFJpK3zTdnnr1K+ksZTuWKhXeSokfnM=
github.com/blevesearch/bleve/v2 v2.4.0 h1:2xyg+Wv60CFHYccXc+moGxbL+8QKT/dZK09AewHgKsg=
github.com/blevesearch/bleve/v2 v2.4.0/go.mod h1:IhQHoFAbHgWKYavb9rQgQEJJVMuY99cKdQ0wPpst2aY=
github.com/blevesearch/bleve_index_api v1.1.6 h1:orkqDFCBuNU2oHW9hN2YEJmet+TE9orml3FCGbl1cKk=
github.com/blevesearch/bleve_index_api v1.1.6/go.mod h1:PbcwjIcRmjhGbkS/lJCpfgVSMROV6TRubGGAODaK1W8=
github.com/blevesearch/geo v0.1.20 h1:paaSpu2Ewh/tn5DKn/FB5SzvH0EWupxHEIwbCk/QPqM=
github.com/blevesearch/geo v0.1.20/go.mod h1:DVG2QjwHNMFmjo+ZgzrIq2sfCh6rIHzy9d9d0B59I6w=
github.com/blevesearch/go-faiss v1.0.15 h1:aBrj6fwLuY8CkhECFbvkc4qhLTkrYI84QoEaw9z1jMI=
github.com/blevesearch/go-faiss v1.0.15/go.mod h1:jrxHrbl42X/RnDPI+wBoZU8joxxuRwedrxqswQ3xfU8=
github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
github.com/blevesearch/scorch_segment_api/v2 v2.2.5 h1:5SsNQmR8v1bojtGQ1zFhZravcMg5rdiX8AVu6LwlVtc=
github.com/blevesearch/scorch_segment_api/v2 v2.2.5/go.mod h1:8N2ytOlBCdurlxDgbqsfeR1oTKRN0ZVIKdUUP1VFZNc=
github.com/blevesearch/scorch_segment_api/v2 v2.2.11 h1:nb5KTeIhDUu+Ka6He7xXvOXcJOt9Db7c3Vy2ptqJQRs=
github.com/blevesearch/scorch_segment_api/v2 v2.2.11/go.mod h1:QVakeAECt+Fxe+zu0A4V1bgPdqNeC93wQvzaXDF3NPo=
github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
@@ -81,138 +47,69 @@ github.com/blevesearch/zapx/v14 v14.3.10 h1:SG6xlsL+W6YjhX5N3aEiL/2tcWh3DO75Bnz7
github.com/blevesearch/zapx/v14 v14.3.10/go.mod h1:qqyuR0u230jN1yMmE4FIAuCxmahRQEOehF78m6oTgns=
github.com/blevesearch/zapx/v15 v15.3.13 h1:6EkfaZiPlAxqXz0neniq35my6S48QI94W/wyhnpDHHQ=
github.com/blevesearch/zapx/v15 v15.3.13/go.mod h1:Turk/TNRKj9es7ZpKK95PS7f6D44Y7fAFy8F4LXQtGg=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/blevesearch/zapx/v16 v16.0.12 h1:Uccxvjmn+hQ6ywQP+wIiTpdq9LnAviGoryJOmGwAo/I=
github.com/blevesearch/zapx/v16 v16.0.12/go.mod h1:MYnOshRfSm4C4drxx1LGRI+MVFByykJ2anDY1fxdk9Q=
github.com/chromedp/cdproto v0.0.0-20230220211738-2b1ec77315c9 h1:wMSvdj3BswqfQOXp2R1bJOAE7xIQLt2dlMQDMf836VY=
github.com/chromedp/cdproto v0.0.0-20230220211738-2b1ec77315c9/go.mod h1:GKljq0VrfU4D5yc+2qA6OVr8pmO/MBbPEWqWQ/oqGEs=
github.com/chromedp/chromedp v0.9.1 h1:CC7cC5p1BeLiiS2gfNNPwp3OaUxtRMBjfiw3E3k6dFA=
github.com/chromedp/chromedp v0.9.1/go.mod h1:DUgZWRvYoEfgi66CgZ/9Yv+psgi+Sksy5DTScENWjaQ=
github.com/chromedp/sysutil v1.0.0 h1:+ZxhTpfpZlmchB58ih/LBHX52ky7w2VhQVKQMucy3Ic=
github.com/chromedp/sysutil v1.0.0/go.mod h1:kgWmDdq8fTzXYcKIBqIYvRRTnYb9aNS9moAV0xufSww=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
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/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
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.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0=
github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI=
github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
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.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/glebarez/go-sqlite v1.22.0 h1:uAcMJhaA6r3LHMTFgP0SifzgXg46yJkgxqyuyec+ruQ=
github.com/glebarez/go-sqlite v1.22.0/go.mod h1:PlBIdHe0+aUEFn+r2/uthrWq4FxbzugL0L8Li6yQJbc=
github.com/glebarez/sqlite v1.10.0 h1:u4gt8y7OND/cCei/NMHmfbLxF6xP2wgKcT/BJf2pYkc=
github.com/glebarez/sqlite v1.10.0/go.mod h1:IJ+lfSOmiekhQsFTJRx/lHtGYmCdtAiTaf5wI9u5uHA=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/glebarez/sqlite v1.11.0 h1:wSG0irqzP6VurnMEpFGer5Li19RpIRi2qvQz++w0GMw=
github.com/glebarez/sqlite v1.11.0/go.mod h1:h8/o8j5wiAsqSPoWELDUdJXhjAhsVliSn7bWZjOhrgQ=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE=
github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8=
github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/gobwas/httphead v0.1.0 h1:exrUm0f4YX0L7EBwZHuCF4GDp8aJfVeBrlLQrs6NqWU=
github.com/gobwas/httphead v0.1.0/go.mod h1:O/RXo79gxV8G+RqlR/otEwx4Q36zl9rqC5u12GKvMCM=
github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
github.com/gobwas/ws v1.1.0 h1:7RFti/xnNkMJnrK7D1yQ/iCIB5OrrY/54/H930kIbHA=
github.com/gobwas/ws v1.1.0/go.mod h1:nzvNcVha5eUziGrbxFCo6qFIojQHjJV5cLYIbezhfL0=
github.com/goccy/go-json v0.9.6/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
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.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang/geo v0.0.0-20230421003525-6adc56603217 h1:HKlyj6in2JV6wVkmQ4XmG/EIm+SCYlPZ+V4GWit7Z+I=
github.com/golang/geo v0.0.0-20230421003525-6adc56603217/go.mod h1:8wI0hitZ3a1IxZfeH3/5I97CI8i5cLGsYe7xNhQGs9U=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
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.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
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.4.1/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.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/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.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
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/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200905233945-acf8798be1f7/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
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/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY=
github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ=
github.com/gorilla/pat v0.0.0-20180118222023-199c85a7f6d1/go.mod h1:YeAe0gNeiNT5hoiZRI4yiOky6jVdNvfO2N6Kav/HmxY=
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
github.com/gorilla/securecookie v1.1.2 h1:YCIWL56dvtr73r6715mJs5ZvhtnY73hBvEF8kXD8ePA=
github.com/gorilla/securecookie v1.1.2/go.mod h1:NfCASbcHqRSY+3a8tlWJwsQap2VX5pwzwo4h3eOamfo=
github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
github.com/gorilla/sessions v1.2.2 h1:lqzMYz6bOfvn2WriPUjNByzeXIlVzURcPmgMczkmTjY=
github.com/gorilla/sessions v1.2.2/go.mod h1:ePLdVu+jbEgHH+KWw8I1z2wqd0BAdAQh/8LRvBeoNcQ=
github.com/hashicorp/go-immutable-radix v1.3.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
@@ -223,14 +120,11 @@ github.com/hashicorp/go-memdb v1.3.4/go.mod h1:uBTr1oQbtuMgd1SSGoR8YV27eT3sBHbYi
github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jarcoal/httpmock v0.0.0-20180424175123-9c70cfe4a1da/go.mod h1:ks+b9deReOc7jgqp+e7LuFiCBH6Rm5hL32cLcEAArb4=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
@@ -239,31 +133,20 @@ github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8Hm
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/labstack/echo/v4 v4.11.4 h1:vDZmA+qNeh1pd/cCkEicDMrjtrnMGQ1QFI9gWN1zGq8=
github.com/labstack/echo/v4 v4.11.4/go.mod h1:noh7EvLwqDsmh/X/HWKPUl1AjzJrhyptRyEbQJfxen8=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
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/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ=
github.com/lestrrat-go/httpcc v1.0.0/go.mod h1:tGS/u00Vh5N6FHNkExqGGNId8e0Big+++0Gf8MBnAvE=
github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
github.com/lestrrat-go/jwx v1.2.21/go.mod h1:9cfxnOH7G1gN75CaJP2hKGcxFEx5sPh1abRIA/ZJVh4=
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/markbates/going v1.0.0/go.mod h1:I6mnB4BPnEeqo85ynXIx1ZFLLbtiLHNXVgWeFO9OGOA=
github.com/markbates/goth v1.78.0 h1:7VEIFDycJp9deyVv3YraGBPdD0ZYQW93Y3Aw1eVP3BY=
github.com/markbates/goth v1.78.0/go.mod h1:X6xdNgpapSENS0O35iTBBcMHoJDQDfI9bJl+APCkYMc=
github.com/markbates/goth v1.79.0 h1:fUYi9R6VubVEK2bpmXvIUp7xRcxA68i8ovfUQx/i5Qc=
github.com/markbates/goth v1.79.0/go.mod h1:RBD+tcFnXul2NnYuODhnIweOcuVPkBohLfEvutPekcU=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
@@ -277,367 +160,105 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mrjones/oauth v0.0.0-20180629183705-f4e24b6d100c/go.mod h1:skjdDftzkFALcuGzYSklqYd8gvat6F1gZJ4YPVbkZpM=
github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A=
github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
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/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/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/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.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho=
github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
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/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
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.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk=
github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.4.15/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.7.1 h1:3bajkSilaCbjdKVsKdZjZCLBNPL9pYzrCakKaf4U49U=
github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E=
github.com/yuin/goldmark-emoji v1.0.2 h1:c/RgTShNgHTtc6xdz2KKI74jJr6rWi7FPgnP9GAsO5s=
github.com/yuin/goldmark-emoji v1.0.2/go.mod h1:RhP/RWpexdp+KHs7ghKnifRoIs/Bq4nDS7tRbCkOwKY=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc h1:+IAOyRda+RLrxa1WC7umKOZRsGq4QrFFMYApOeHzQwQ=
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc/go.mod h1:ovIvrum6DQJA4QsJSovrkC4saKHQVs7TvcaeO8AIl5I=
go.abhg.dev/goldmark/mermaid v0.5.0 h1:mDkykpSPJ+5wCQ8bSXgzJ2KQskjXkI5Ndxz7JYDHW38=
go.abhg.dev/goldmark/mermaid v0.5.0/go.mod h1:OCyk2o85TX2drWHH+HRy6bih2yZlUwbbv/R1MMh1YLs=
go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/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-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-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
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-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
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-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200927032502-5d4f70055728/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/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-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/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-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/oauth2 v0.20.0 h1:4mQdhULixXKP1rwYBW0vAijoXnkTG0BLCDRzfe1idMo=
golang.org/x/oauth2 v0.20.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
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.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.19.0 h1:+ThwsDv+tYfnJFhF4L8jITxu1tdTWRTZpdsWgEgjL6Q=
golang.org/x/term v0.19.0/go.mod h1:2CuTdWZ7KHSQwUzKva0cbMg6q2DMI3Mmxp+gKJbskEk=
golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
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/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
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-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/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.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20200929161345-d7fc70abf50f/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/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-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.32.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
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.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.8 h1:IhEN5q69dyKagZPYMSdIjS2HqprW324FRQZJcGqPAsM=
google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJffLiz/Ds=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200929141702-51c3e5b607fe/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
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.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
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.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.32.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
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.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
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/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4=
google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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/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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
modernc.org/libc v1.38.0 h1:o4Lpk0zNDSdsjfEXnF1FGXWQ9PDi1NOdWcLP5n13FGo=
modernc.org/libc v1.38.0/go.mod h1:YAXkAZ8ktnkCKaN9sw/UDeUVkGYJ/YquGO4FTi5nmHE=
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
modernc.org/cc/v4 v4.21.0 h1:D/gLKtcztomvWbsbvBKo3leKQv+86f+DdqEZBBXhnag=
modernc.org/cc/v4 v4.21.0/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.17.3 h1:t2CQci84jnxKw3GGnHvjGKjiNZeZqyQx/023spkk4hU=
modernc.org/ccgo/v4 v4.17.3/go.mod h1:1FCbAtWYJoKuc+AviS+dH+vGNtYmFJqBeRWjmnDWsIg=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
modernc.org/libc v1.50.5 h1:ZzeUd0dIc/sUtoPTCYIrgypkuzoGzNu6kbEWj2VuEmk=
modernc.org/libc v1.50.5/go.mod h1:rhzrUx5oePTSTIzBgM0mTftwWHK8tiT9aNFUt1mldl0=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
modernc.org/sqlite v1.28.0 h1:Zx+LyDDmXczNnEQdvPuEfcFVA2ZPyaD7UCZDjef3BHQ=
modernc.org/sqlite v1.28.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/sqlite v1.29.8 h1:nGKglNx9K5v0As+zF0/Gcl1kMkmaU1XynYyq92PbsC8=
modernc.org/sqlite v1.29.8/go.mod h1:lQPm27iqa4UNZpmr4Aor0MH0HkCLbt1huYDfWylLZFk=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=

View File

@@ -20,7 +20,7 @@ var CmdVersion = cli.Command{
Name: "version",
Usage: "Print the version of Opengist",
Action: func(c *cli.Context) error {
fmt.Println("Opengist v" + config.OpengistVersion)
fmt.Println("Opengist " + config.OpengistVersion)
return nil
},
}
@@ -57,7 +57,7 @@ func App() error {
}
func Initialize(ctx *cli.Context) {
fmt.Println("Opengist v" + config.OpengistVersion)
fmt.Println("Opengist " + config.OpengistVersion)
if err := config.InitConfig(ctx.String("config"), os.Stdout); err != nil {
panic(err)

View File

@@ -17,7 +17,7 @@ import (
"gopkg.in/yaml.v3"
)
var OpengistVersion = "1.7.1"
var OpengistVersion = ""
var C *config

View File

@@ -24,6 +24,8 @@ var (
)
const truncateLimit = 2 << 18
const diffSize = 2 << 12
const maxFilesPerDiffCommit = 10
type RevisionNotFoundError struct{}
@@ -313,7 +315,7 @@ func GetLog(user string, gist string, skip int) ([]*Commit, error) {
}
}(cmd)
return parseLog(stdout, truncateLimit), err
return parseLog(stdout, maxFilesPerDiffCommit, diffSize)
}
func CloneTmp(user string, gist string, gistTmpId string, email string, remove bool) error {

View File

@@ -125,7 +125,7 @@ like Opengist actually`,
require.Contains(t, commits[0].Files, File{
Filename: "my_other_file.txt",
OldFilename: "",
OldFilename: "my_other_file.txt",
Content: `@@ -1,2 +1,2 @@
I really
-hate Opengist

View File

@@ -6,7 +6,6 @@ import (
"encoding/csv"
"fmt"
"io"
"regexp"
"strings"
)
@@ -63,129 +62,287 @@ func truncateCommandOutput(out io.Reader, maxBytes int64) (string, bool, error)
return string(buf), truncated, nil
}
func parseLog(out io.Reader, maxBytes int) []*Commit {
scanner := bufio.NewScanner(out)
// inspired from https://github.com/go-gitea/gitea/blob/main/services/gitdiff/gitdiff.go
func parseLog(out io.Reader, maxFiles int, maxBytes int) ([]*Commit, error) {
var commits []*Commit
var currentCommit *Commit
var currentFile *File
var isContent bool
var bytesRead = 0
scanNext := true
var headerParsed = false
var skipped = false
var line string
var err error
input := bufio.NewReaderSize(out, maxBytes)
// Loop Commits
loopLog:
for {
// If a commit was skipped, do not read a new line
if !skipped {
line, err = input.ReadString('\n')
if err != nil {
if err == io.EOF {
break loopLog
}
return commits, err
}
}
// Remove trailing newline characters
if len(line) > 0 && (line[len(line)-1] == '\n' || line[len(line)-1] == '\r') {
line = line[:len(line)-1]
}
// Attempt to parse commit header (hash, author, mail, timestamp) or a diff
switch line[0] {
// Commit hash
case 'c':
if headerParsed {
commits = append(commits, currentCommit)
}
skipped = false
currentCommit = &Commit{Hash: line[2:], Files: []File{}}
continue
// Author name
case 'a':
headerParsed = true
currentCommit.AuthorName = line[2:]
continue
// Author email
case 'm':
currentCommit.AuthorEmail = line[2:]
continue
// Commit timestamp
case 't':
currentCommit.Timestamp = line[2:]
continue
// Commit shortstat
case ' ':
changed := []byte(line)[1:]
changed = bytes.ReplaceAll(changed, []byte("(+)"), []byte(""))
changed = bytes.ReplaceAll(changed, []byte("(-)"), []byte(""))
currentCommit.Changed = string(changed)
// shortstat is followed by an empty line
line, err = input.ReadString('\n')
if err != nil {
if err == io.EOF {
break loopLog
}
return commits, err
}
continue
// Commit diff
default:
// Loop files in diff
loopCommit:
for {
// If we have reached the maximum number of files to show for a single commit, skip to the next commit
if len(currentCommit.Files) >= maxFiles {
line, err = skipToNextCommit(input)
if err != nil {
if err == io.EOF {
break loopLog
}
return commits, err
}
// Skip to the next commit
headerParsed = false
skipped = true
break loopCommit
}
// Else create a new file and parse it
currentFile = &File{}
parseRename := true
loopFileDiff:
for {
line, err = input.ReadString('\n')
if err != nil {
if err != io.EOF {
return commits, err
}
headerParsed = false
break loopCommit
}
// If the line is a newline character, the commit is finished
if line == "\n" {
currentCommit.Files = append(currentCommit.Files, *currentFile)
headerParsed = false
break loopCommit
}
// Attempt to parse the file header
switch {
case strings.HasPrefix(line, "diff --git"):
currentCommit.Files = append(currentCommit.Files, *currentFile)
headerParsed = false
break loopFileDiff
case strings.HasPrefix(line, "old mode"):
case strings.HasPrefix(line, "new mode"):
case strings.HasPrefix(line, "index"):
case strings.HasPrefix(line, "similarity index"):
case strings.HasPrefix(line, "dissimilarity index"):
continue
case strings.HasPrefix(line, "rename from "):
currentFile.OldFilename = line[12 : len(line)-1]
case strings.HasPrefix(line, "rename to "):
currentFile.Filename = line[10 : len(line)-1]
parseRename = false
case strings.HasPrefix(line, "copy from "):
currentFile.OldFilename = line[10 : len(line)-1]
case strings.HasPrefix(line, "copy to "):
currentFile.Filename = line[8 : len(line)-1]
parseRename = false
case strings.HasPrefix(line, "new file"):
currentFile.IsCreated = true
case strings.HasPrefix(line, "deleted file"):
currentFile.IsDeleted = true
case strings.HasPrefix(line, "--- "):
name := line[4 : len(line)-1]
if parseRename && currentFile.IsDeleted {
currentFile.Filename = name[2:]
} else if parseRename && strings.HasPrefix(name, "a/") {
currentFile.OldFilename = name[2:]
}
case strings.HasPrefix(line, "+++ "):
name := line[4 : len(line)-1]
if parseRename && strings.HasPrefix(name, "b/") {
currentFile.Filename = name[2:]
}
// Header is finally parsed, now we can parse the file diff content
lineBytes, isFragment, err := parseDiffContent(currentFile, maxBytes, input)
if err != nil {
if err != io.EOF {
return commits, err
}
// EOF reached, commit is finished
currentCommit.Files = append(currentCommit.Files, *currentFile)
headerParsed = false
break loopCommit
}
currentCommit.Files = append(currentCommit.Files, *currentFile)
if string(lineBytes) == "" {
headerParsed = false
break loopCommit
}
for isFragment {
_, isFragment, err = input.ReadLine()
if err != nil {
return commits, fmt.Errorf("unable to ReadLine: %w", err)
}
}
break loopFileDiff
}
}
}
}
commits = append(commits, currentCommit)
}
return commits, nil
}
func parseDiffContent(currentFile *File, maxBytes int, input *bufio.Reader) (lineBytes []byte, isFragment bool, err error) {
sb := &strings.Builder{}
var currFileLineCount int
for {
if scanNext && !scanner.Scan() {
break
}
scanNext = true
for isFragment {
currentFile.Truncated = true
// new commit found
currentFile = nil
currentCommit = &Commit{Hash: string(scanner.Bytes()[2:]), Files: []File{}}
scanner.Scan()
currentCommit.AuthorName = string(scanner.Bytes()[2:])
scanner.Scan()
currentCommit.AuthorEmail = string(scanner.Bytes()[2:])
scanner.Scan()
currentCommit.Timestamp = string(scanner.Bytes()[2:])
scanner.Scan()
if len(scanner.Bytes()) == 0 {
commits = append(commits, currentCommit)
break
// Read the next line
_, isFragment, err = input.ReadLine()
if err != nil {
return nil, false, err
}
}
// if there is no shortstat, it means that the commit is empty, we add it and move onto the next one
if scanner.Bytes()[0] != ' ' {
commits = append(commits, currentCommit)
sb.Reset()
// avoid scanning the next line, as we already did it
scanNext = false
// Read the next line
lineBytes, isFragment, err = input.ReadLine()
if err != nil {
if err == io.EOF {
return lineBytes, isFragment, err
}
return nil, false, err
}
// End of file
if len(lineBytes) == 0 {
return lineBytes, false, err
}
if lineBytes[0] == 'd' {
return lineBytes, false, err
}
if currFileLineCount >= maxBytes {
currentFile.Truncated = true
continue
}
changed := scanner.Bytes()[1:]
changed = bytes.ReplaceAll(changed, []byte("(+)"), []byte(""))
changed = bytes.ReplaceAll(changed, []byte("(-)"), []byte(""))
currentCommit.Changed = string(changed)
// twice because --shortstat adds a new line
scanner.Scan()
scanner.Scan()
// commit header parsed
// files changes inside the commit
for {
line := scanner.Bytes()
// end of content of file
if len(line) == 0 {
isContent = false
if currentFile != nil {
currentCommit.Files = append(currentCommit.Files, *currentFile)
}
break
}
// new file found
if bytes.HasPrefix(line, []byte("diff --git")) {
// current file is finished, we can add it to the commit
if currentFile != nil {
currentCommit.Files = append(currentCommit.Files, *currentFile)
}
// create a new file
isContent = false
bytesRead = 0
currentFile = &File{}
filenameRegex := regexp.MustCompile(`^diff --git a/(.+) b/(.+)$`)
matches := filenameRegex.FindStringSubmatch(string(line))
if len(matches) == 3 {
currentFile.Filename = matches[2]
if matches[1] != matches[2] {
currentFile.OldFilename = matches[1]
}
}
scanner.Scan()
continue
}
if bytes.HasPrefix(line, []byte("new")) {
currentFile.IsCreated = true
}
if bytes.HasPrefix(line, []byte("deleted")) {
currentFile.IsDeleted = true
}
// file content found
if line[0] == '@' {
isContent = true
}
if isContent {
currentFile.Content += string(line) + "\n"
bytesRead += len(line)
if bytesRead > maxBytes {
currentFile.Truncated = true
currentFile.Content = ""
isContent = false
line := string(lineBytes)
if isFragment {
currentFile.Truncated = true
for isFragment {
lineBytes, isFragment, err = input.ReadLine()
if err != nil {
return lineBytes, isFragment, fmt.Errorf("unable to ReadLine: %w", err)
}
}
scanner.Scan()
}
commits = append(commits, currentCommit)
if len(line) > maxBytes {
currentFile.Truncated = true
line = line[:maxBytes]
}
currentFile.Content += line + "\n"
}
}
return commits
func skipToNextCommit(input *bufio.Reader) (line string, err error) {
// need to skip until the next cmdDiffHead
var isFragment, wasFragment bool
var lineBytes []byte
for {
lineBytes, isFragment, err = input.ReadLine()
if err != nil {
return "", err
}
if wasFragment {
wasFragment = isFragment
continue
}
if bytes.HasPrefix(lineBytes, []byte("c")) {
break
}
wasFragment = isFragment
}
line = string(lineBytes)
if isFragment {
var tail string
tail, err = input.ReadString('\n')
if err != nil {
return "", err
}
line += tail
}
return line, err
}
func ParseCsv(file *File) (*CsvFile, error) {

View File

@@ -112,6 +112,20 @@ func (store *LocaleStore) MatchTag(langs []language.Tag) string {
return "en-US"
}
func (l *Locale) String(key string, args ...any) string {
message := l.Messages[key]
if message == "" {
return Locales.Locales["en-US"].String(key, args...)
}
if len(args) == 0 {
return message
}
return fmt.Sprintf(message, args...)
}
func (l *Locale) Tr(key string, args ...any) template.HTML {
message := l.Messages[key]

View File

@@ -17,8 +17,8 @@ gist.header.clone-http: Klonovat pomocí %s
gist.header.clone-http-help: Klonovat s pomocí Git pomocí základní autentizace HTTP.
gist.header.clone-ssh: Klonovat pomocí SSH
gist.header.clone-ssh-help: Klonovat s pomocí Git pomocí klíče SSH.
gist.header.embed:
gist.header.embed-help:
gist.header.embed: ''
gist.header.embed-help: ''
gist.header.download-zip: Stáhnout ZIP
gist.raw: Raw
@@ -181,3 +181,80 @@ admin.gists.private: Soukromé?
admin.gists.nb-files: Počet souborů
admin.gists.nb-likes: Počet lajků
admin.gists.delete_confirm: Opravdu chcete smazat tento gist?
gist.forks.for: ''
gist.likes.for: ''
gist.revision-of: ''
error.page-not-found: ''
error.bad-request: ''
error.signup-disabled: ''
error.signup-disabled-form: ''
error.login-disabled-form: ''
error.complete-oauth-login: ''
error.oauth-unsupported: ''
error.cannot-bind-data: ''
error.invalid-number: ''
error.invalid-character-unescaped: ''
admin.actions.reset-hooks: ''
admin.invitations.expired: ''
flash.admin.user-deleted: ''
flash.admin.gist-deleted: ''
flash.admin.invitation-created: ''
flash.admin.invitation-deleted: ''
flash.admin.sync-fs: ''
flash.admin.sync-db: ''
flash.admin.git-gc: ''
flash.admin.sync-previews: ''
gist.new.create-a-new-gist: ''
gist.edit.edit-gist: ''
flash.admin.reset-hooks: ''
flash.admin.index-gists: ''
flash.auth.username-exists: ''
flash.auth.invalid-credentials: ''
flash.auth.account-linked-oauth: ''
flash.auth.account-unlinked-oauth: ''
flash.auth.user-sshkeys-not-retrievable: ''
flash.auth.user-sshkeys-not-created: ''
flash.auth.must-be-logged-in: ''
flash.gist.visibility-changed: ''
flash.gist.fork-own-gist: ''
flash.gist.forked: ''
flash.user.email-updated: ''
flash.user.invalid-ssh-key: ''
flash.user.ssh-key-added: ''
flash.user.ssh-key-deleted: ''
flash.user.password-updated: ''
flash.user.username-updated: ''
validation.is-too-long: ''
validation.should-not-be-empty: ''
validation.should-not-include-sub-directory: ''
validation.should-only-contain-alphanumeric-characters: ''
gist.list.all-liked-by: ''
gist.list.all-forked-by: ''
gist.list.all-from: ''
validation.should-only-contain-alphanumeric-characters-and-dashes: ''
validation.not-enough: ''
validation.invalid: ''
html.title.admin-panel: ''
flash.gist.deleted: ''
gist.new.url: ''
gist.search.found: ''
gist.search.no-results: ''
gist.search.help.user: ''
gist.search.help.title: ''
gist.search.help.filename: ''
gist.search.help.extension: ''
gist.search.help.language: ''
settings.change-username: ''
admin.invitations: ''
admin.invitations.create: ''
admin.actions.sync-previews: ''
admin.actions.index-gists: ''
admin.invitations.code: ''
admin.invitations.copy_link: ''
admin.invitations.uses: ''
gist.new.preview: ''
settings.link-gitlab-account: ''
settings.unlink-gitlab-account: ''
admin.invitations.help: ''
admin.invitations.max_uses: ''
admin.invitations.expires_at: ''

View File

@@ -196,3 +196,67 @@ admin.gists.private: 'privat?'
admin.gists.nb-files: 'Anz. Dateien'
admin.gists.nb-likes: 'Anz. Favoriten'
admin.gists.delete_confirm: 'Willst du diese Gist löschen?'
auth.oauth: ''
gist.new.preview: ''
gist.new.create-a-new-gist: ''
gist.edit.edit-gist: ''
gist.list.all-liked-by: ''
gist.list.all-forked-by: ''
gist.list.all-from: ''
gist.forks.for: ''
gist.likes.for: ''
gist.revision-of: ''
error.page-not-found: ''
error.bad-request: ''
error.signup-disabled: ''
error.signup-disabled-form: ''
error.login-disabled-form: ''
error.complete-oauth-login: ''
error.oauth-unsupported: ''
error.cannot-bind-data: ''
error.invalid-number: ''
error.invalid-character-unescaped: ''
admin.invitations: ''
admin.invitations.create: ''
admin.invitations.help: ''
admin.invitations.max_uses: ''
admin.invitations.expires_at: ''
admin.invitations.code: ''
admin.invitations.copy_link: ''
admin.invitations.uses: ''
admin.invitations.expired: ''
flash.admin.user-deleted: ''
flash.admin.gist-deleted: ''
flash.admin.invitation-created: ''
flash.admin.invitation-deleted: ''
flash.admin.sync-fs: ''
flash.admin.sync-db: ''
flash.admin.git-gc: ''
flash.admin.sync-previews: ''
flash.admin.reset-hooks: ''
flash.admin.index-gists: ''
flash.auth.username-exists: ''
flash.auth.invalid-credentials: ''
flash.auth.account-linked-oauth: ''
flash.auth.account-unlinked-oauth: ''
flash.auth.user-sshkeys-not-retrievable: ''
flash.auth.user-sshkeys-not-created: ''
flash.auth.must-be-logged-in: ''
flash.gist.visibility-changed: ''
flash.gist.deleted: ''
flash.gist.fork-own-gist: ''
flash.gist.forked: ''
flash.user.email-updated: ''
flash.user.invalid-ssh-key: ''
flash.user.ssh-key-added: ''
flash.user.ssh-key-deleted: ''
flash.user.password-updated: ''
flash.user.username-updated: ''
validation.is-too-long: ''
validation.should-not-be-empty: ''
validation.should-not-include-sub-directory: ''
validation.should-only-contain-alphanumeric-characters: ''
validation.should-only-contain-alphanumeric-characters-and-dashes: ''
validation.not-enough: ''
validation.invalid: ''
html.title.admin-panel: ''

View File

@@ -44,8 +44,10 @@ gist.new.create-public-button: Create public gist
gist.new.create-unlisted-button: Create unlisted gist
gist.new.create-private-button: Create private gist
gist.new.preview: Preview
gist.new.create-a-new-gist: Create a new gist
gist.edit.editing: Editing
gist.edit.edit-gist: Edit %s
gist.edit.change-visibility: Make
gist.edit.delete: Delete
gist.edit.cancel: Cancel
@@ -68,6 +70,9 @@ gist.list.forks: forks
gist.list.files: files
gist.list.last-active: Last active
gist.list.no-gists: No gists
gist.list.all-liked-by: All gists liked by %s
gist.list.all-forked-by: All gists forked by %s
gist.list.all-from: All gists from %s
gist.search.found: gists found
gist.search.no-results: No gists found
@@ -80,9 +85,11 @@ gist.search.help.language: gists having files with given language
gist.forks: Forks
gist.forks.view: View fork
gist.forks.no: No public forks
gist.forks.for: Forks for %s
gist.likes: Likes
gist.likes.no: No likes yet
gist.likes.for: Likes for %s
gist.revisions: Revisions
gist.revision.revised: revised this gist
@@ -95,6 +102,7 @@ gist.revision.file-renamed-no-changes: File renamed without changes
gist.revision.empty-file: Empty file
gist.revision.no-changes: No changes
gist.revision.no-revisions: No revisions to show
gist.revision-of: Revision of %s
settings: Settings
settings.email: Email
@@ -136,6 +144,16 @@ auth.login-instead: Login instead
auth.oauth: Continue with %s account
error: Error
error.page-not-found: Page not found
error.bad-request: Bad request
error.signup-disabled: Signing up is disabled
error.signup-disabled-form: Signing up via registration form is disabled
error.login-disabled-form: Logging in via login form is disabled
error.complete-oauth-login: "Cannot complete user auth: %s"
error.oauth-unsupported: Unsupported provider
error.cannot-bind-data: Cannot bind data
error.invalid-number: Invalid number
error.invalid-character-unescaped: Invalid character unescaped
header.menu.all: All
header.menu.new: New
@@ -204,4 +222,45 @@ admin.invitations.expires_at: Expires at
admin.invitations.code: Code
admin.invitations.copy_link: Copy link
admin.invitations.uses: Uses
admin.invitations.expired: Expired
admin.invitations.expired: Expired
flash.admin.user-deleted: User has been deleted
flash.admin.gist-deleted: Gist has been deleted
flash.admin.invitation-created: Invitation has been created
flash.admin.invitation-deleted: Invitation has been deleted
flash.admin.sync-fs: Syncing repositories from filesystem...
flash.admin.sync-db: Syncing repositories from database...
flash.admin.git-gc: Garbage collecting repositories...
flash.admin.sync-previews: Syncing Gist previews...
flash.admin.reset-hooks: Resetting Git server hooks for all repositories...
flash.admin.index-gists: Indexing all gists...
flash.auth.username-exists: Username already exists
flash.auth.invalid-credentials: Invalid credentials
flash.auth.account-linked-oauth: Account linked to %s
flash.auth.account-unlinked-oauth: Account unlinked from %s
flash.auth.user-sshkeys-not-retrievable: Could not get user keys
flash.auth.user-sshkeys-not-created: Could not create ssh key
flash.auth.must-be-logged-in: You must be logged in to access gists
flash.gist.visibility-changed: Gist visibility has been changed
flash.gist.deleted: Gist has been deleted
flash.gist.fork-own-gist: Unable to fork own gists
flash.gist.forked: Gist has been forked
flash.user.email-updated: Email updated
flash.user.invalid-ssh-key: Invalid SSH key
flash.user.ssh-key-added: SSH key added
flash.user.ssh-key-deleted: SSH key deleted
flash.user.password-updated: Password updated
flash.user.username-updated: Username updated
validation.is-too-long: Field %s is too long
validation.should-not-be-empty: Field %s should not be empty
validation.should-not-include-sub-directory: Field %s should not include a sub directory
validation.should-only-contain-alphanumeric-characters: Field %s should only contain alphanumeric characters
validation.should-only-contain-alphanumeric-characters-and-dashes: Field %s should only contain alphanumeric characters and dashes
validation.not-enough: Not enough %s
validation.invalid: Invalid %s
html.title.admin-panel: Admin panel

View File

@@ -17,8 +17,8 @@ gist.header.clone-http: Clonar via %s
gist.header.clone-http-help: Clonar con Git usando autenticación básica HTTP.
gist.header.clone-ssh: Clonar via SSH
gist.header.clone-ssh-help: Clonar con Git usando una clave SSH.
gist.header.embed:
gist.header.embed-help:
gist.header.embed: ''
gist.header.embed-help: ''
gist.header.download-zip: Descargar ZIP
gist.raw: Sin formato
@@ -174,3 +174,86 @@ admin.gists.private: ¿Privado?
admin.gists.nb-files: Núm. de archivos
admin.gists.nb-likes: Núm. de gustos
admin.gists.delete_confirm: ¿Quieres eliminar este gist?
gist.new.url: ''
gist.new.preview: ''
gist.new.create-a-new-gist: ''
gist.edit.edit-gist: ''
gist.list.all-liked-by: ''
gist.list.all-forked-by: ''
gist.list.all-from: ''
gist.search.found: ''
gist.search.no-results: ''
gist.search.help.user: ''
gist.search.help.title: ''
gist.search.help.filename: ''
gist.search.help.extension: ''
gist.search.help.language: ''
gist.forks.for: ''
gist.likes.for: ''
gist.revision-of: ''
settings.link-gitlab-account: ''
settings.unlink-gitlab-account: ''
settings.change-username: ''
settings.create-password: ''
settings.create-password-help: ''
settings.change-password: ''
settings.change-password-help: ''
settings.password-label-title: ''
error.page-not-found: ''
error.bad-request: ''
error.signup-disabled: ''
error.signup-disabled-form: ''
error.login-disabled-form: ''
error.complete-oauth-login: ''
error.oauth-unsupported: ''
error.cannot-bind-data: ''
error.invalid-number: ''
error.invalid-character-unescaped: ''
admin.invitations: ''
admin.invitations.create: ''
admin.actions.sync-previews: ''
admin.actions.reset-hooks: ''
admin.actions.index-gists: ''
admin.config-link-overriden: ''
admin.invitations.help: ''
admin.invitations.max_uses: ''
admin.invitations.expires_at: ''
admin.invitations.code: ''
admin.invitations.copy_link: ''
admin.invitations.uses: ''
admin.invitations.expired: ''
flash.admin.user-deleted: ''
flash.admin.gist-deleted: ''
flash.admin.invitation-created: ''
flash.admin.invitation-deleted: ''
flash.admin.sync-fs: ''
flash.admin.sync-db: ''
flash.admin.git-gc: ''
flash.admin.sync-previews: ''
flash.admin.reset-hooks: ''
flash.admin.index-gists: ''
flash.auth.username-exists: ''
flash.auth.invalid-credentials: ''
flash.auth.account-linked-oauth: ''
flash.auth.account-unlinked-oauth: ''
flash.auth.user-sshkeys-not-retrievable: ''
flash.auth.user-sshkeys-not-created: ''
flash.auth.must-be-logged-in: ''
flash.gist.visibility-changed: ''
flash.gist.deleted: ''
flash.gist.fork-own-gist: ''
flash.gist.forked: ''
flash.user.email-updated: ''
flash.user.invalid-ssh-key: ''
flash.user.ssh-key-added: ''
flash.user.ssh-key-deleted: ''
flash.user.password-updated: ''
flash.user.username-updated: ''
validation.is-too-long: ''
validation.should-not-be-empty: ''
validation.should-not-include-sub-directory: ''
validation.should-only-contain-alphanumeric-characters: ''
validation.should-only-contain-alphanumeric-characters-and-dashes: ''
validation.not-enough: ''
validation.invalid: ''
html.title.admin-panel: ''

View File

@@ -194,3 +194,66 @@ gist.new.url: URL
gist.search.no-results: Aucun gist trouvé
settings.unlink-gitlab-account: Détacher le compte GitLab
admin.actions.index-gists: Indexer tous les gists
gist.new.preview: ''
gist.new.create-a-new-gist: ''
gist.edit.edit-gist: ''
gist.list.all-liked-by: ''
gist.list.all-forked-by: ''
gist.list.all-from: ''
gist.forks.for: ''
gist.likes.for: ''
gist.revision-of: ''
error.page-not-found: ''
error.bad-request: ''
error.signup-disabled: ''
error.signup-disabled-form: ''
error.login-disabled-form: ''
error.complete-oauth-login: ''
error.oauth-unsupported: ''
error.cannot-bind-data: ''
error.invalid-number: ''
error.invalid-character-unescaped: ''
admin.invitations: ''
admin.invitations.create: ''
admin.invitations.help: ''
admin.invitations.max_uses: ''
admin.invitations.expires_at: ''
admin.invitations.code: ''
admin.invitations.copy_link: ''
admin.invitations.uses: ''
admin.invitations.expired: ''
flash.admin.user-deleted: ''
flash.admin.gist-deleted: ''
flash.admin.invitation-created: ''
flash.admin.invitation-deleted: ''
flash.admin.sync-fs: ''
flash.admin.sync-db: ''
flash.admin.git-gc: ''
flash.admin.sync-previews: ''
flash.admin.reset-hooks: ''
flash.admin.index-gists: ''
flash.auth.username-exists: ''
flash.auth.invalid-credentials: ''
flash.auth.account-linked-oauth: ''
flash.auth.account-unlinked-oauth: ''
flash.auth.user-sshkeys-not-retrievable: ''
flash.auth.user-sshkeys-not-created: ''
flash.auth.must-be-logged-in: ''
flash.gist.visibility-changed: ''
flash.gist.deleted: ''
flash.gist.fork-own-gist: ''
flash.gist.forked: ''
flash.user.email-updated: ''
flash.user.invalid-ssh-key: ''
flash.user.ssh-key-added: ''
flash.user.ssh-key-deleted: ''
flash.user.password-updated: ''
flash.user.username-updated: ''
validation.is-too-long: ''
validation.should-not-be-empty: ''
validation.should-not-include-sub-directory: ''
validation.should-only-contain-alphanumeric-characters: ''
validation.should-only-contain-alphanumeric-characters-and-dashes: ''
validation.not-enough: ''
validation.invalid: ''
html.title.admin-panel: ''

View File

@@ -17,8 +17,8 @@ gist.header.clone-http: "Clone-ozás ezzel: %s"
gist.header.clone-http-help: Clone-ozás Git HTTP basic hitelesítéssel.
gist.header.clone-ssh: Clone-ozás SSH-n keresztül
gist.header.clone-ssh-help: Clone-ozás SSH kulccsal
gist.header.embed:
gist.header.embed-help:
gist.header.embed: ''
gist.header.embed-help: ''
gist.header.download-zip: ZIP archívum letöltése
gist.raw: Eredeti
@@ -194,3 +194,66 @@ admin.gists.private: Privát ?
admin.gists.nb-files: Fájlok száma
admin.gists.nb-likes: Kedv. száma
admin.gists.delete_confirm: Biztosan törlöd a gistet?
gist.new.preview: ''
gist.new.create-a-new-gist: ''
gist.edit.edit-gist: ''
gist.list.all-liked-by: ''
gist.list.all-forked-by: ''
gist.list.all-from: ''
gist.forks.for: ''
gist.likes.for: ''
gist.revision-of: ''
error.page-not-found: ''
error.bad-request: ''
error.signup-disabled: ''
error.signup-disabled-form: ''
error.login-disabled-form: ''
error.complete-oauth-login: ''
error.oauth-unsupported: ''
error.cannot-bind-data: ''
error.invalid-number: ''
error.invalid-character-unescaped: ''
admin.invitations: ''
admin.invitations.create: ''
admin.invitations.help: ''
admin.invitations.max_uses: ''
admin.invitations.expires_at: ''
admin.invitations.code: ''
admin.invitations.copy_link: ''
admin.invitations.uses: ''
admin.invitations.expired: ''
flash.admin.user-deleted: ''
flash.admin.gist-deleted: ''
flash.admin.invitation-created: ''
flash.admin.invitation-deleted: ''
flash.admin.sync-fs: ''
flash.admin.sync-db: ''
flash.admin.git-gc: ''
flash.admin.sync-previews: ''
flash.admin.reset-hooks: ''
flash.admin.index-gists: ''
flash.auth.username-exists: ''
flash.auth.invalid-credentials: ''
flash.auth.account-linked-oauth: ''
flash.auth.account-unlinked-oauth: ''
flash.auth.user-sshkeys-not-retrievable: ''
flash.auth.user-sshkeys-not-created: ''
flash.auth.must-be-logged-in: ''
flash.gist.visibility-changed: ''
flash.gist.deleted: ''
flash.gist.fork-own-gist: ''
flash.gist.forked: ''
flash.user.email-updated: ''
flash.user.invalid-ssh-key: ''
flash.user.ssh-key-added: ''
flash.user.ssh-key-deleted: ''
flash.user.password-updated: ''
flash.user.username-updated: ''
validation.is-too-long: ''
validation.should-not-be-empty: ''
validation.should-not-include-sub-directory: ''
validation.should-only-contain-alphanumeric-characters: ''
validation.should-only-contain-alphanumeric-characters-and-dashes: ''
validation.not-enough: ''
validation.invalid: ''
html.title.admin-panel: ''

View File

@@ -174,3 +174,88 @@ admin.gists.private: Privado
admin.gists.nb-files: Núm. de arquivos
admin.gists.nb-likes: Núm. de curtidas
admin.gists.delete_confirm: Quer excluir este gist?
flash.admin.index-gists: ''
gist.header.embed: ''
gist.header.embed-help: ''
gist.new.url: ''
gist.list.all-liked-by: ''
gist.new.preview: ''
gist.new.create-a-new-gist: ''
gist.edit.edit-gist: ''
gist.list.all-forked-by: ''
gist.list.all-from: ''
gist.search.found: ''
gist.search.no-results: ''
gist.search.help.user: ''
gist.search.help.title: ''
gist.search.help.filename: ''
gist.search.help.extension: ''
gist.search.help.language: ''
gist.forks.for: ''
gist.likes.for: ''
gist.revision-of: ''
settings.link-gitlab-account: ''
settings.unlink-gitlab-account: ''
settings.change-username: ''
settings.create-password: ''
settings.create-password-help: ''
settings.change-password: ''
settings.change-password-help: ''
settings.password-label-title: ''
error.page-not-found: ''
error.bad-request: ''
error.signup-disabled: ''
error.signup-disabled-form: ''
error.login-disabled-form: ''
error.complete-oauth-login: ''
error.oauth-unsupported: ''
error.cannot-bind-data: ''
error.invalid-number: ''
error.invalid-character-unescaped: ''
admin.invitations: ''
admin.invitations.create: ''
admin.actions.sync-previews: ''
admin.actions.reset-hooks: ''
admin.actions.index-gists: ''
admin.config-link-overriden: ''
validation.invalid: ''
admin.invitations.help: ''
admin.invitations.max_uses: ''
admin.invitations.expires_at: ''
admin.invitations.code: ''
admin.invitations.copy_link: ''
admin.invitations.uses: ''
admin.invitations.expired: ''
flash.admin.user-deleted: ''
flash.admin.gist-deleted: ''
flash.admin.invitation-created: ''
flash.admin.invitation-deleted: ''
flash.admin.sync-fs: ''
flash.admin.sync-db: ''
flash.admin.git-gc: ''
flash.admin.sync-previews: ''
flash.admin.reset-hooks: ''
flash.auth.username-exists: ''
flash.auth.invalid-credentials: ''
flash.auth.account-linked-oauth: ''
flash.auth.account-unlinked-oauth: ''
flash.auth.user-sshkeys-not-retrievable: ''
flash.auth.user-sshkeys-not-created: ''
flash.auth.must-be-logged-in: ''
flash.gist.visibility-changed: ''
flash.gist.deleted: ''
flash.gist.fork-own-gist: ''
flash.gist.forked: ''
flash.user.email-updated: ''
flash.user.invalid-ssh-key: ''
flash.user.ssh-key-added: ''
flash.user.ssh-key-deleted: ''
flash.user.password-updated: ''
flash.user.username-updated: ''
validation.is-too-long: ''
validation.should-not-be-empty: ''
validation.should-not-include-sub-directory: ''
validation.should-only-contain-alphanumeric-characters: ''
validation.should-only-contain-alphanumeric-characters-and-dashes: ''
validation.not-enough: ''
html.title.admin-panel: ''

View File

@@ -17,8 +17,8 @@ gist.header.clone-http: Клонировать с помощью %s
gist.header.clone-http-help: Клонировать с помощью Git используя аутентификацию HTTP.
gist.header.clone-ssh: Клонировать c помощью SSH
gist.header.clone-ssh-help: Клонировать c помощью Git используя ключ SSH.
gist.header.embed:
gist.header.embed-help:
gist.header.embed: ''
gist.header.embed-help: ''
gist.header.download-zip: Скачать ZIP-архив
gist.raw: Исходник
@@ -174,3 +174,85 @@ admin.gists.private: Приватный
admin.gists.nb-files: Файлов
admin.gists.nb-likes: Понравилось
admin.gists.delete_confirm: Вы уверены что хотите удалить этот фрагмент?
gist.new.url: ''
gist.new.preview: ''
gist.new.create-a-new-gist: ''
gist.edit.edit-gist: ''
gist.list.all-liked-by: ''
gist.list.all-forked-by: ''
gist.list.all-from: ''
gist.search.found: ''
gist.search.no-results: ''
gist.search.help.user: ''
gist.search.help.title: ''
gist.search.help.filename: ''
gist.search.help.extension: ''
gist.search.help.language: ''
gist.forks.for: ''
gist.likes.for: ''
gist.revision-of: ''
settings.link-gitlab-account: ''
settings.unlink-gitlab-account: ''
settings.change-username: ''
settings.create-password: ''
settings.create-password-help: ''
settings.change-password: ''
settings.change-password-help: ''
settings.password-label-title: ''
error.page-not-found: ''
error.bad-request: ''
error.signup-disabled: ''
error.signup-disabled-form: ''
error.login-disabled-form: ''
error.complete-oauth-login: ''
error.oauth-unsupported: ''
error.cannot-bind-data: ''
error.invalid-number: ''
error.invalid-character-unescaped: ''
admin.invitations: ''
admin.invitations.create: ''
admin.actions.sync-previews: ''
admin.actions.reset-hooks: ''
admin.actions.index-gists: ''
validation.should-not-be-empty: ''
admin.invitations.help: ''
admin.invitations.max_uses: ''
admin.invitations.expires_at: ''
admin.invitations.code: ''
admin.invitations.copy_link: ''
admin.invitations.uses: ''
admin.invitations.expired: ''
flash.admin.user-deleted: ''
flash.admin.gist-deleted: ''
flash.admin.invitation-created: ''
flash.admin.invitation-deleted: ''
flash.admin.sync-fs: ''
flash.admin.sync-db: ''
flash.admin.git-gc: ''
flash.admin.sync-previews: ''
flash.admin.reset-hooks: ''
flash.admin.index-gists: ''
flash.auth.username-exists: ''
flash.auth.invalid-credentials: ''
flash.auth.account-linked-oauth: ''
flash.auth.account-unlinked-oauth: ''
flash.auth.user-sshkeys-not-retrievable: ''
flash.auth.user-sshkeys-not-created: ''
flash.auth.must-be-logged-in: ''
flash.gist.visibility-changed: ''
flash.gist.deleted: ''
flash.gist.fork-own-gist: ''
flash.gist.forked: ''
flash.user.email-updated: ''
flash.user.invalid-ssh-key: ''
flash.user.ssh-key-added: ''
flash.user.ssh-key-deleted: ''
flash.user.password-updated: ''
flash.user.username-updated: ''
validation.is-too-long: ''
validation.should-not-include-sub-directory: ''
validation.should-only-contain-alphanumeric-characters: ''
validation.should-only-contain-alphanumeric-characters-and-dashes: ''
validation.not-enough: ''
validation.invalid: ''
html.title.admin-panel: ''

View File

@@ -17,8 +17,8 @@ gist.header.clone-http: 通过 %s 克隆
gist.header.clone-http-help: 使用 Git 通过 HTTP 基础认证克隆。
gist.header.clone-ssh: 通过 SSH 克隆
gist.header.clone-ssh-help: 使用 Git 通过 SSH 密钥克隆。
gist.header.embed:
gist.header.embed-help:
gist.header.embed: ''
gist.header.embed-help: ''
gist.header.download-zip: 下载 ZIP
gist.raw: 原始文件
@@ -174,3 +174,85 @@ admin.gists.private: 私有?
admin.gists.nb-files: 文件数
admin.gists.nb-likes: 喜欢数
admin.gists.delete_confirm: 你想要删除此 Gist 吗?
gist.new.url: ''
gist.new.preview: ''
error.page-not-found: ''
gist.new.create-a-new-gist: ''
gist.edit.edit-gist: ''
gist.list.all-liked-by: ''
gist.list.all-forked-by: ''
gist.list.all-from: ''
gist.search.found: ''
gist.search.no-results: ''
gist.search.help.user: ''
gist.search.help.title: ''
gist.search.help.filename: ''
gist.search.help.extension: ''
gist.search.help.language: ''
gist.forks.for: ''
gist.likes.for: ''
gist.revision-of: ''
settings.link-gitlab-account: ''
settings.unlink-gitlab-account: ''
settings.change-username: ''
settings.create-password: ''
settings.create-password-help: ''
settings.change-password: ''
settings.change-password-help: ''
settings.password-label-title: ''
error.bad-request: ''
error.signup-disabled: ''
error.signup-disabled-form: ''
error.login-disabled-form: ''
error.complete-oauth-login: ''
error.oauth-unsupported: ''
error.cannot-bind-data: ''
error.invalid-number: ''
error.invalid-character-unescaped: ''
admin.invitations: ''
admin.invitations.create: ''
admin.actions.sync-previews: ''
admin.actions.reset-hooks: ''
admin.actions.index-gists: ''
admin.invitations.help: ''
admin.invitations.max_uses: ''
admin.invitations.expires_at: ''
admin.invitations.code: ''
admin.invitations.copy_link: ''
admin.invitations.uses: ''
admin.invitations.expired: ''
flash.admin.user-deleted: ''
flash.admin.gist-deleted: ''
flash.admin.invitation-created: ''
flash.admin.invitation-deleted: ''
flash.admin.sync-fs: ''
flash.admin.sync-db: ''
flash.admin.git-gc: ''
flash.admin.sync-previews: ''
flash.admin.reset-hooks: ''
flash.admin.index-gists: ''
flash.auth.username-exists: ''
flash.auth.invalid-credentials: ''
flash.auth.account-linked-oauth: ''
flash.auth.account-unlinked-oauth: ''
flash.auth.user-sshkeys-not-retrievable: ''
flash.auth.user-sshkeys-not-created: ''
flash.auth.must-be-logged-in: ''
flash.gist.visibility-changed: ''
flash.gist.deleted: ''
flash.gist.fork-own-gist: ''
flash.gist.forked: ''
flash.user.email-updated: ''
flash.user.invalid-ssh-key: ''
flash.user.ssh-key-added: ''
flash.user.ssh-key-deleted: ''
flash.user.password-updated: ''
flash.user.username-updated: ''
validation.is-too-long: ''
validation.should-not-be-empty: ''
validation.should-not-include-sub-directory: ''
validation.should-only-contain-alphanumeric-characters: ''
validation.should-only-contain-alphanumeric-characters-and-dashes: ''
validation.not-enough: ''
validation.invalid: ''
html.title.admin-panel: ''

View File

@@ -193,3 +193,66 @@ admin.actions.index-gists: 索引所有的 Gists
gist.search.help.user: 由使用者建立的 Gists
gist.search.found: 已找到 Gists
gist.search.help.extension: Gists 的副檔名
gist.new.preview: ''
gist.new.create-a-new-gist: ''
gist.edit.edit-gist: ''
gist.list.all-liked-by: ''
gist.list.all-forked-by: ''
gist.list.all-from: ''
gist.forks.for: ''
gist.likes.for: ''
gist.revision-of: ''
error.page-not-found: ''
error.bad-request: ''
error.signup-disabled: ''
error.signup-disabled-form: ''
error.login-disabled-form: ''
error.complete-oauth-login: ''
error.oauth-unsupported: ''
error.cannot-bind-data: ''
error.invalid-number: ''
error.invalid-character-unescaped: ''
admin.invitations: ''
admin.invitations.create: ''
admin.invitations.help: ''
admin.invitations.max_uses: ''
admin.invitations.expires_at: ''
admin.invitations.code: ''
admin.invitations.copy_link: ''
admin.invitations.uses: ''
admin.invitations.expired: ''
flash.admin.user-deleted: ''
flash.admin.gist-deleted: ''
flash.admin.invitation-created: ''
flash.admin.invitation-deleted: ''
flash.admin.sync-fs: ''
flash.admin.sync-db: ''
flash.admin.git-gc: ''
flash.admin.sync-previews: ''
flash.admin.reset-hooks: ''
flash.admin.index-gists: ''
flash.auth.username-exists: ''
flash.auth.invalid-credentials: ''
flash.auth.account-linked-oauth: ''
flash.auth.account-unlinked-oauth: ''
flash.auth.user-sshkeys-not-retrievable: ''
flash.auth.user-sshkeys-not-created: ''
flash.auth.must-be-logged-in: ''
flash.gist.visibility-changed: ''
flash.gist.deleted: ''
flash.gist.fork-own-gist: ''
flash.gist.forked: ''
flash.user.email-updated: ''
flash.user.invalid-ssh-key: ''
flash.user.ssh-key-added: ''
flash.user.ssh-key-deleted: ''
flash.user.password-updated: ''
flash.user.username-updated: ''
validation.is-too-long: ''
validation.should-not-be-empty: ''
validation.should-not-include-sub-directory: ''
validation.should-only-contain-alphanumeric-characters: ''
validation.should-only-contain-alphanumeric-characters-and-dashes: ''
validation.not-enough: ''
validation.invalid: ''
html.title.admin-panel: ''

View File

@@ -2,6 +2,7 @@ package utils
import (
"github.com/go-playground/validator/v10"
"github.com/thomiceli/opengist/internal/i18n"
"regexp"
"strings"
)
@@ -26,26 +27,26 @@ func (cv *OpengistValidator) Var(field interface{}, tag string) error {
return cv.v.Var(field, tag)
}
func ValidationMessages(err *error) string {
func ValidationMessages(err *error, locale *i18n.Locale) string {
errs := (*err).(validator.ValidationErrors)
messages := make([]string, len(errs))
for i, e := range errs {
switch e.Tag() {
case "max":
messages[i] = e.Field() + " is too long"
messages[i] = locale.String("validation.is-too-long", e.Field())
case "required":
messages[i] = e.Field() + " should not be empty"
messages[i] = locale.String("validation.should-not-be-empty", e.Field())
case "excludes":
messages[i] = e.Field() + " should not include a sub directory"
messages[i] = locale.String("validation.should-not-include-sub-directory", e.Field())
case "alphanum":
messages[i] = e.Field() + " should only contain alphanumeric characters"
messages[i] = locale.String("validation.should-only-contain-alphanumeric-characters", e.Field())
case "alphanumdash":
case "alphanumdashorempty":
messages[i] = e.Field() + " should only contain alphanumeric characters and dashes"
messages[i] = locale.String("validation.should-only-contain-alphanumeric-characters-and-dashes", e.Field())
case "min":
messages[i] = "Not enough " + e.Field()
messages[i] = locale.String("validation.not-enough", e.Field())
case "notreserved":
messages[i] = "Invalid " + e.Field()
messages[i] = locale.String("validation.invalid", e.Field())
}
}

View File

@@ -12,8 +12,7 @@ import (
)
func adminIndex(ctx echo.Context) error {
setData(ctx, "title", "Admin panel")
setData(ctx, "htmlTitle", "Admin panel")
setData(ctx, "htmlTitle", trH(ctx, "admin.admin_panel"))
setData(ctx, "adminHeaderPage", "index")
setData(ctx, "opengistVersion", config.OpengistVersion)
@@ -52,8 +51,7 @@ func adminIndex(ctx echo.Context) error {
}
func adminUsers(ctx echo.Context) error {
setData(ctx, "title", "Users")
setData(ctx, "htmlTitle", "Users - Admin panel")
setData(ctx, "htmlTitle", trH(ctx, "admin.users")+" - "+trH(ctx, "admin.admin_panel"))
setData(ctx, "adminHeaderPage", "users")
pageInt := getPage(ctx)
@@ -64,15 +62,14 @@ func adminUsers(ctx echo.Context) error {
}
if err = paginate(ctx, data, pageInt, 10, "data", "admin-panel/users", 1); err != nil {
return errorRes(404, "Page not found", nil)
return errorRes(404, tr(ctx, "error.page-not-found"), nil)
}
return html(ctx, "admin_users.html")
}
func adminGists(ctx echo.Context) error {
setData(ctx, "title", "Gists")
setData(ctx, "htmlTitle", "Gists - Admin panel")
setData(ctx, "htmlTitle", trH(ctx, "admin.gists")+" - "+trH(ctx, "admin.admin_panel"))
setData(ctx, "adminHeaderPage", "gists")
pageInt := getPage(ctx)
@@ -83,7 +80,7 @@ func adminGists(ctx echo.Context) error {
}
if err = paginate(ctx, data, pageInt, 10, "data", "admin-panel/gists", 1); err != nil {
return errorRes(404, "Page not found", nil)
return errorRes(404, tr(ctx, "error.page-not-found"), nil)
}
return html(ctx, "admin_gists.html")
@@ -100,7 +97,7 @@ func adminUserDelete(ctx echo.Context) error {
return errorRes(500, "Cannot delete this user", err)
}
addFlash(ctx, "User has been deleted", "success")
addFlash(ctx, tr(ctx, "flash.admin.user-deleted"), "success")
return redirect(ctx, "/admin-panel/users")
}
@@ -120,49 +117,48 @@ func adminGistDelete(ctx echo.Context) error {
gist.RemoveFromIndex()
addFlash(ctx, "Gist has been deleted", "success")
addFlash(ctx, tr(ctx, "flash.admin.gist-deleted"), "success")
return redirect(ctx, "/admin-panel/gists")
}
func adminSyncReposFromFS(ctx echo.Context) error {
addFlash(ctx, "Syncing repositories from filesystem...", "success")
addFlash(ctx, tr(ctx, "flash.admin.sync-fs"), "success")
go actions.Run(actions.SyncReposFromFS)
return redirect(ctx, "/admin-panel")
}
func adminSyncReposFromDB(ctx echo.Context) error {
addFlash(ctx, "Syncing repositories from database...", "success")
addFlash(ctx, tr(ctx, "flash.admin.sync-db"), "success")
go actions.Run(actions.SyncReposFromDB)
return redirect(ctx, "/admin-panel")
}
func adminGcRepos(ctx echo.Context) error {
addFlash(ctx, "Garbage collecting repositories...", "success")
addFlash(ctx, tr(ctx, "flash.admin.git-gc"), "success")
go actions.Run(actions.GitGcRepos)
return redirect(ctx, "/admin-panel")
}
func adminSyncGistPreviews(ctx echo.Context) error {
addFlash(ctx, "Syncing Gist previews...", "success")
addFlash(ctx, tr(ctx, "flash.admin.sync-previews"), "success")
go actions.Run(actions.SyncGistPreviews)
return redirect(ctx, "/admin-panel")
}
func adminResetHooks(ctx echo.Context) error {
addFlash(ctx, "Resetting Git server hooks for all repositories...", "success")
addFlash(ctx, tr(ctx, "flash.admin.reset-hooks"), "success")
go actions.Run(actions.ResetHooks)
return redirect(ctx, "/admin-panel")
}
func adminIndexGists(ctx echo.Context) error {
addFlash(ctx, "Indexing all gists...", "success")
addFlash(ctx, tr(ctx, "flash.admin.index-gists"), "success")
go actions.Run(actions.IndexGists)
return redirect(ctx, "/admin-panel")
}
func adminConfig(ctx echo.Context) error {
setData(ctx, "title", "Configuration")
setData(ctx, "htmlTitle", "Configuration - Admin panel")
setData(ctx, "htmlTitle", trH(ctx, "admin.configuration")+" - "+trH(ctx, "admin.admin_panel"))
setData(ctx, "adminHeaderPage", "config")
return html(ctx, "admin_config.html")
@@ -182,8 +178,7 @@ func adminSetConfig(ctx echo.Context) error {
}
func adminInvitations(ctx echo.Context) error {
setData(ctx, "title", "Invitations")
setData(ctx, "htmlTitle", "Invitations - Admin panel")
setData(ctx, "htmlTitle", trH(ctx, "admin.invitations")+" - "+trH(ctx, "admin.admin_panel"))
setData(ctx, "adminHeaderPage", "invitations")
var invitations []*db.Invitation
@@ -218,7 +213,7 @@ func adminInvitationsCreate(ctx echo.Context) error {
return errorRes(500, "Cannot create invitation", err)
}
addFlash(ctx, "Invitation has been created", "success")
addFlash(ctx, tr(ctx, "flash.admin.invitation-created"), "success")
return redirect(ctx, "/admin-panel/invitations")
}
@@ -233,6 +228,6 @@ func adminInvitationsDelete(ctx echo.Context) error {
return errorRes(500, "Cannot delete this invitation", err)
}
addFlash(ctx, "Invitation has been deleted", "success")
addFlash(ctx, tr(ctx, "flash.admin.invitation-deleted"), "success")
return redirect(ctx, "/admin-panel/invitations")
}

View File

@@ -16,6 +16,7 @@ import (
"github.com/rs/zerolog/log"
"github.com/thomiceli/opengist/internal/config"
"github.com/thomiceli/opengist/internal/db"
"github.com/thomiceli/opengist/internal/i18n"
"github.com/thomiceli/opengist/internal/utils"
"golang.org/x/text/cases"
"golang.org/x/text/language"
@@ -48,8 +49,8 @@ func register(ctx echo.Context) error {
}
}
setData(ctx, "title", tr(ctx, "auth.new-account"))
setData(ctx, "htmlTitle", "New account")
setData(ctx, "title", trH(ctx, "auth.new-account"))
setData(ctx, "htmlTitle", trH(ctx, "auth.new-account"))
setData(ctx, "disableForm", disableForm)
setData(ctx, "disableSignup", disableSignup)
setData(ctx, "isLoginPage", false)
@@ -68,30 +69,30 @@ func processRegister(ctx echo.Context) error {
}
if disableSignup == true {
return errorRes(403, "Signing up is disabled", nil)
return errorRes(403, tr(ctx, "error.signup-disabled"), nil)
}
if getData(ctx, "DisableLoginForm") == true {
return errorRes(403, "Signing up via registration form is disabled", nil)
return errorRes(403, tr(ctx, "error.signup-disabled-form"), nil)
}
setData(ctx, "title", "New account")
setData(ctx, "htmlTitle", "New account")
setData(ctx, "title", trH(ctx, "auth.new-account"))
setData(ctx, "htmlTitle", trH(ctx, "auth.new-account"))
sess := getSession(ctx)
dto := new(db.UserDTO)
if err := ctx.Bind(dto); err != nil {
return errorRes(400, "Cannot bind data", err)
return errorRes(400, tr(ctx, "error.cannot-bind-data"), err)
}
if err := ctx.Validate(dto); err != nil {
addFlash(ctx, utils.ValidationMessages(&err), "error")
addFlash(ctx, utils.ValidationMessages(&err, getData(ctx, "locale").(*i18n.Locale)), "error")
return html(ctx, "auth_form.html")
}
if exists, err := db.UserExists(dto.Username); err != nil || exists {
addFlash(ctx, "Username already exists", "error")
addFlash(ctx, tr(ctx, "flash.auth.username-exists"), "error")
return html(ctx, "auth_form.html")
}
@@ -126,8 +127,8 @@ func processRegister(ctx echo.Context) error {
}
func login(ctx echo.Context) error {
setData(ctx, "title", tr(ctx, "auth.login"))
setData(ctx, "htmlTitle", "Login")
setData(ctx, "title", trH(ctx, "auth.login"))
setData(ctx, "htmlTitle", trH(ctx, "auth.login"))
setData(ctx, "disableForm", getData(ctx, "DisableLoginForm"))
setData(ctx, "isLoginPage", true)
return html(ctx, "auth_form.html")
@@ -135,7 +136,7 @@ func login(ctx echo.Context) error {
func processLogin(ctx echo.Context) error {
if getData(ctx, "DisableLoginForm") == true {
return errorRes(403, "Logging in via login form is disabled", nil)
return errorRes(403, tr(ctx, "error.login-disabled-form"), nil)
}
var err error
@@ -143,7 +144,7 @@ func processLogin(ctx echo.Context) error {
dto := &db.UserDTO{}
if err = ctx.Bind(dto); err != nil {
return errorRes(400, "Cannot bind data", err)
return errorRes(400, tr(ctx, "error.cannot-bind-data"), err)
}
password := dto.Password
@@ -154,7 +155,7 @@ func processLogin(ctx echo.Context) error {
return errorRes(500, "Cannot get user", err)
}
log.Warn().Msg("Invalid HTTP authentication attempt from " + ctx.RealIP())
addFlash(ctx, "Invalid credentials", "error")
addFlash(ctx, tr(ctx, "flash.auth.invalid-credentials"), "error")
return redirect(ctx, "/login")
}
@@ -163,7 +164,7 @@ func processLogin(ctx echo.Context) error {
return errorRes(500, "Cannot check for password", err)
}
log.Warn().Msg("Invalid HTTP authentication attempt from " + ctx.RealIP())
addFlash(ctx, "Invalid credentials", "error")
addFlash(ctx, tr(ctx, "flash.auth.invalid-credentials"), "error")
return redirect(ctx, "/login")
}
@@ -178,7 +179,7 @@ func processLogin(ctx echo.Context) error {
func oauthCallback(ctx echo.Context) error {
user, err := gothic.CompleteUserAuth(ctx.Response(), ctx.Request())
if err != nil {
return errorRes(400, "Cannot complete user auth: "+err.Error(), err)
return errorRes(400, tr(ctx, "error.complete-oauth-login", err.Error()), err)
}
currUser := getUserLogged(ctx)
@@ -190,7 +191,7 @@ func oauthCallback(ctx echo.Context) error {
return errorRes(500, "Cannot update user "+title.String(user.Provider)+" id", err)
}
addFlash(ctx, "Account linked to "+title.String(user.Provider), "success")
addFlash(ctx, tr(ctx, "flash.auth.account-linked-oauth", title.String(user.Provider)), "success")
return redirect(ctx, "/settings")
}
@@ -198,7 +199,7 @@ func oauthCallback(ctx echo.Context) error {
userDB, err := db.GetUserByProvider(user.UserID, user.Provider)
if err != nil {
if getData(ctx, "DisableSignup") == true {
return errorRes(403, "Signing up is disabled", nil)
return errorRes(403, tr(ctx, "error.signup-disabled"), nil)
}
if !errors.Is(err, gorm.ErrRecordNotFound) {
@@ -216,7 +217,7 @@ func oauthCallback(ctx echo.Context) error {
if err = userDB.Create(); err != nil {
if db.IsUniqueConstraintViolation(err) {
addFlash(ctx, "Username "+user.NickName+" already exists in Opengist", "error")
addFlash(ctx, tr(ctx, "flash.auth.username-exists"), "error")
return redirect(ctx, "/login")
}
@@ -246,7 +247,7 @@ func oauthCallback(ctx echo.Context) error {
body, err := io.ReadAll(resp.Body)
if err != nil {
addFlash(ctx, "Could not get user keys", "error")
addFlash(ctx, tr(ctx, "flash.auth.user-sshkeys-not-retrievable"), "error")
log.Error().Err(err).Msg("Could not get user keys")
}
@@ -262,7 +263,7 @@ func oauthCallback(ctx echo.Context) error {
}
if err = sshKey.Create(); err != nil {
addFlash(ctx, "Could not create ssh key", "error")
addFlash(ctx, tr(ctx, "flash.auth.user-sshkeys-not-created"), "error")
log.Error().Err(err).Msg("Could not create ssh key")
}
}
@@ -360,7 +361,7 @@ func oauth(ctx echo.Context) error {
return errorRes(500, "Cannot unlink account from "+title.String(provider), err)
}
addFlash(ctx, "Account unlinked from "+title.String(provider), "success")
addFlash(ctx, tr(ctx, "flash.auth.account-unlinked-oauth", title.String(provider)), "success")
return redirect(ctx, "/settings")
}
}
@@ -368,7 +369,7 @@ func oauth(ctx echo.Context) error {
ctxValue := context.WithValue(ctx.Request().Context(), gothic.ProviderParamKey, provider)
ctx.SetRequest(ctx.Request().WithContext(ctxValue))
if provider != GitHubProvider && provider != GitLabProvider && provider != GiteaProvider && provider != OpenIDConnect {
return errorRes(400, "Unsupported provider", nil)
return errorRes(400, tr(ctx, "error.oauth-unsupported"), nil)
}
gothic.BeginAuthHandler(ctx.Response(), ctx.Request())

View File

@@ -8,6 +8,7 @@ import (
"fmt"
"github.com/rs/zerolog/log"
"github.com/thomiceli/opengist/internal/git"
"github.com/thomiceli/opengist/internal/i18n"
"github.com/thomiceli/opengist/internal/index"
"github.com/thomiceli/opengist/internal/render"
"github.com/thomiceli/opengist/internal/utils"
@@ -139,18 +140,18 @@ func allGists(ctx echo.Context) error {
pageInt := getPage(ctx)
sort := "created"
sortText := tr(ctx, "gist.list.sort-by-created")
sortText := trH(ctx, "gist.list.sort-by-created")
order := "desc"
orderText := tr(ctx, "gist.list.order-by-desc")
orderText := trH(ctx, "gist.list.order-by-desc")
if ctx.QueryParam("sort") == "updated" {
sort = "updated"
sortText = tr(ctx, "gist.list.sort-by-updated")
sortText = trH(ctx, "gist.list.sort-by-updated")
}
if ctx.QueryParam("order") == "asc" {
order = "asc"
orderText = tr(ctx, "gist.list.order-by-asc")
orderText = trH(ctx, "gist.list.order-by-asc")
}
setData(ctx, "sort", sortText)
@@ -167,14 +168,14 @@ func allGists(ctx echo.Context) error {
if fromUserStr == "" {
urlctx := ctx.Request().URL.Path
if strings.HasSuffix(urlctx, "search") {
setData(ctx, "htmlTitle", "Search results")
setData(ctx, "htmlTitle", trH(ctx, "gist.list.search-results"))
setData(ctx, "mode", "search")
setData(ctx, "searchQuery", ctx.QueryParam("q"))
setData(ctx, "searchQueryUrl", template.URL("&q="+ctx.QueryParam("q")))
urlPage = "search"
gists, err = db.GetAllGistsFromSearch(currentUserId, ctx.QueryParam("q"), pageInt-1, sort, order)
} else if strings.HasSuffix(urlctx, "all") {
setData(ctx, "htmlTitle", "All gists")
setData(ctx, "htmlTitle", trH(ctx, "gist.list.all"))
setData(ctx, "mode", "all")
urlPage = "all"
gists, err = db.GetAllGistsForCurrentUser(currentUserId, pageInt-1, sort, order)
@@ -224,17 +225,17 @@ func allGists(ctx echo.Context) error {
if liked {
urlPage = fromUserStr + "/liked"
setData(ctx, "htmlTitle", "All gists liked by "+fromUserStr)
setData(ctx, "htmlTitle", trH(ctx, "gist.list.all-liked-by", fromUserStr))
setData(ctx, "mode", "liked")
gists, err = db.GetAllGistsLikedByUser(fromUser.ID, currentUserId, pageInt-1, sort, order)
} else if forked {
urlPage = fromUserStr + "/forked"
setData(ctx, "htmlTitle", "All gists forked by "+fromUserStr)
setData(ctx, "htmlTitle", trH(ctx, "gist.list.all-forked-by", fromUserStr))
setData(ctx, "mode", "forked")
gists, err = db.GetAllGistsForkedByUser(fromUser.ID, currentUserId, pageInt-1, sort, order)
} else {
urlPage = fromUserStr
setData(ctx, "htmlTitle", "All gists from "+fromUserStr)
setData(ctx, "htmlTitle", trH(ctx, "gist.list.all-from", fromUserStr))
setData(ctx, "mode", "fromUser")
gists, err = db.GetAllGistsFromUser(fromUser.ID, currentUserId, pageInt-1, sort, order)
}
@@ -254,7 +255,7 @@ func allGists(ctx echo.Context) error {
}
if err = paginate(ctx, renderedGists, pageInt, 10, "gists", fromUserStr, 2, "&sort="+sort+"&order="+order); err != nil {
return errorRes(404, "Page not found", nil)
return errorRes(404, tr(ctx, "error.page-not-found"), nil)
}
setData(ctx, "urlPage", urlPage)
@@ -312,11 +313,11 @@ func search(ctx echo.Context) error {
if 10*pageInt < int(nbHits) {
setData(ctx, "nextPage", pageInt+1)
}
setData(ctx, "prevLabel", tr(ctx, "pagination.previous"))
setData(ctx, "nextLabel", tr(ctx, "pagination.next"))
setData(ctx, "prevLabel", trH(ctx, "pagination.previous"))
setData(ctx, "nextLabel", trH(ctx, "pagination.next"))
setData(ctx, "urlPage", "search")
setData(ctx, "urlParams", template.URL("&q="+ctx.QueryParam("q")))
setData(ctx, "htmlTitle", "Search results")
setData(ctx, "htmlTitle", trH(ctx, "gist.list.search-results"))
setData(ctx, "nbHits", nbHits)
setData(ctx, "gists", renderedGists)
setData(ctx, "langs", langs)
@@ -449,7 +450,7 @@ func revisions(ctx echo.Context) error {
}
if err := paginate(ctx, commits, pageInt, 10, "commits", userName+"/"+gistName+"/revisions", 2); err != nil {
return errorRes(404, "Page not found", nil)
return errorRes(404, tr(ctx, "error.page-not-found"), nil)
}
emailsSet := map[string]struct{}{}
@@ -468,13 +469,13 @@ func revisions(ctx echo.Context) error {
setData(ctx, "page", "revisions")
setData(ctx, "revision", "HEAD")
setData(ctx, "emails", emailsUsers)
setData(ctx, "htmlTitle", "Revision of "+gist.Title)
setData(ctx, "htmlTitle", trH(ctx, "gist.revision-of", gist.Title))
return html(ctx, "revisions.html")
}
func create(ctx echo.Context) error {
setData(ctx, "htmlTitle", "Create a new gist")
setData(ctx, "htmlTitle", trH(ctx, "gist.new.create-a-new-gist"))
return html(ctx, "create.html")
}
@@ -486,21 +487,21 @@ func processCreate(ctx echo.Context) error {
err := ctx.Request().ParseForm()
if err != nil {
return errorRes(400, "Bad request", err)
return errorRes(400, tr(ctx, "error.bad-request"), err)
}
dto := new(db.GistDTO)
var gist *db.Gist
if isCreate {
setData(ctx, "htmlTitle", "Create a new gist")
setData(ctx, "htmlTitle", trH(ctx, "gist.new.create-a-new-gist"))
} else {
gist = getData(ctx, "gist").(*db.Gist)
setData(ctx, "htmlTitle", "Edit "+gist.Title)
setData(ctx, "htmlTitle", trH(ctx, "gist.edit.edit-gist", gist.Title))
}
if err := ctx.Bind(dto); err != nil {
return errorRes(400, "Cannot bind data", err)
return errorRes(400, tr(ctx, "error.cannot-bind-data"), err)
}
dto.Files = make([]db.FileDTO, 0)
@@ -516,7 +517,7 @@ func processCreate(ctx echo.Context) error {
escapedValue, err := url.QueryUnescape(content)
if err != nil {
return errorRes(400, "Invalid character unescaped", err)
return errorRes(400, tr(ctx, "error.invalid-character-unescaped"), err)
}
dto.Files = append(dto.Files, db.FileDTO{
@@ -527,7 +528,7 @@ func processCreate(ctx echo.Context) error {
err = ctx.Validate(dto)
if err != nil {
addFlash(ctx, utils.ValidationMessages(&err), "error")
addFlash(ctx, utils.ValidationMessages(&err, getData(ctx, "locale").(*i18n.Locale)), "error")
if isCreate {
return html(ctx, "create.html")
} else {
@@ -610,7 +611,7 @@ func toggleVisibility(ctx echo.Context) error {
return errorRes(500, "Error updating this gist", err)
}
addFlash(ctx, "Gist visibility has been changed", "success")
addFlash(ctx, tr(ctx, "flash.gist.visibility-changed"), "success")
return redirect(ctx, "/"+gist.User.Username+"/"+gist.Identifier())
}
@@ -622,7 +623,7 @@ func deleteGist(ctx echo.Context) error {
}
gist.RemoveFromIndex()
addFlash(ctx, "Gist has been deleted", "success")
addFlash(ctx, tr(ctx, "flash.gist.deleted"), "success")
return redirect(ctx, "/")
}
@@ -662,7 +663,7 @@ func fork(ctx echo.Context) error {
}
if gist.User.ID == currentUser.ID {
addFlash(ctx, "Unable to fork own gists", "error")
addFlash(ctx, tr(ctx, "flash.gist.fork-own-gist"), "error")
return redirect(ctx, "/"+gist.User.Username+"/"+gist.Identifier())
}
@@ -698,7 +699,7 @@ func fork(ctx echo.Context) error {
return errorRes(500, "Error incrementing the fork count", err)
}
addFlash(ctx, "Gist has been forked", "success")
addFlash(ctx, tr(ctx, "flash.gist.forked"), "success")
return redirect(ctx, "/"+currentUser.Username+"/"+newGist.Identifier())
}
@@ -749,7 +750,7 @@ func edit(ctx echo.Context) error {
}
setData(ctx, "files", files)
setData(ctx, "htmlTitle", "Edit "+gist.Title)
setData(ctx, "htmlTitle", trH(ctx, "gist.edit.edit-gist", gist.Title))
return html(ctx, "edit.html")
}
@@ -810,10 +811,10 @@ func likes(ctx echo.Context) error {
}
if err = paginate(ctx, likers, pageInt, 30, "likers", gist.User.Username+"/"+gist.Identifier()+"/likes", 1); err != nil {
return errorRes(404, "Page not found", nil)
return errorRes(404, tr(ctx, "error.page-not-found"), nil)
}
setData(ctx, "htmlTitle", "Like for "+gist.Title)
setData(ctx, "htmlTitle", trH(ctx, "gist.likes.for", gist.Title))
setData(ctx, "revision", "HEAD")
return html(ctx, "likes.html")
}
@@ -834,10 +835,10 @@ func forks(ctx echo.Context) error {
}
if err = paginate(ctx, forks, pageInt, 30, "forks", gist.User.Username+"/"+gist.Identifier()+"/forks", 2); err != nil {
return errorRes(404, "Page not found", nil)
return errorRes(404, tr(ctx, "error.page-not-found"), nil)
}
setData(ctx, "htmlTitle", "Forks for "+gist.Title)
setData(ctx, "htmlTitle", trH(ctx, "gist.forks.for: Forks for %s", gist.Title))
setData(ctx, "revision", "HEAD")
return html(ctx, "forks.html")
}
@@ -848,7 +849,7 @@ func checkbox(ctx echo.Context) error {
i, err := strconv.Atoi(checkboxNb)
if err != nil {
return errorRes(400, "Invalid number", nil)
return errorRes(400, tr(ctx, "error.invalid-number"), nil)
}
gist := getData(ctx, "gist").(*db.Gist)

View File

@@ -523,7 +523,7 @@ func checkRequireLogin(next echo.HandlerFunc) echo.HandlerFunc {
require := getData(ctx, "RequireLogin")
if require == true {
addFlash(ctx, "You must be logged in to access gists", "error")
addFlash(ctx, tr(ctx, "flash.auth.must-be-logged-in"), "error")
return redirect(ctx, "/login")
}
return next(ctx)

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"github.com/thomiceli/opengist/internal/config"
"github.com/thomiceli/opengist/internal/git"
"github.com/thomiceli/opengist/internal/i18n"
"github.com/thomiceli/opengist/internal/utils"
"os"
"path/filepath"
@@ -28,7 +29,7 @@ func userSettings(ctx echo.Context) error {
setData(ctx, "email", user.Email)
setData(ctx, "sshKeys", keys)
setData(ctx, "hasPassword", user.Password != "")
setData(ctx, "htmlTitle", "Settings")
setData(ctx, "htmlTitle", trH(ctx, "settings"))
return html(ctx, "settings.html")
}
@@ -51,7 +52,7 @@ func emailProcess(ctx echo.Context) error {
return errorRes(500, "Cannot update email", err)
}
addFlash(ctx, "Email updated", "success")
addFlash(ctx, tr(ctx, "flash.user.email-updated"), "success")
return redirect(ctx, "/settings")
}
@@ -70,11 +71,11 @@ func sshKeysProcess(ctx echo.Context) error {
dto := new(db.SSHKeyDTO)
if err := ctx.Bind(dto); err != nil {
return errorRes(400, "Cannot bind data", err)
return errorRes(400, tr(ctx, "error.cannot-bind-data"), err)
}
if err := ctx.Validate(dto); err != nil {
addFlash(ctx, utils.ValidationMessages(&err), "error")
addFlash(ctx, utils.ValidationMessages(&err, getData(ctx, "locale").(*i18n.Locale)), "error")
return redirect(ctx, "/settings")
}
key := dto.ToSSHKey()
@@ -83,7 +84,7 @@ func sshKeysProcess(ctx echo.Context) error {
pubKey, _, _, _, err := ssh.ParseAuthorizedKey([]byte(key.Content))
if err != nil {
addFlash(ctx, "Invalid SSH key", "error")
addFlash(ctx, tr(ctx, "flash.user.invalid-ssh-key"), "error")
return redirect(ctx, "/settings")
}
key.Content = strings.TrimSpace(string(ssh.MarshalAuthorizedKey(pubKey)))
@@ -92,7 +93,7 @@ func sshKeysProcess(ctx echo.Context) error {
return errorRes(500, "Cannot add SSH key", err)
}
addFlash(ctx, "SSH key added", "success")
addFlash(ctx, tr(ctx, "flash.user.ssh-key-added"), "success")
return redirect(ctx, "/settings")
}
@@ -113,7 +114,7 @@ func sshKeysDelete(ctx echo.Context) error {
return errorRes(500, "Cannot delete SSH key", err)
}
addFlash(ctx, "SSH key deleted", "success")
addFlash(ctx, tr(ctx, "flash.user.ssh-key-deleted"), "success")
return redirect(ctx, "/settings")
}
@@ -122,12 +123,12 @@ func passwordProcess(ctx echo.Context) error {
dto := new(db.UserDTO)
if err := ctx.Bind(dto); err != nil {
return errorRes(400, "Cannot bind data", err)
return errorRes(400, tr(ctx, "error.cannot-bind-data"), err)
}
dto.Username = user.Username
if err := ctx.Validate(dto); err != nil {
addFlash(ctx, utils.ValidationMessages(&err), "error")
addFlash(ctx, utils.ValidationMessages(&err, getData(ctx, "locale").(*i18n.Locale)), "error")
return html(ctx, "settings.html")
}
@@ -141,7 +142,7 @@ func passwordProcess(ctx echo.Context) error {
return errorRes(500, "Cannot update password", err)
}
addFlash(ctx, "Password updated", "success")
addFlash(ctx, tr(ctx, "flash.user.password-updated"), "success")
return redirect(ctx, "/settings")
}
@@ -150,17 +151,17 @@ func usernameProcess(ctx echo.Context) error {
dto := new(db.UserDTO)
if err := ctx.Bind(dto); err != nil {
return errorRes(400, "Cannot bind data", err)
return errorRes(400, tr(ctx, "error.cannot-bind-data"), err)
}
dto.Password = user.Password
if err := ctx.Validate(dto); err != nil {
addFlash(ctx, utils.ValidationMessages(&err), "error")
addFlash(ctx, utils.ValidationMessages(&err, getData(ctx, "locale").(*i18n.Locale)), "error")
return redirect(ctx, "/settings")
}
if exists, err := db.UserExists(dto.Username); err != nil || exists {
addFlash(ctx, "Username already exists", "error")
addFlash(ctx, tr(ctx, "flash.auth.username-exists"), "error")
return redirect(ctx, "/settings")
}
@@ -180,6 +181,6 @@ func usernameProcess(ctx echo.Context) error {
return errorRes(500, "Cannot update username", err)
}
addFlash(ctx, "Username updated", "success")
addFlash(ctx, tr(ctx, "flash.user.username-updated"), "success")
return redirect(ctx, "/settings")
}

View File

@@ -158,11 +158,11 @@ func paginate[T any](ctx echo.Context, data []*T, pageInt int, perPage int, temp
switch labels {
case 1:
setData(ctx, "prevLabel", tr(ctx, "pagination.previous"))
setData(ctx, "nextLabel", tr(ctx, "pagination.next"))
setData(ctx, "prevLabel", trH(ctx, "pagination.previous"))
setData(ctx, "nextLabel", trH(ctx, "pagination.next"))
case 2:
setData(ctx, "prevLabel", tr(ctx, "pagination.newer"))
setData(ctx, "nextLabel", tr(ctx, "pagination.older"))
setData(ctx, "prevLabel", trH(ctx, "pagination.newer"))
setData(ctx, "nextLabel", trH(ctx, "pagination.older"))
}
setData(ctx, "urlPage", urlPage)
@@ -170,9 +170,14 @@ func paginate[T any](ctx echo.Context, data []*T, pageInt int, perPage int, temp
return nil
}
func tr(ctx echo.Context, key string) template.HTML {
func trH(ctx echo.Context, key string, args ...any) template.HTML {
l := getData(ctx, "locale").(*i18n.Locale)
return l.Tr(key)
return l.Tr(key, args...)
}
func tr(ctx echo.Context, key string, args ...any) string {
l := getData(ctx, "locale").(*i18n.Locale)
return l.String(key, args...)
}
func parseSearchQueryStr(query string) (string, map[string]string) {

View File

@@ -36,8 +36,17 @@ document.addEventListener("DOMContentLoaded", () => {
let mdpreview = dom.querySelector(".md-preview") as HTMLElement;
let formfilename = dom.querySelector<HTMLInputElement>(".form-filename");
// check if file ends with .md on pageload
if (formfilename!.value.endsWith(".md")) {
mdpreview!.classList.remove("hidden");
} else {
mdpreview!.classList.add("hidden");
}
// event if the filename ends with .md; trigger event
dom.querySelector<HTMLInputElement>(".form-filename")!.onkeyup = (e) => {
formfilename!.onkeyup = (e) => {
let filename = (e.target as HTMLInputElement).value;
if (filename.endsWith(".md")) {
mdpreview!.classList.remove("hidden");

View File

@@ -21,6 +21,9 @@ document.querySelectorAll<HTMLElement>('.table-code').forEach((el) => {
let copybtnhtml = `<button type="button" style="top: 1em !important; right: 1em !important;" class="md-code-copy-btn absolute focus-within:z-auto rounded-md dark:border-gray-600 px-2 py-2 opacity-80 font-medium text-slate-700 bg-gray-100 dark:bg-gray-700 dark:text-slate-300 hover:bg-gray-200 dark:hover:bg-gray-600 hover:border-gray-500 hover:text-slate-700 dark:hover:text-slate-300 focus:border-primary-500 focus:outline-none focus:ring-1 focus:ring-primary-500"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-5 h-5"><path stroke-linecap="round" stroke-linejoin="round" d="M8.25 7.5V6.108c0-1.135.845-2.098 1.976-2.192.373-.03.748-.057 1.123-.08M15.75 18H18a2.25 2.25 0 002.25-2.25V6.108c0-1.135-.845-2.098-1.976-2.192a48.424 48.424 0 00-1.123-.08M15.75 18.75v-1.875a3.375 3.375 0 00-3.375-3.375h-1.5a1.125 1.125 0 01-1.125-1.125v-1.5A3.375 3.375 0 006.375 7.5H5.25m11.9-3.664A2.251 2.251 0 0015 2.25h-1.5a2.251 2.251 0 00-2.15 1.586m5.8 0c.065.21.1.433.1.664v.75h-6V4.5c0-.231.035-.454.1-.664M6.75 7.5H4.875c-.621 0-1.125.504-1.125 1.125v12c0 .621.504 1.125 1.125 1.125h9.75c.621 0 1.125-.504 1.125-1.125V16.5a9 9 0 00-9-9z" /></svg></button>`;
document.querySelectorAll<HTMLElement>('.markdown-body pre').forEach((el) => {
if (el.classList.contains("mermaid")) {
return;
}
el.innerHTML = copybtnhtml + `<span class="code-div">` + el.innerHTML + `</span>`;
});

View File

@@ -4,10 +4,19 @@ import './opengist.svg';
import './default.png';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import 'dayjs/locale/cs';
import 'dayjs/locale/de';
import 'dayjs/locale/es';
import 'dayjs/locale/fr';
import 'dayjs/locale/hu';
import 'dayjs/locale/pt';
import 'dayjs/locale/ru';
import 'dayjs/locale/zh';
import localizedFormat from 'dayjs/plugin/localizedFormat';
dayjs.extend(relativeTime);
dayjs.extend(localizedFormat);
dayjs.locale(window.opengist_locale || 'en');
document.addEventListener('DOMContentLoaded', () => {
const themeMenu = document.getElementById('theme-menu')!;

View File

@@ -4,6 +4,7 @@ CHECKSUMS_FILE="build/checksums.txt"
BINARY_NAME="opengist"
TARGETS="darwin/amd64 darwin/arm64 linux/amd64 linux/arm64 linux/armv6 linux/armv7 linux/386 windows/amd64"
VERSION=$(git describe --tags | sed 's/^v//')
VERSION_PKG="github.com/thomiceli/opengist/internal/config.OpengistVersion"
if [ -z "$VERSION" ]; then
echo "Error: Could not retrieve version from git tags. Exiting..."
@@ -38,7 +39,7 @@ for TARGET in $TARGETS; do
echo "Building version $VERSION for $GOOS/$GOARCH${GOARM:+v$GOARM}..."
mkdir -p $OUTPUT_DIR
env GOOS=$GOOS GOARCH=$GOARCH GOARM=$GOARM CGO_ENABLED=0 go build -tags fs_embed -o $OUTPUT_FILE
env GOOS=$GOOS GOARCH=$GOARCH GOARM=$GOARM CGO_ENABLED=0 go build -tags fs_embed -ldflags "-X $VERSION_PKG=v$VERSION" -o $OUTPUT_FILE
cp README.md $OUTPUT_DIR
cp LICENSE $OUTPUT_DIR
cp config.yml $OUTPUT_DIR

View File

@@ -11,6 +11,7 @@
<script>
window.opengist_base_url = "{{ $.c.ExternalUrl }}";
window.opengist_locale = "{{ .locale.Code }}".substring(0, 2);
const checkTheme = () => {
if (localStorage.theme === 'dark' || (!('theme' in localStorage) && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark')
@@ -179,11 +180,11 @@
</div>
{{ else }}
{{ if not .DisableSignup }}
<a href="{{ $.c.ExternalUrl }}/register" class="inline-flex text-slate-700 dark:text-slate-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-black dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium">
<a href="{{ $.c.ExternalUrl }}/register" class="hidden sm:inline-flex text-slate-700 dark:text-slate-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-black dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium">
<p class="text-slate-700 dark:text-slate-300 mr-1">{{ .locale.Tr "header.menu.register" }}</p>
</a>
{{ end }}
<a href="{{ $.c.ExternalUrl }}/login" class="inline-flex text-slate-700 dark:text-slate-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-black dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium">
<a href="{{ $.c.ExternalUrl }}/login" class="hidden sm:inline-flex hidden-xs text-slate-700 dark:text-slate-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-black dark:hover:text-white px-3 py-2 rounded-md text-sm font-medium">
<p class="text-slate-700 dark:text-slate-300 mr-1">{{ .locale.Tr "header.menu.login" }}</p>
</a>
{{ end }}
@@ -252,9 +253,15 @@
<a href="{{ $.c.ExternalUrl }}/{{ .userLogged.Username }}" class="text-slate-700 dark:text-slate-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-black dark:hover:text-white block px-3 py-2 rounded-md text-base font-medium">{{ .locale.Tr "header.menu.my-gists" }}</a>
<a href="{{ $.c.ExternalUrl }}/settings" class="text-slate-700 dark:text-slate-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-black dark:hover:text-white block px-3 py-2 rounded-md text-base font-medium">{{ .locale.Tr "header.menu.settings" }}</a>
{{ if .userLogged.IsAdmin }}
{{ if .userLogged.IsAdmin }}
<a href="{{ $.c.ExternalUrl }}/admin-panel" class="text-slate-700 dark:text-slate-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-black dark:hover:text-white block px-3 py-2 rounded-md text-base font-medium">{{ .locale.Tr "header.menu.admin" }}</a>
{{ end }}
<a href="{{ $.c.ExternalUrl }}/logout" class="dark:text-rose-400 text-rose-500 hover:text-rose-600 dark:hover:text-rose-500 hover:bg-gray-100 dark:hover:bg-gray-700 block px-3 py-2 rounded-md text-base font-medium">{{ .locale.Tr "header.menu.logout" }}</a>
{{ else }}
{{ if not .DisableSignup }}
<a href="{{ $.c.ExternalUrl }}/register" class="text-slate-700 dark:text-slate-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-black dark:hover:text-white block px-3 py-2 rounded-md text-base font-medium">{{ .locale.Tr "header.menu.register" }}</a>
{{ end }}
<a href="{{ $.c.ExternalUrl }}/login" class="text-slate-700 dark:text-slate-300 hover:bg-gray-100 dark:hover:bg-gray-700 hover:text-black dark:hover:text-white block px-3 py-2 rounded-md text-base font-medium">{{ .locale.Tr "header.menu.login" }}</a>
{{ end }}
</div>
</div>

View File

@@ -35,7 +35,7 @@
<span class="flex text-sm ml-2 text-slate-700 dark:text-slate-300">{{ $file.Filename }}<span class="italic text-gray-600 dark:text-gray-400 ml-1">({{ $.locale.Tr "gist.revision.file-created" }})</span></span>
{{ else if $file.IsDeleted }}
<span class="flex text-sm ml-2 text-slate-700 dark:text-slate-300">{{ $file.Filename }} <span class="italic text-gray-600 dark:text-gray-400 ml-1">({{ $.locale.Tr "gist.revision.file-deleted" }})</span></span>
{{ else if ne $file.OldFilename "" }}
{{ else if ne $file.OldFilename $file.Filename }}
<span class="flex text-sm ml-2 text-slate-700 dark:text-slate-300">{{ $file.OldFilename }} <span class="italic text-gray-600 dark:text-gray-400 mx-1">{{ $.locale.Tr "gist.revision.file-renamed" }}</span> {{ $file.Filename }}</span>
{{ else }}
<span class="flex text-sm ml-2 text-slate-700 dark:text-slate-300">{{ $file.Filename }}</span>

View File

@@ -5,7 +5,7 @@
<div class="flex ">
<div class="div">
<a href="{{ .c.ExternalUrl }}/{{ .gist.User.Username }}">
<img class="h-10 w-10 rounded-md mr-2 border border-gray-200 dark:border-gray-700 my-1" src="{{ avatarUrl .gist.User .DisableGravatar }}" alt="{{ .gist.User.Username }}'s Avatar">
<img class="h-10 min-w-10 w-10 rounded-md mr-2 border border-gray-200 dark:border-gray-700 my-1" src="{{ avatarUrl .gist.User .DisableGravatar }}" alt="{{ .gist.User.Username }}'s Avatar">
</a>
</div>
<div class="flex-auto">