├── .github
├── FUNDING.yml
└── workflows
│ ├── binary-release.yml
│ ├── dev-docker.yml
│ ├── main-docker.yml
│ └── readme-dockerhub.yml
├── .gitignore
├── .version
├── CHANGELOG.md
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── assets
├── Screenshot 2023-04-02 at 22-27-40 Resource Diary.png
├── Screenshot 2023-04-02 at 22-28-56 Resource Diary.png
└── logo.png
├── build
└── ci
│ ├── build-deb.sh
│ └── build.sh
├── cmd
└── rediary
│ └── main.go
├── configs
├── install.sh
├── rediary.service
└── rediary@.service
├── docker-compose.yml
├── docs
└── BCRYPT.md
├── go.mod
├── go.sum
└── internal
├── auth
├── auth.go
├── cookie.go
├── hash.go
├── models-vars.go
├── session.go
└── timeparse.go
├── check
├── error.go
└── path.go
├── conf
├── getconfig.go
└── map-struct.go
├── db
├── edit.go
├── quote_str.go
└── sqlite.go
├── models
└── models.go
└── web
├── actions-tags.go
├── auth-conf.go
├── chart-counters.go
├── config.go
├── diary.go
├── exec-tpl.go
├── filter.go
├── heatmap.go
├── index.go
├── login.go
├── record.go
├── stat.go
├── templates
├── auth.html
├── config.html
├── diary.html
├── footer.html
├── header.html
├── index.html
├── login.html
└── stat.html
├── var-const.go
└── webgui.go
/.github/FUNDING.yml:
--------------------------------------------------------------------------------
1 | # These are supported funding model platforms
2 |
3 | custom: ['https://boosty.to/aceberg/donate', 'https://aceberg.github.io/MyDocs/sponsor']
4 |
--------------------------------------------------------------------------------
/.github/workflows/binary-release.yml:
--------------------------------------------------------------------------------
1 | name: Binary-release
2 |
3 | on:
4 | workflow_dispatch:
5 | release:
6 | types: [created]
7 |
8 | jobs:
9 | generate:
10 | name: Create release-artifacts
11 | runs-on: ubuntu-latest
12 | steps:
13 | - name: Checkout the repository
14 | uses: actions/checkout@master
15 |
16 | - name: Get version tag from env file
17 | uses: c-py/action-dotenv-to-setenv@v2
18 | with:
19 | env-file: .version
20 |
21 | - uses: actions/setup-go@v4
22 | with:
23 | go-version: 'stable'
24 | - run: go version
25 |
26 | - name: Build and archive
27 | run: build/ci/build.sh ${{ env.VERSION }}
28 |
29 | - name: Build .deb package
30 | run: build/ci/build-deb.sh ${{ env.VERSION }}
31 |
32 | - name: Upload the artifacts
33 | uses: skx/github-action-publish-binaries@master
34 | env:
35 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36 | with:
37 | args: 'rediary-*'
--------------------------------------------------------------------------------
/.github/workflows/dev-docker.yml:
--------------------------------------------------------------------------------
1 | name: Dev-Docker
2 |
3 | on:
4 | workflow_dispatch:
5 |
6 | env:
7 | IMAGE_NAME: rediary
8 | TAGS: dev
9 |
10 |
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - name: Checkout repository
17 | uses: actions/checkout@v3
18 |
19 | - name: Build and Push Docker Image to docker.io
20 | uses: mr-smithers-excellent/docker-build-push@v5
21 | with:
22 | image: ${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}
23 | tags: ${{ env.TAGS }}
24 | registry: docker.io
25 | username: ${{ secrets.DOCKER_USERNAME }}
26 | password: ${{ secrets.DOCKER_PASSWORD }}
--------------------------------------------------------------------------------
/.github/workflows/main-docker.yml:
--------------------------------------------------------------------------------
1 | name: Main-Docker
2 |
3 | on:
4 | workflow_dispatch:
5 | # push:
6 | # branches: [ "main" ]
7 | # paths:
8 | # - 'Dockerfile'
9 | # - 'src/**'
10 |
11 | env:
12 | IMAGE_NAME: rediary
13 |
14 | jobs:
15 | build:
16 | runs-on: ubuntu-latest
17 |
18 | steps:
19 | - name: Checkout repository
20 | uses: actions/checkout@v3
21 |
22 | - name: Get version tag from env file
23 | uses: c-py/action-dotenv-to-setenv@v2
24 | with:
25 | env-file: .version
26 |
27 | - name: Set up QEMU
28 | uses: docker/setup-qemu-action@v2
29 |
30 | - name: Set up Docker Buildx
31 | id: buildx
32 | uses: docker/setup-buildx-action@v2
33 |
34 | - name: Login to GHCR
35 | uses: docker/login-action@v2
36 | with:
37 | registry: ghcr.io
38 | username: ${{ github.actor }}
39 | password: ${{ secrets.GITHUB_TOKEN }}
40 |
41 | - name: Login to Docker Hub
42 | uses: docker/login-action@v2
43 | with:
44 | username: ${{ secrets.DOCKER_USERNAME }}
45 | password: ${{ secrets.DOCKER_PASSWORD }}
46 |
47 | - name: Build and push
48 | uses: docker/build-push-action@v4
49 | with:
50 | context: .
51 | platforms: linux/amd64,linux/arm/v7,linux/arm64
52 | push: true
53 | tags: |
54 | ${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:latest
55 | ${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
56 | ghcr.io/${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:latest
57 | ghcr.io/${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}:${{ env.VERSION }}
--------------------------------------------------------------------------------
/.github/workflows/readme-dockerhub.yml:
--------------------------------------------------------------------------------
1 | name: Readme-DockerHub
2 |
3 | on:
4 | workflow_dispatch:
5 | push:
6 | branches: [ "main" ]
7 | paths:
8 | - 'README.md'
9 |
10 | env:
11 | IMAGE_NAME: rediary
12 |
13 | jobs:
14 | build:
15 | runs-on: ubuntu-latest
16 |
17 | steps:
18 | - name: Checkout repository
19 | uses: actions/checkout@v3
20 |
21 | - name: Sync README.md to DockerHub
22 | uses: ms-jpq/sync-dockerhub-readme@v1
23 | with:
24 | username: ${{ secrets.DOCKER_USERNAME }}
25 | password: ${{ secrets.DOCKER_PASSWORD }}
26 | repository: ${{ secrets.DOCKER_USERNAME }}/${{ env.IMAGE_NAME }}
27 | readme: "./README.md"
28 |
29 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Ignore tmp
2 | tmp/
--------------------------------------------------------------------------------
/.version:
--------------------------------------------------------------------------------
1 | VERSION=1.0.1
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | # Change Log
3 | All notable changes to this project will be documented in this file.
4 |
5 | ## [1.0.1] - 2023-11-04
6 | ### Added
7 | - Adjustable mood max
8 |
9 | ## [1.0.0] - 2023-07-25
10 | ### Added
11 | - Session-Cookie Auth
12 | - Bianry and .deb release
13 |
14 | ## [0.2.0] - 2023-06-04
15 | ### Added
16 | - Notes in diary records
17 |
18 | ## [0.1.5] - 2023-06-04
19 | ### Added
20 | - Background color: light or dark
21 | - Clear table button warning
22 | - Clickable calendar
23 |
24 | ## [0.1.4] - 2023-04-02
25 | ### Added
26 | - Filter by tag
27 |
28 | ## [0.1.3] - 2023-03-27
29 | ### Added
30 | - Tag cloud
31 |
32 | ## [0.1.2] - 2023-03-21
33 | ### Added
34 | - JS HeatMap
35 | - Plus and Minus colors Config
36 |
37 | ## [0.1.1] - 2023-03-17
38 | ### Added
39 | - Github Actions
40 |
--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:alpine AS builder
2 |
3 | RUN apk add build-base
4 | COPY cmd /src/cmd
5 | COPY internal /src/internal
6 | COPY go.mod /src/
7 | COPY go.sum /src/
8 | RUN cd /src/cmd/rediary/ && CGO_ENABLED=0 go build -o /rediary .
9 |
10 |
11 | FROM scratch
12 |
13 | WORKDIR /data/rediary
14 | WORKDIR /app
15 |
16 | COPY --from=builder /rediary /app/
17 |
18 | ENTRYPOINT ["./rediary"]
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Andrew Erlikh
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | mod:
2 | rm go.mod || true && \
3 | rm go.sum || true && \
4 | go mod init github.com/aceberg/rediary && \
5 | go mod tidy
6 |
7 | run:
8 | cd cmd/rediary/ && \
9 | go run .
10 |
11 | fmt:
12 | go fmt ./...
13 |
14 | lint:
15 | golangci-lint run
16 | golint ./...
17 |
18 | check: fmt lint
19 |
20 | go-build:
21 | cd cmd/rediary/ && \
22 | CGO_ENABLED=0 go build -o ../../tmp/rediary .
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://github.com/aceberg/rediary/actions/workflows/main-docker.yml)
2 | [](https://goreportcard.com/report/github.com/aceberg/rediary)
3 | [](https://codeclimate.com/github/aceberg/rediary/maintainability)
4 | 
5 |
6 |
7 |
8 | Resource Diary
9 |
10 | Emotional resource diary
11 |
12 | - [Quick start](https://github.com/aceberg/rediary#quick-start)
13 | - [Usage](https://github.com/aceberg/rediary#usage)
14 | - [Config](https://github.com/aceberg/rediary#config)
15 | - [Options](https://github.com/aceberg/rediary#options)
16 | - [Thanks](https://github.com/aceberg/rediary#thanks)
17 |
18 |
19 | 
20 |
21 | ## Quick start
22 |
23 | ```sh
24 | docker run --name rediary \
25 | -e "TZ=Asia/Novosibirsk" \
26 | -v ~/.dockerdata/rediary:/data/rediary \
27 | -p 8847:8847 \
28 | aceberg/rediary
29 | ```
30 | Or use [docker-compose.yml](docker-compose.yml)
31 |
32 | ## Usage
33 | Add your own Tags and Actions on Config page.
34 |
35 | ## Config
36 |
37 |
38 | Configuration can be done through config file or environment variables
39 |
40 | | Variable | Description | Default |
41 | | -------- | ----------- | ------- |
42 | | DB | Path to Database | /data/rediary/sqlite.db |
43 | | HOST | Listen address | 0.0.0.0 |
44 | | PORT | Port for web GUI | 8847 |
45 | | THEME | Any theme name from https://bootswatch.com in lowcase | minty |
46 | | BGCOLOR | Background color: light or dark | light |
47 | | MOODMAX | Length of Minus and Plus scales | 5 |
48 | | TZ | Set your timezone for correct time | "" |
49 | | AUTH | Enable Session-Cookie authentication | false |
50 | | AUTH_USER | Username | "" |
51 | | AUTH_PASSWORD | Encrypted password (bcrypt). [How to encrypt password with bcrypt?](docs/BCRYPT.md) | "" |
52 | | AUTH_EXPIRE | Session expiration time. A number and suffix: **m, h, d** or **M**. | 7d |
53 |
54 | ## Options
55 |
56 | | Key | Description | Default |
57 | | -------- | ----------- | ------- |
58 | | -c | Path to config file | /data/rediary/config.yaml |
59 |
60 | ## Thanks
61 | - All go packages listed in [dependencies](https://github.com/aceberg/rediary/network/dependencies)
62 | - [Bootstrap](https://getbootstrap.com/)
63 | - Themes: [Free themes for Bootstrap](https://bootswatch.com)
64 | - Favicon and logo: [Flaticon](https://www.flaticon.com/icons/)
--------------------------------------------------------------------------------
/assets/Screenshot 2023-04-02 at 22-27-40 Resource Diary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aceberg/rediary/ae2eaf70a7712effd66eca52e9667239449d9e97/assets/Screenshot 2023-04-02 at 22-27-40 Resource Diary.png
--------------------------------------------------------------------------------
/assets/Screenshot 2023-04-02 at 22-28-56 Resource Diary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aceberg/rediary/ae2eaf70a7712effd66eca52e9667239449d9e97/assets/Screenshot 2023-04-02 at 22-28-56 Resource Diary.png
--------------------------------------------------------------------------------
/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aceberg/rediary/ae2eaf70a7712effd66eca52e9667239449d9e97/assets/logo.png
--------------------------------------------------------------------------------
/build/ci/build-deb.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | PKGNAME=rediary
4 | PKGDIR=$PKGNAME-$1-0_all
5 |
6 | umask 0022
7 |
8 | mkdir -p $PKGDIR/usr/bin
9 | mkdir -p $PKGDIR/lib/systemd/system
10 |
11 | cp configs/$PKGNAME.service $PKGDIR/lib/systemd/system/
12 | cp configs/$PKGNAME@.service $PKGDIR/lib/systemd/system/
13 |
14 | cp $PKGNAME $PKGDIR/usr/bin/
15 |
16 | mkdir -p $PKGDIR/DEBIAN
17 |
18 | echo "Package: $PKGNAME
19 | Version: $1
20 | Section: utils
21 | Priority: optional
22 | Architecture: all
23 | Maintainer: aceberg
24 | Description: Emotional resource diary
25 | " > $PKGDIR/DEBIAN/control
26 |
27 | echo "
28 | systemctl daemon-reload
29 | " > $PKGDIR/DEBIAN/postinst
30 |
31 | chmod 775 $PKGDIR/DEBIAN/postinst
32 |
33 | dpkg-deb --build --root-owner-group $PKGDIR
34 |
35 | rm -rf $PKGDIR
--------------------------------------------------------------------------------
/build/ci/build.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | PKGNAME=rediary
4 | PKGDIR=/opt/$PKGNAME
5 |
6 | cd cmd/$PKGNAME/ && CGO_ENABLED=0 go build -o ../../$PKGNAME .
7 | cd ../../
8 |
9 | umask 0022
10 |
11 | mkdir -p $PKGDIR
12 | cp $PKGNAME $PKGDIR/
13 | cp configs/$PKGNAME.service $PKGDIR/
14 | cp configs/$PKGNAME@.service $PKGDIR/
15 | cp configs/install.sh $PKGDIR/
16 |
17 | cd /opt
18 | tar cvzf $PKGNAME-$1.tar.gz $PKGNAME
19 | cd -
20 | cp /opt/$PKGNAME-$1.tar.gz .
--------------------------------------------------------------------------------
/cmd/rediary/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "flag"
5 |
6 | _ "time/tzdata"
7 |
8 | "github.com/aceberg/rediary/internal/check"
9 | "github.com/aceberg/rediary/internal/models"
10 | "github.com/aceberg/rediary/internal/web"
11 | )
12 |
13 | const confPath = "/data/rediary/config.yaml"
14 |
15 | func main() {
16 | var conf models.Conf
17 |
18 | confPtr := flag.String("c", confPath, "Path to config yaml file")
19 | flag.Parse()
20 |
21 | conf.ConfPath = *confPtr
22 |
23 | check.Path(conf.ConfPath)
24 |
25 | web.Gui(conf)
26 | }
27 |
--------------------------------------------------------------------------------
/configs/install.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | cp rediary /usr/bin/
4 | cp rediary.service /lib/systemd/system/
5 | cp rediary@.service /lib/systemd/system/
--------------------------------------------------------------------------------
/configs/rediary.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=rediary
3 | Documentation=https://github.com/aceberg/rediary
4 | After=network-online.target
5 | Wants=network-online.target
6 |
7 | [Service]
8 | ExecStart=/usr/bin/rediary -c /etc/rediary/config.yaml
9 | Restart=on-failure
10 |
11 | [Install]
12 | WantedBy=multi-user.target
--------------------------------------------------------------------------------
/configs/rediary@.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=rediary
3 | Documentation=https://github.com/aceberg/rediary
4 | After=network-online.target
5 | Wants=network-online.target
6 |
7 | [Service]
8 | User=%i
9 | ExecStart=/usr/bin/rediary -c /home/%i/.config/rediary/config.yaml
10 | Restart=on-failure
11 |
12 | [Install]
13 | WantedBy=multi-user.target
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: "3"
2 | services:
3 | rediary:
4 | image: aceberg/rediary
5 | restart: unless-stopped
6 | ports:
7 | - 8847:8847
8 | volumes:
9 | - ~/.dockerdata/rediary:/data/rediary # app data (set your own path instead of dockerdata)
10 | environment:
11 | TZ: Asia/Novosibirsk # required: needs your TZ for correct time
12 | DB: "/data/rediary/sqlite.db" # optional, default: /data/rediary/sqlite.db
13 | HOST: "0.0.0.0" # optional, default: 0.0.0.0
14 | PORT: "8847" # optional, default: 8847
15 | THEME: "minty" # optional, default: minty
--------------------------------------------------------------------------------
/docs/BCRYPT.md:
--------------------------------------------------------------------------------
1 | # How to encrypt password with bcrypt?
2 |
3 | It is not safe to store password unencrypted, so this app uses `bcrypt` encryption. There are several ways to encrypt your password.
4 |
5 | ## 1. Set password through web GUI
6 | Then the app will encrypt it for you.
7 |
8 | ## 2. Encrypt password yourself
9 | On Linux encryption can be done with `htpasswd` command:
10 | ```sh
11 | htpasswd -nbBC 10 USER YourSecretPassword | sed 's/USER://'
12 | ```
13 |
14 | ## 3. Encrypt password online
15 | There are online tools for `bcrypt` encryption.
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/aceberg/rediary
2 |
3 | go 1.21.2
4 |
5 | require (
6 | github.com/google/uuid v1.4.0
7 | github.com/jmoiron/sqlx v1.3.5
8 | github.com/spf13/viper v1.17.0
9 | golang.org/x/crypto v0.14.0
10 | modernc.org/sqlite v1.27.0
11 | )
12 |
13 | require (
14 | github.com/dustin/go-humanize v1.0.1 // indirect
15 | github.com/fsnotify/fsnotify v1.6.0 // indirect
16 | github.com/hashicorp/hcl v1.0.0 // indirect
17 | github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
18 | github.com/magiconair/properties v1.8.7 // indirect
19 | github.com/mattn/go-isatty v0.0.17 // indirect
20 | github.com/mitchellh/mapstructure v1.5.0 // indirect
21 | github.com/pelletier/go-toml/v2 v2.1.0 // indirect
22 | github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
23 | github.com/sagikazarmark/locafero v0.3.0 // indirect
24 | github.com/sagikazarmark/slog-shim v0.1.0 // indirect
25 | github.com/sourcegraph/conc v0.3.0 // indirect
26 | github.com/spf13/afero v1.10.0 // indirect
27 | github.com/spf13/cast v1.5.1 // indirect
28 | github.com/spf13/pflag v1.0.5 // indirect
29 | github.com/subosito/gotenv v1.6.0 // indirect
30 | go.uber.org/atomic v1.9.0 // indirect
31 | go.uber.org/multierr v1.9.0 // indirect
32 | golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
33 | golang.org/x/mod v0.12.0 // indirect
34 | golang.org/x/sys v0.13.0 // indirect
35 | golang.org/x/text v0.13.0 // indirect
36 | golang.org/x/tools v0.13.0 // indirect
37 | gopkg.in/ini.v1 v1.67.0 // indirect
38 | gopkg.in/yaml.v3 v3.0.1 // indirect
39 | lukechampine.com/uint128 v1.2.0 // indirect
40 | modernc.org/cc/v3 v3.40.0 // indirect
41 | modernc.org/ccgo/v3 v3.16.13 // indirect
42 | modernc.org/libc v1.29.0 // indirect
43 | modernc.org/mathutil v1.6.0 // indirect
44 | modernc.org/memory v1.7.2 // indirect
45 | modernc.org/opt v0.1.3 // indirect
46 | modernc.org/strutil v1.1.3 // indirect
47 | modernc.org/token v1.0.1 // indirect
48 | )
49 |
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
2 | cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
3 | cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
4 | cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
5 | cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
6 | cloud.google.com/go v0.44.3/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
7 | cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
8 | cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
9 | cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
10 | cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
11 | cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
12 | cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
13 | cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
14 | cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
15 | cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
16 | cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
17 | cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
18 | cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
19 | cloud.google.com/go v0.75.0/go.mod h1:VGuuCn7PG0dwsd5XPVm2Mm3wlh3EL55/79EKB6hlPTY=
20 | cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
21 | cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
22 | cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
23 | cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
24 | cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
25 | cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
26 | cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
27 | cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
28 | cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
29 | cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
30 | cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
31 | cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
32 | cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
33 | cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
34 | cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
35 | cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
36 | cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
37 | cloud.google.com/go/storage v1.14.0/go.mod h1:GrKmX003DSIwi9o29oFT7YDnHYwZoctc3fOKtUw0Xmo=
38 | dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
39 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
40 | github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
41 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
42 | github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
43 | github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
44 | github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
45 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
46 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
47 | github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
48 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
49 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
50 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
51 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
52 | github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
53 | github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
54 | github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
55 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
56 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
57 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
58 | github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
59 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
60 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
61 | github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
62 | github.com/frankban/quicktest v1.14.4/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
63 | github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
64 | github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
65 | github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
66 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
67 | github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
68 | github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
69 | github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
70 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
71 | github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
72 | github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
73 | github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
74 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
75 | github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
76 | github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
77 | github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
78 | github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
79 | github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
80 | github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
81 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
82 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
83 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
84 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
85 | github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
86 | github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
87 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
88 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
89 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
90 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
91 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
92 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
93 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
94 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
95 | github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
96 | github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
97 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
98 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
99 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
100 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
101 | github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
102 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
103 | github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
104 | github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
105 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
106 | github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
107 | github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
108 | github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
109 | github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
110 | github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
111 | github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
112 | github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
113 | github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
114 | github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
115 | github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
116 | github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
117 | github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
118 | github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
119 | github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
120 | github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
121 | github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
122 | github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
123 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
124 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
125 | github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
126 | github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
127 | github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
128 | github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
129 | github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
130 | github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
131 | github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
132 | github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
133 | github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
134 | github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
135 | github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
136 | github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
137 | github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
138 | github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
139 | github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
140 | github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs=
141 | github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
142 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
143 | github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
144 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
145 | github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
146 | github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
147 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
148 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
149 | github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
150 | github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
151 | github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
152 | github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
153 | github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
154 | github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
155 | github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
156 | github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
157 | github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
158 | github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
159 | github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
160 | github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
161 | github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
162 | github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
163 | github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
164 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
165 | github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
166 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
167 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
168 | github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
169 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
170 | github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
171 | github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
172 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
173 | github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
174 | github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
175 | github.com/sagikazarmark/locafero v0.3.0 h1:zT7VEGWC2DTflmccN/5T1etyKvxSxpHsjb9cJvm4SvQ=
176 | github.com/sagikazarmark/locafero v0.3.0/go.mod h1:w+v7UsPNFwzF1cHuOajOOzoq4U7v/ig1mpRjqV+Bu1U=
177 | github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
178 | github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
179 | github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
180 | github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
181 | github.com/spf13/afero v1.10.0 h1:EaGW2JJh15aKOejeuJ+wpFSHnbd7GE6Wvp3TsNhb6LY=
182 | github.com/spf13/afero v1.10.0/go.mod h1:UBogFpq8E9Hx+xc5CNTTEpTnuHVmXDwZcZcE1eb/UhQ=
183 | github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
184 | github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
185 | github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
186 | github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
187 | github.com/spf13/viper v1.17.0 h1:I5txKw7MJasPL/BrfkbA0Jyo/oELqVmux4pR/UxOMfI=
188 | github.com/spf13/viper v1.17.0/go.mod h1:BmMMMLQXSbcHK6KAOiFLz0l5JHrU89OdIRHvsk0+yVI=
189 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
190 | github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
191 | github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
192 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
193 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
194 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
195 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
196 | github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
197 | github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
198 | github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
199 | github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
200 | github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
201 | github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
202 | github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
203 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
204 | github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
205 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
206 | go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
207 | go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
208 | go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
209 | go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
210 | go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
211 | go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
212 | go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
213 | go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
214 | go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
215 | go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
216 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
217 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
218 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
219 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
220 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
221 | golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
222 | golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
223 | golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
224 | golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
225 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
226 | golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
227 | golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
228 | golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
229 | golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
230 | golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
231 | golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
232 | golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
233 | golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
234 | golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
235 | golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
236 | golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
237 | golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
238 | golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
239 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
240 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
241 | golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
242 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
243 | golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
244 | golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
245 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
246 | golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
247 | golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
248 | golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
249 | golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
250 | golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
251 | golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
252 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
253 | golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
254 | golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
255 | golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
256 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
257 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
258 | golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
259 | golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
260 | golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
261 | golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
262 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
263 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
264 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
265 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
266 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
267 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
268 | golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
269 | golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
270 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
271 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
272 | golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
273 | golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
274 | golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
275 | golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
276 | golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
277 | golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
278 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
279 | golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
280 | golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
281 | golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
282 | golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
283 | golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
284 | golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
285 | golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
286 | golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
287 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
288 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
289 | golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
290 | golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
291 | golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
292 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
293 | golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
294 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
295 | golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
296 | golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
297 | golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
298 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
299 | golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
300 | golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
301 | golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
302 | golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
303 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
304 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
305 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
306 | golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
307 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
308 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
309 | golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
310 | golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
311 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
312 | golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
313 | golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
314 | golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
315 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
316 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
317 | golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
318 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
319 | golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
320 | golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
321 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
322 | golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
323 | golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
324 | golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
325 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
326 | golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
327 | golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
328 | golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
329 | golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
330 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
331 | golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
332 | golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
333 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
334 | golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
335 | golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
336 | golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
337 | golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
338 | golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
339 | golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
340 | golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
341 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
342 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
343 | golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
344 | golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
345 | golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
346 | golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
347 | golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
348 | golang.org/x/sys v0.0.0-20210423185535-09eb48e85fd7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
349 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
350 | golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
351 | golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
352 | golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
353 | golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
354 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
355 | golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
356 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
357 | golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
358 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
359 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
360 | golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
361 | golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
362 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
363 | golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
364 | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
365 | golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
366 | golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
367 | golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
368 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
369 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
370 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
371 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
372 | golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
373 | golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
374 | golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
375 | golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
376 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
377 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
378 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
379 | golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
380 | golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
381 | golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
382 | golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
383 | golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
384 | golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
385 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
386 | golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
387 | golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
388 | golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
389 | golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
390 | golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
391 | golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
392 | golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
393 | golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
394 | golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
395 | golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
396 | golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
397 | golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
398 | golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
399 | golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
400 | golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
401 | golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
402 | golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
403 | golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
404 | golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
405 | golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
406 | golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
407 | golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
408 | golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
409 | golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
410 | golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
411 | golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
412 | golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
413 | golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
414 | golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
415 | golang.org/x/tools v0.13.0 h1:Iey4qkscZuv0VvIt8E0neZjtPVQFSc870HQ448QgEmQ=
416 | golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
417 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
418 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
419 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
420 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
421 | google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
422 | google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
423 | google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
424 | google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
425 | google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
426 | google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
427 | google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
428 | google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
429 | google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
430 | google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
431 | google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
432 | google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
433 | google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
434 | google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
435 | google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
436 | google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
437 | google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
438 | google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
439 | google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
440 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
441 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
442 | google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
443 | google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
444 | google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
445 | google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
446 | google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
447 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
448 | google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
449 | google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
450 | google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
451 | google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
452 | google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
453 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
454 | google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
455 | google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
456 | google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
457 | google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
458 | google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
459 | google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
460 | google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
461 | google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
462 | google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
463 | google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
464 | google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
465 | google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
466 | google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
467 | google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
468 | google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
469 | google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
470 | google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
471 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
472 | google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
473 | google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
474 | google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
475 | google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
476 | google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
477 | google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
478 | google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
479 | google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
480 | google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
481 | google.golang.org/genproto v0.0.0-20210108203827-ffc7fda8c3d7/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
482 | google.golang.org/genproto v0.0.0-20210226172003-ab064af71705/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
483 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
484 | google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
485 | google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
486 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
487 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
488 | google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
489 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
490 | google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
491 | google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
492 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
493 | google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
494 | google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
495 | google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
496 | google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
497 | google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
498 | google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
499 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
500 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
501 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
502 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
503 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
504 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
505 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
506 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
507 | google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
508 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
509 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
510 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
511 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
512 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
513 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
514 | gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
515 | gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
516 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
517 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
518 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
519 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
520 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
521 | honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
522 | honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
523 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
524 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
525 | honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
526 | honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
527 | lukechampine.com/uint128 v1.2.0 h1:mBi/5l91vocEN8otkC5bDLhi2KdCticRiwbdB0O+rjI=
528 | lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
529 | modernc.org/cc/v3 v3.40.0 h1:P3g79IUS/93SYhtoeaHW+kRCIrYaxJ27MFPv+7kaTOw=
530 | modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
531 | modernc.org/ccgo/v3 v3.16.13 h1:Mkgdzl46i5F/CNR/Kj80Ri59hC8TKAhZrYSaqvkwzUw=
532 | modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
533 | modernc.org/ccorpus v1.11.6 h1:J16RXiiqiCgua6+ZvQot4yUuUy8zxgqbqEEUuGPlISk=
534 | modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
535 | modernc.org/httpfs v1.0.6 h1:AAgIpFZRXuYnkjftxTAZwMIiwEqAfk8aVB2/oA6nAeM=
536 | modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
537 | modernc.org/libc v1.29.0 h1:tTFRFq69YKCF2QyGNuRUQxKBm1uZZLubf6Cjh/pVHXs=
538 | modernc.org/libc v1.29.0/go.mod h1:DaG/4Q3LRRdqpiLyP0C2m1B8ZMGkQ+cCgOIjEtQlYhQ=
539 | modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
540 | modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
541 | modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E=
542 | modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E=
543 | modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
544 | modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
545 | modernc.org/sqlite v1.27.0 h1:MpKAHoyYB7xqcwnUwkuD+npwEa0fojF0B5QRbN+auJ8=
546 | modernc.org/sqlite v1.27.0/go.mod h1:Qxpazz0zH8Z1xCFyi5GSL3FzbtZ3fvbjmywNogldEW0=
547 | modernc.org/strutil v1.1.3 h1:fNMm+oJklMGYfU9Ylcywl0CO5O6nTfaowNsh2wpPjzY=
548 | modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
549 | modernc.org/tcl v1.15.2 h1:C4ybAYCGJw968e+Me18oW55kD/FexcHbqH2xak1ROSY=
550 | modernc.org/tcl v1.15.2/go.mod h1:3+k/ZaEbKrC8ePv8zJWPtBSW0V7Gg9g8rkmhI1Kfs3c=
551 | modernc.org/token v1.0.1 h1:A3qvTqOwexpfZZeyI0FeGPDlSWX5pjZu9hF4lU+EKWg=
552 | modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
553 | modernc.org/z v1.7.3 h1:zDJf6iHjrnB+WRD88stbXokugjyc0/pB91ri1gO6LZY=
554 | modernc.org/z v1.7.3/go.mod h1:Ipv4tsdxZRbQyLq9Q1M6gdbkxYzdlrciF2Hi/lS7nWE=
555 | rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
556 | rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
557 | rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
558 |
--------------------------------------------------------------------------------
/internal/auth/auth.go:
--------------------------------------------------------------------------------
1 | package auth
2 |
3 | import (
4 | "net/http"
5 | "time"
6 | )
7 |
8 | // Auth - main auth func
9 | func Auth(next http.HandlerFunc, conf *Conf) http.HandlerFunc {
10 | return func(w http.ResponseWriter, r *http.Request) {
11 |
12 | if !conf.Auth || conf.User == "" || conf.Password == "" {
13 | next.ServeHTTP(w, r)
14 | return
15 | }
16 |
17 | sessionToken := getTokenFromCookie(r)
18 |
19 | userSession, exists := allSessions[sessionToken]
20 | if !exists {
21 | http.Redirect(w, r, "/login/", 302)
22 | return
23 | }
24 | if userSession.Before(time.Now()) {
25 | delete(allSessions, sessionToken)
26 | http.Redirect(w, r, "/login/", 302)
27 | return
28 | }
29 |
30 | userSession = time.Now().Add(conf.Expire)
31 | allSessions[sessionToken] = userSession
32 |
33 | next.ServeHTTP(w, r)
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/internal/auth/cookie.go:
--------------------------------------------------------------------------------
1 | package auth
2 |
3 | import (
4 | "net/http"
5 | )
6 |
7 | func setTokenCookie(w http.ResponseWriter, token string) {
8 |
9 | cookie := http.Cookie{Name: cookieName, Value: token, Path: "/"}
10 | http.SetCookie(w, &cookie)
11 | }
12 |
13 | func getTokenFromCookie(r *http.Request) string {
14 |
15 | cookie, err := r.Cookie(cookieName)
16 | if err != nil {
17 |
18 | return ""
19 | }
20 |
21 | return cookie.Value
22 | }
23 |
--------------------------------------------------------------------------------
/internal/auth/hash.go:
--------------------------------------------------------------------------------
1 | package auth
2 |
3 | import (
4 | "log"
5 |
6 | "golang.org/x/crypto/bcrypt"
7 | )
8 |
9 | // HashPassword - generate hash from password
10 | func HashPassword(pw string) string {
11 |
12 | hashed, err := bcrypt.GenerateFromPassword([]byte(pw), 10)
13 | if err != nil {
14 | log.Println("PASSWORD ERROR:", err)
15 | return ""
16 | }
17 |
18 | return string(hashed)
19 | }
20 |
21 | // MatchPasswords - check if password and hash matches
22 | func MatchPasswords(hash, pw string) bool {
23 |
24 | err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(pw))
25 |
26 | return err == nil
27 | }
28 |
--------------------------------------------------------------------------------
/internal/auth/models-vars.go:
--------------------------------------------------------------------------------
1 | package auth
2 |
3 | import (
4 | "time"
5 | )
6 |
7 | // Conf - auth config
8 | type Conf struct {
9 | Auth bool
10 | User string
11 | Password string
12 | ExpStr string
13 | Expire time.Duration
14 | }
15 |
16 | var allSessions = map[string]time.Time{}
17 |
18 | var cookieName = "rediary_session_token"
19 |
--------------------------------------------------------------------------------
/internal/auth/session.go:
--------------------------------------------------------------------------------
1 | package auth
2 |
3 | import (
4 | "net/http"
5 | "time"
6 |
7 | "github.com/google/uuid"
8 | )
9 |
10 | // StartSession for new login
11 | func StartSession(w http.ResponseWriter, r *http.Request) {
12 |
13 | sessionToken := uuid.NewString()
14 |
15 | allSessions[sessionToken] = time.Now().Add(60 * time.Second)
16 |
17 | setTokenCookie(w, sessionToken)
18 |
19 | http.Redirect(w, r, "/", 302)
20 |
21 | }
22 |
23 | // LogOut - log out
24 | func LogOut(w http.ResponseWriter, r *http.Request) {
25 |
26 | sessionToken := getTokenFromCookie(r)
27 |
28 | delete(allSessions, sessionToken)
29 |
30 | setTokenCookie(w, "")
31 |
32 | http.Redirect(w, r, "/", 302)
33 | }
34 |
--------------------------------------------------------------------------------
/internal/auth/timeparse.go:
--------------------------------------------------------------------------------
1 | package auth
2 |
3 | import (
4 | "errors"
5 | "time"
6 | )
7 |
8 | func timeParse(timeout string) (time.Duration, error) {
9 | var err error
10 | var t time.Duration
11 |
12 | length := len(timeout)
13 | if length > 1 {
14 | suffix := timeout[length-1]
15 |
16 | switch string(suffix) {
17 | case "h":
18 | t, err = time.ParseDuration(timeout)
19 | case "m":
20 | t, err = time.ParseDuration(timeout)
21 | case "d": //day
22 | t, err = time.ParseDuration(timeout[:length-1] + "h")
23 | t = 24 * t
24 | case "M": // month
25 | t, err = time.ParseDuration(timeout[:length-1] + "h")
26 | t = 730 * t
27 | default:
28 | err = errors.New("ERROR: TimeParse: wrong time format")
29 | }
30 | } else {
31 | err = errors.New("ERROR: TimeParse: wrong time format")
32 | }
33 |
34 | return t, err
35 | }
36 |
37 | // ToTime - converts string (example: 3d) to time.Duration
38 | func ToTime(s string) time.Duration {
39 |
40 | t, err := timeParse(s)
41 | if err != nil {
42 | t, _ = timeParse("7d")
43 | }
44 |
45 | return t
46 | }
47 |
--------------------------------------------------------------------------------
/internal/check/error.go:
--------------------------------------------------------------------------------
1 | package check
2 |
3 | import (
4 | "log"
5 | )
6 |
7 | // IfError prints error, if it is not nil
8 | func IfError(err error) bool {
9 | if err == nil {
10 | return false
11 | }
12 |
13 | log.Println("ERROR:", err)
14 | return true
15 | }
16 |
--------------------------------------------------------------------------------
/internal/check/path.go:
--------------------------------------------------------------------------------
1 | package check
2 |
3 | import (
4 | "os"
5 | "path/filepath"
6 | )
7 |
8 | // Path - create path if not exist
9 | func Path(path string) {
10 |
11 | _, err := os.Stat(path)
12 |
13 | if path != "" && err != nil {
14 |
15 | dir := filepath.Dir(path)
16 |
17 | err = os.MkdirAll(dir, os.ModePerm)
18 | IfError(err)
19 |
20 | _, err = os.Create(path)
21 | IfError(err)
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/internal/conf/getconfig.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | import (
4 | "github.com/spf13/viper"
5 |
6 | "github.com/aceberg/rediary/internal/auth"
7 | "github.com/aceberg/rediary/internal/check"
8 | "github.com/aceberg/rediary/internal/models"
9 | )
10 |
11 | // Get - read config from file or env
12 | func Get(path string) (models.Conf, auth.Conf) {
13 | var config models.Conf
14 | var actions []models.Action
15 | var tags []models.TagType
16 |
17 | var authConf auth.Conf
18 |
19 | viper.SetDefault("DB", "/data/rediary/sqlite.db")
20 | viper.SetDefault("HOST", "0.0.0.0")
21 | viper.SetDefault("PORT", "8847")
22 | viper.SetDefault("THEME", "minty")
23 | viper.SetDefault("BGCOLOR", "light")
24 | viper.SetDefault("COLORPLUS", "#ff3300")
25 | viper.SetDefault("COLORMINUS", "#00aeff")
26 | viper.SetDefault("MOODMAX", "5")
27 | viper.SetDefault("AUTH_USER", "")
28 | viper.SetDefault("AUTH_PASSWORD", "")
29 | viper.SetDefault("AUTH_EXPIRE", "7d")
30 |
31 | viper.SetConfigFile(path)
32 | viper.SetConfigType("yaml")
33 | err := viper.ReadInConfig()
34 | check.IfError(err)
35 |
36 | viper.AutomaticEnv() // Get ENVIRONMENT variables
37 |
38 | config.DB, _ = viper.Get("DB").(string)
39 | config.Host, _ = viper.Get("HOST").(string)
40 | config.Port, _ = viper.Get("PORT").(string)
41 | config.Theme, _ = viper.Get("THEME").(string)
42 | config.BgColor, _ = viper.Get("BGCOLOR").(string)
43 | config.ColorPlus, _ = viper.Get("COLORPLUS").(string)
44 | config.ColorMinus, _ = viper.Get("COLORMINUS").(string)
45 | config.MoodMax, _ = viper.Get("MOODMAX").(string)
46 | authConf.Auth = viper.GetBool("AUTH")
47 | authConf.User, _ = viper.Get("AUTH_USER").(string)
48 | authConf.Password, _ = viper.Get("AUTH_PASSWORD").(string)
49 | authConf.ExpStr, _ = viper.Get("AUTH_EXPIRE").(string)
50 |
51 | authConf.Expire = auth.ToTime(authConf.ExpStr)
52 | config.Auth = authConf.Auth
53 |
54 | err = viper.UnmarshalKey("actions", &actions)
55 | check.IfError(err)
56 | config.Actions = actions
57 |
58 | err = viper.UnmarshalKey("tags", &tags)
59 | check.IfError(err)
60 | config.TagMap = structToMap(tags)
61 |
62 | return config, authConf
63 | }
64 |
65 | // Write - write config to file
66 | func Write(config models.Conf, authConf auth.Conf) {
67 |
68 | viper.SetConfigFile(config.ConfPath)
69 | viper.SetConfigType("yaml")
70 |
71 | viper.Set("db", config.DB)
72 | viper.Set("host", config.Host)
73 | viper.Set("port", config.Port)
74 | viper.Set("theme", config.Theme)
75 | viper.Set("BGCOLOR", config.BgColor)
76 | viper.Set("colorminus", config.ColorMinus)
77 | viper.Set("colorplus", config.ColorPlus)
78 | viper.Set("moodmax", config.MoodMax)
79 | viper.Set("actions", config.Actions)
80 | viper.Set("tags", mapToStruct(config.TagMap))
81 |
82 | viper.Set("auth", authConf.Auth)
83 | viper.Set("auth_user", authConf.User)
84 | viper.Set("auth_password", authConf.Password)
85 | viper.Set("auth_expire", authConf.ExpStr)
86 |
87 | err := viper.WriteConfig()
88 | check.IfError(err)
89 | }
90 |
--------------------------------------------------------------------------------
/internal/conf/map-struct.go:
--------------------------------------------------------------------------------
1 | package conf
2 |
3 | import (
4 | "github.com/aceberg/rediary/internal/models"
5 | )
6 |
7 | func structToMap(tagStruct []models.TagType) map[string]string {
8 |
9 | tagMap := make(map[string]string)
10 |
11 | for _, tag := range tagStruct {
12 |
13 | tagMap[tag.Name] = tag.Color
14 | }
15 |
16 | return tagMap
17 | }
18 |
19 | func mapToStruct(tagMap map[string]string) []models.TagType {
20 |
21 | var tagStruct []models.TagType
22 | var tag models.TagType
23 |
24 | for key, value := range tagMap {
25 | tag.Name = key
26 | tag.Color = value
27 | tagStruct = append(tagStruct, tag)
28 | }
29 |
30 | return tagStruct
31 | }
32 |
--------------------------------------------------------------------------------
/internal/db/edit.go:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/aceberg/rediary/internal/check"
7 | "github.com/aceberg/rediary/internal/models"
8 | )
9 |
10 | // Create - create table if not exists
11 | func Create(path string) {
12 |
13 | sqlStatement := `CREATE TABLE IF NOT EXISTS records (
14 | "ID" INTEGER PRIMARY KEY,
15 | "DATE" TEXT,
16 | "TAG" TEXT,
17 | "NAME" TEXT,
18 | "COLOR" TEXT,
19 | "NOTE" TEXT,
20 | "MINUS" TEXT,
21 | "PLUS" TEXT,
22 | "TOTAL" TEXT
23 | );`
24 | err := exec(path, sqlStatement)
25 | check.IfError(err)
26 | }
27 |
28 | // Insert - insert one rec into DB
29 | func Insert(path string, rec models.Record) {
30 |
31 | sqlStatement := `INSERT INTO records (DATE, TAG, NAME, COLOR, NOTE, MINUS, PLUS, TOTAL)
32 | VALUES ('%s','%s','%s','%s','%s','%d','%d','%d');`
33 |
34 | rec.Name = quoteStr(rec.Name)
35 | rec.Tag = quoteStr(rec.Tag)
36 |
37 | sqlStatement = fmt.Sprintf(sqlStatement, rec.Date, rec.Tag, rec.Name, rec.Color, rec.Note, rec.Minus, rec.Plus, rec.Total)
38 |
39 | err := exec(path, sqlStatement)
40 | check.IfError(err)
41 | }
42 |
43 | // Delete - delete one record
44 | func Delete(path string, id int) {
45 |
46 | sqlStatement := `DELETE FROM records WHERE ID='%d';`
47 |
48 | sqlStatement = fmt.Sprintf(sqlStatement, id)
49 |
50 | err := exec(path, sqlStatement)
51 | check.IfError(err)
52 | }
53 |
54 | // Clear - delete all records from table
55 | func Clear(path string) {
56 | sqlStatement := `DELETE FROM records;`
57 | err := exec(path, sqlStatement)
58 | check.IfError(err)
59 | }
60 |
61 | // Migrate - add column to table
62 | func Migrate(path string) {
63 |
64 | sqlStatement := `SELECT 1 FROM records WHERE NOTE;`
65 | err := exec(path, sqlStatement)
66 |
67 | if err != nil {
68 |
69 | sqlStatement = `ALTER TABLE records ADD NOTE TEXT DEFAULT "";`
70 | err = exec(path, sqlStatement)
71 | check.IfError(err)
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/internal/db/quote_str.go:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import "strings"
4 |
5 | func quoteStr(str string) string {
6 | return strings.ReplaceAll(str, "'", "''")
7 | }
8 |
--------------------------------------------------------------------------------
/internal/db/sqlite.go:
--------------------------------------------------------------------------------
1 | package db
2 |
3 | import (
4 | "github.com/jmoiron/sqlx"
5 |
6 | // Import module for SQLite DB
7 | _ "modernc.org/sqlite"
8 |
9 | "github.com/aceberg/rediary/internal/check"
10 | "github.com/aceberg/rediary/internal/models"
11 | )
12 |
13 | func connect(path string) *sqlx.DB {
14 | dbx, err := sqlx.Connect("sqlite", path)
15 | check.IfError(err)
16 |
17 | return dbx
18 | }
19 |
20 | func exec(path string, sqlStatement string) error {
21 |
22 | dbx := connect(path)
23 |
24 | _, err := dbx.Exec(sqlStatement)
25 |
26 | return err
27 | }
28 |
29 | // Select - select all from DB
30 | func Select(path string) []models.Record {
31 | var recs []models.Record
32 |
33 | dbx := connect(path)
34 |
35 | err := dbx.Select(&recs, "SELECT * FROM records ORDER BY DATE DESC")
36 | check.IfError(err)
37 |
38 | return recs
39 | }
40 |
--------------------------------------------------------------------------------
/internal/models/models.go:
--------------------------------------------------------------------------------
1 | package models
2 |
3 | import (
4 | "github.com/aceberg/rediary/internal/auth"
5 | )
6 |
7 | // Conf - web gui config
8 | type Conf struct {
9 | DB string
10 | Host string
11 | Port string
12 | Theme string
13 | BgColor string
14 | Icon string
15 | ConfPath string
16 | ColorPlus string
17 | ColorMinus string
18 | MoodMax string
19 | Actions []Action
20 | TagMap map[string]string
21 | Auth bool
22 | }
23 |
24 | // Action - one action
25 | type Action struct {
26 | Name string `mapstructure:"name"`
27 | Tag string `mapstructure:"tag"`
28 | }
29 |
30 | // TagType - one tag
31 | type TagType struct {
32 | Name string `mapstructure:"name"`
33 | Color string `mapstructure:"color"`
34 | }
35 |
36 | // ChartJS - data for charts
37 | type ChartJS struct {
38 | Tag []string
39 | Color []string
40 | Count []int
41 | }
42 |
43 | // HeatMap - data for heatmap
44 | type HeatMap struct {
45 | X string
46 | Y string
47 | D string
48 | V int
49 | }
50 |
51 | // Record - write to DB
52 | type Record struct {
53 | ID int `db:"ID"`
54 | Date string `db:"DATE"`
55 | Tag string `db:"TAG"`
56 | Name string `db:"NAME"`
57 | Color string `db:"COLOR"`
58 | Note string `db:"NOTE"`
59 | Minus int `db:"MINUS"`
60 | Plus int `db:"PLUS"`
61 | Total int `db:"TOTAL"`
62 | }
63 |
64 | // GuiData - web gui data
65 | type GuiData struct {
66 | Config Conf
67 | Records []Record
68 | OneRec Record
69 | Themes []string
70 | Chart ChartJS
71 | Heat []HeatMap
72 | Auth auth.Conf
73 | }
74 |
--------------------------------------------------------------------------------
/internal/web/actions-tags.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | // "log"
5 | "net/http"
6 | "sort"
7 | "strings"
8 |
9 | "github.com/aceberg/rediary/internal/conf"
10 | "github.com/aceberg/rediary/internal/models"
11 | )
12 |
13 | func addActionHandler(w http.ResponseWriter, r *http.Request) {
14 | var action models.Action
15 |
16 | action.Name = r.FormValue("name")
17 | action.Tag = r.FormValue("tag")
18 |
19 | if action.Name != "" && !strings.Contains(action.Name, ":") {
20 | AppConfig.Actions = append(AppConfig.Actions, action)
21 |
22 | sort.Slice(AppConfig.Actions, func(i, j int) bool {
23 | return AppConfig.Actions[i].Name < AppConfig.Actions[j].Name
24 | })
25 |
26 | sort.Slice(AppConfig.Actions, func(i, j int) bool {
27 | return AppConfig.Actions[i].Tag < AppConfig.Actions[j].Tag
28 | })
29 |
30 | conf.Write(AppConfig, authConf)
31 | }
32 |
33 | http.Redirect(w, r, r.Header.Get("Referer"), 302)
34 | }
35 |
36 | func delActionHandler(w http.ResponseWriter, r *http.Request) {
37 | var newActions []models.Action
38 |
39 | tagname := r.FormValue("name")
40 |
41 | if tagname != "" {
42 | tnslice := strings.Split(tagname, ":")
43 | tag := tnslice[0]
44 | name := tnslice[1]
45 |
46 | for _, a := range AppConfig.Actions {
47 | if a.Tag != tag || a.Name != name {
48 | newActions = append(newActions, a)
49 | }
50 | }
51 | AppConfig.Actions = newActions
52 |
53 | conf.Write(AppConfig, authConf)
54 | }
55 |
56 | http.Redirect(w, r, r.Header.Get("Referer"), 302)
57 | }
58 |
59 | func addTagHandler(w http.ResponseWriter, r *http.Request) {
60 |
61 | tag := r.FormValue("tag")
62 | color := r.FormValue("color")
63 |
64 | if tag != "" && !strings.Contains(tag, ":") {
65 | AppConfig.TagMap[tag] = color
66 | conf.Write(AppConfig, authConf)
67 | }
68 |
69 | http.Redirect(w, r, r.Header.Get("Referer"), 302)
70 | }
71 |
72 | func delTagHandler(w http.ResponseWriter, r *http.Request) {
73 |
74 | tag := r.FormValue("tag")
75 |
76 | delete(AppConfig.TagMap, tag)
77 |
78 | conf.Write(AppConfig, authConf)
79 |
80 | http.Redirect(w, r, r.Header.Get("Referer"), 302)
81 | }
82 |
--------------------------------------------------------------------------------
/internal/web/auth-conf.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "log"
5 | "net/http"
6 |
7 | "github.com/aceberg/rediary/internal/auth"
8 | "github.com/aceberg/rediary/internal/conf"
9 | "github.com/aceberg/rediary/internal/models"
10 | )
11 |
12 | func authConfHandler(w http.ResponseWriter, r *http.Request) {
13 | var guiData models.GuiData
14 |
15 | guiData.Config = AppConfig
16 | guiData.Auth.Auth = authConf.Auth
17 | guiData.Auth.User = authConf.User
18 | guiData.Auth.ExpStr = authConf.ExpStr
19 |
20 | execTemplate(w, "auth", guiData)
21 | }
22 |
23 | func saveAuthHandler(w http.ResponseWriter, r *http.Request) {
24 |
25 | authConf.User = r.FormValue("user")
26 | authConf.ExpStr = r.FormValue("expire")
27 |
28 | authStr := r.FormValue("auth")
29 | pw := r.FormValue("password")
30 |
31 | if authStr == "on" {
32 | authConf.Auth = true
33 | } else {
34 | authConf.Auth = false
35 | }
36 | AppConfig.Auth = authConf.Auth
37 |
38 | if pw != "" {
39 | authConf.Password = auth.HashPassword(pw)
40 | }
41 |
42 | authConf.Expire = auth.ToTime(authConf.ExpStr)
43 |
44 | if authConf.Auth && (authConf.User == "" || authConf.Password == "") {
45 | log.Println("WARNING: Auth won't work with empty login or password.")
46 | authConf.Auth = false
47 | }
48 |
49 | conf.Write(AppConfig, authConf)
50 |
51 | http.Redirect(w, r, r.Header.Get("Referer"), 302)
52 | }
53 |
--------------------------------------------------------------------------------
/internal/web/chart-counters.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "github.com/aceberg/rediary/internal/models"
5 | )
6 |
7 | func countTotal(records []models.Record) models.Record {
8 | var total models.Record
9 |
10 | for _, rec := range records {
11 | total.Minus = total.Minus + rec.Minus
12 | total.Plus = total.Plus + rec.Plus
13 | total.Total = total.Total + rec.Total
14 | }
15 |
16 | return total
17 | }
18 |
19 | func countTags(records []models.Record) models.ChartJS {
20 | var chart models.ChartJS
21 |
22 | countTagMap := make(map[string]int)
23 |
24 | for _, rec := range records {
25 | _, exists := countTagMap[rec.Tag]
26 | if exists {
27 | countTagMap[rec.Tag] = countTagMap[rec.Tag] + rec.Total
28 | } else {
29 | countTagMap[rec.Tag] = rec.Total
30 | }
31 | }
32 |
33 | for tag, count := range countTagMap {
34 | chart.Tag = append(chart.Tag, tag)
35 | chart.Color = append(chart.Color, AppConfig.TagMap[tag])
36 | chart.Count = append(chart.Count, count)
37 | }
38 |
39 | return chart
40 | }
41 |
42 | func countNames(records []models.Record) models.ChartJS {
43 | var chart models.ChartJS
44 |
45 | countTagMap := make(map[string]int)
46 |
47 | for _, rec := range records {
48 | _, exists := countTagMap[rec.Name]
49 | if exists {
50 | countTagMap[rec.Name] = countTagMap[rec.Name] + rec.Total
51 | } else {
52 | countTagMap[rec.Name] = rec.Total
53 | }
54 | }
55 |
56 | for tag, count := range countTagMap {
57 | chart.Tag = append(chart.Tag, tag)
58 | chart.Count = append(chart.Count, count)
59 | }
60 |
61 | return chart
62 | }
63 |
64 | func countCloud(records []models.Record) models.ChartJS {
65 | var chart models.ChartJS
66 |
67 | countTagMap := make(map[string]int)
68 |
69 | for _, rec := range records {
70 | _, exists := countTagMap[rec.Name]
71 | if exists {
72 | countTagMap[rec.Name] = countTagMap[rec.Name] + 1
73 | } else {
74 | countTagMap[rec.Name] = 1
75 | }
76 | }
77 |
78 | for tag, count := range countTagMap {
79 | chart.Tag = append(chart.Tag, tag)
80 | chart.Count = append(chart.Count, count*10)
81 | }
82 |
83 | return chart
84 | }
85 |
--------------------------------------------------------------------------------
/internal/web/config.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "log"
5 | "net/http"
6 |
7 | "github.com/aceberg/rediary/internal/conf"
8 | "github.com/aceberg/rediary/internal/db"
9 | "github.com/aceberg/rediary/internal/models"
10 | )
11 |
12 | func configHandler(w http.ResponseWriter, r *http.Request) {
13 | var guiData models.GuiData
14 |
15 | guiData.Config = AppConfig
16 | guiData.Themes = []string{"cerulean", "cosmo", "cyborg", "darkly", "flatly", "journal", "litera", "lumen", "lux", "materia", "minty", "morph", "pulse", "quartz", "sandstone", "simplex", "sketchy", "slate", "solar", "spacelab", "superhero", "united", "vapor", "yeti", "zephyr"}
17 |
18 | execTemplate(w, "config", guiData)
19 | }
20 |
21 | func saveConfigHandler(w http.ResponseWriter, r *http.Request) {
22 |
23 | AppConfig.DB = r.FormValue("db")
24 | AppConfig.Host = r.FormValue("host")
25 | AppConfig.Port = r.FormValue("port")
26 | AppConfig.Theme = r.FormValue("theme")
27 | AppConfig.BgColor = r.FormValue("bgcolor")
28 | AppConfig.MoodMax = r.FormValue("moodmax")
29 |
30 | conf.Write(AppConfig, authConf)
31 |
32 | http.Redirect(w, r, r.Header.Get("Referer"), 302)
33 | }
34 |
35 | func saveColorsHandler(w http.ResponseWriter, r *http.Request) {
36 |
37 | AppConfig.ColorMinus = r.FormValue("minus")
38 | AppConfig.ColorPlus = r.FormValue("plus")
39 |
40 | conf.Write(AppConfig, authConf)
41 |
42 | http.Redirect(w, r, r.Header.Get("Referer"), 302)
43 | }
44 |
45 | func clearHandler(w http.ResponseWriter, r *http.Request) {
46 |
47 | log.Println("INFO: deleting all records from DB")
48 |
49 | db.Clear(AppConfig.DB)
50 |
51 | http.Redirect(w, r, r.Header.Get("Referer"), 302)
52 | }
53 |
--------------------------------------------------------------------------------
/internal/web/diary.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/aceberg/rediary/internal/db"
7 | "github.com/aceberg/rediary/internal/models"
8 | )
9 |
10 | func diaryHandler(w http.ResponseWriter, r *http.Request) {
11 | var guiData models.GuiData
12 |
13 | guiData.Config = AppConfig
14 |
15 | show := r.URL.Query().Get("show")
16 | tag := r.URL.Query().Get("tag")
17 |
18 | if tag == "" {
19 | if show == "" {
20 | AllRecords = db.Select(AppConfig.DB)
21 | show = "week"
22 | }
23 | guiData.Records = filterRecords(AllRecords, show)
24 | guiData.OneRec = countTotal(guiData.Records)
25 | guiData.Chart = countTags(guiData.Records)
26 | } else {
27 | AllRecords = filterByTag(AllRecords, tag)
28 | guiData.Records = filterRecords(AllRecords, "week")
29 | guiData.OneRec = countTotal(guiData.Records)
30 | guiData.Chart = countNames(guiData.Records)
31 | }
32 |
33 | execTemplate(w, "diary", guiData)
34 | }
35 |
36 | func diaryShowHandler(w http.ResponseWriter, r *http.Request) {
37 | var guiData models.GuiData
38 |
39 | guiData.Config = AppConfig
40 |
41 | from := r.URL.Query().Get("from")
42 | to := r.URL.Query().Get("to")
43 |
44 | guiData.Records = fromDateToDate(AllRecords, from, to)
45 |
46 | guiData.OneRec = countTotal(guiData.Records)
47 | guiData.Chart = countTags(guiData.Records)
48 |
49 | execTemplate(w, "diary", guiData)
50 | }
51 |
--------------------------------------------------------------------------------
/internal/web/exec-tpl.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "html/template"
5 | "net/http"
6 |
7 | "github.com/aceberg/rediary/internal/check"
8 | "github.com/aceberg/rediary/internal/models"
9 | )
10 |
11 | func execTemplate(w http.ResponseWriter, tpl string, guiData models.GuiData) {
12 | // tmpl, err := template.ParseFiles(TemplPath+tpl+".html", TemplPath+"header.html", TemplPath+"footer.html")
13 | tmpl, err := template.ParseFS(TemplHTML, TemplPath+tpl+".html", TemplPath+"header.html", TemplPath+"footer.html")
14 | check.IfError(err)
15 | err = tmpl.ExecuteTemplate(w, "header", guiData)
16 | check.IfError(err)
17 | err = tmpl.ExecuteTemplate(w, tpl, guiData)
18 | check.IfError(err)
19 | }
20 |
--------------------------------------------------------------------------------
/internal/web/filter.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/aceberg/rediary/internal/models"
7 | )
8 |
9 | func filterRecords(records []models.Record, show string) []models.Record {
10 | var filtered []models.Record
11 |
12 | currentTime := time.Now()
13 | max := currentTime.Format("2006-01-02")
14 |
15 | switch show {
16 | case "week":
17 | min := currentTime.AddDate(0, 0, -7).Format("2006-01-02")
18 | filtered = fromDateToDate(records, min, max)
19 | case "month":
20 | min := currentTime.AddDate(0, -1, 0).Format("2006-01-02")
21 | filtered = fromDateToDate(records, min, max)
22 | default:
23 | filtered = records
24 | }
25 |
26 | return filtered
27 | }
28 |
29 | func fromDateToDate(records []models.Record, min, max string) []models.Record {
30 | var filtered []models.Record
31 |
32 | if max == "" {
33 | currentTime := time.Now()
34 | max = currentTime.Format("2006-01-02")
35 | }
36 |
37 | for _, rec := range records {
38 | if rec.Date >= min && rec.Date <= max {
39 | filtered = append(filtered, rec)
40 | }
41 | }
42 |
43 | return filtered
44 | }
45 |
46 | func filterByTag(records []models.Record, tag string) []models.Record {
47 | var filtered []models.Record
48 |
49 | for _, rec := range records {
50 | if rec.Tag == tag {
51 | filtered = append(filtered, rec)
52 | }
53 | }
54 |
55 | return filtered
56 | }
57 |
--------------------------------------------------------------------------------
/internal/web/heatmap.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "strconv"
5 | "time"
6 |
7 | "github.com/aceberg/rediary/internal/models"
8 | )
9 |
10 | func generateHeatmap(records []models.Record) []models.HeatMap {
11 | var heatMap []models.HeatMap
12 | var heat models.HeatMap
13 | totalByDay := make(map[string]int)
14 |
15 | max := time.Now()
16 | min := max.AddDate(0, 0, -35)
17 |
18 | monthRecords := fromDateToDate(records, min.Format("2006-01-02"), max.Format("2006-01-02"))
19 |
20 | for _, rec := range monthRecords {
21 | val, exists := totalByDay[rec.Date]
22 | if exists {
23 | totalByDay[rec.Date] = val + rec.Total
24 | } else {
25 | totalByDay[rec.Date] = rec.Total
26 | }
27 | }
28 |
29 | i := 4
30 | for d := max; !d.Before(min); d = d.AddDate(0, 0, -1) {
31 | heat.D = d.Format("2006-01-02")
32 | val, exists := totalByDay[heat.D]
33 | if exists {
34 | heat.V = val
35 | } else {
36 | heat.V = 0
37 | }
38 | heat.X = d.Weekday().String()[0:2]
39 | heat.Y = strconv.Itoa(i)
40 |
41 | heatMap = append(heatMap, heat)
42 |
43 | if heat.X == "Mo" {
44 | i--
45 | }
46 | if i < 0 {
47 | break
48 | }
49 | }
50 |
51 | return heatMap
52 | }
53 |
--------------------------------------------------------------------------------
/internal/web/index.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "net/http"
5 | "time"
6 |
7 | "github.com/aceberg/rediary/internal/db"
8 | "github.com/aceberg/rediary/internal/models"
9 | )
10 |
11 | func indexHandler(w http.ResponseWriter, r *http.Request) {
12 | var guiData models.GuiData
13 |
14 | guiData.Config = AppConfig
15 |
16 | AllRecords = db.Select(AppConfig.DB)
17 | guiData.Heat = generateHeatmap(AllRecords)
18 |
19 | today := time.Now().Format("2006-01-02")
20 | monthAgo := time.Now().AddDate(0, -1, 0)
21 |
22 | monthRecords := fromDateToDate(AllRecords, monthAgo.Format("2006-01-02"), today)
23 | guiData.Chart = countCloud(monthRecords)
24 |
25 | guiData.Records = fromDateToDate(AllRecords, today, today)
26 | guiData.OneRec = countTotal(guiData.Records)
27 | guiData.OneRec.Date = today
28 |
29 | execTemplate(w, "index", guiData)
30 | }
31 |
--------------------------------------------------------------------------------
/internal/web/login.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "log"
5 | "net/http"
6 |
7 | "github.com/aceberg/rediary/internal/auth"
8 | "github.com/aceberg/rediary/internal/models"
9 | )
10 |
11 | func loginHandler(w http.ResponseWriter, r *http.Request) {
12 | var guiData models.GuiData
13 | guiData.Config = AppConfig
14 |
15 | username := r.FormValue("username")
16 | password := r.FormValue("password")
17 | logout := r.FormValue("logout")
18 |
19 | if username == authConf.User && auth.MatchPasswords(authConf.Password, password) {
20 |
21 | log.Println("INFO: user '"+username+"' logged in. Session expire time", authConf.Expire)
22 |
23 | auth.StartSession(w, r)
24 | }
25 | if logout == "yes" {
26 |
27 | auth.LogOut(w, r)
28 | }
29 |
30 | execTemplate(w, "login", guiData)
31 | }
32 |
--------------------------------------------------------------------------------
/internal/web/record.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "log"
5 | "net/http"
6 | "strconv"
7 | "strings"
8 | "time"
9 |
10 | "github.com/aceberg/rediary/internal/check"
11 | "github.com/aceberg/rediary/internal/db"
12 | "github.com/aceberg/rediary/internal/models"
13 | )
14 |
15 | func addRecordHandler(w http.ResponseWriter, r *http.Request) {
16 | var rec models.Record
17 |
18 | date := r.FormValue("date")
19 | name := r.FormValue("name")
20 | minus := r.FormValue("minus")
21 | plus := r.FormValue("plus")
22 | note := r.FormValue("note")
23 |
24 | if name != "" {
25 | n := strings.Split(name, ":")
26 |
27 | rec.Tag = n[0]
28 | rec.Name = n[1]
29 | rec.Color = AppConfig.TagMap[rec.Tag]
30 |
31 | rec.Minus, _ = strconv.Atoi(minus)
32 | rec.Plus, _ = strconv.Atoi(plus)
33 | rec.Total = rec.Plus - rec.Minus
34 |
35 | rec.Note = note
36 |
37 | if date == "" {
38 | currentTime := time.Now()
39 | rec.Date = currentTime.Format("2006-01-02")
40 | } else {
41 | rec.Date = date
42 | }
43 |
44 | log.Println("INFO: new record", rec)
45 |
46 | db.Insert(AppConfig.DB, rec)
47 | }
48 |
49 | http.Redirect(w, r, r.Header.Get("Referer"), 302)
50 | }
51 |
52 | func delRecordHandler(w http.ResponseWriter, r *http.Request) {
53 |
54 | idStr := r.URL.Query().Get("id")
55 |
56 | id, err := strconv.Atoi(idStr)
57 | check.IfError(err)
58 |
59 | log.Println("INFO: deleting record with ID =", id)
60 |
61 | db.Delete(AppConfig.DB, id)
62 |
63 | http.Redirect(w, r, r.Header.Get("Referer"), 302)
64 | }
65 |
--------------------------------------------------------------------------------
/internal/web/stat.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "net/http"
5 |
6 | "github.com/aceberg/rediary/internal/db"
7 | "github.com/aceberg/rediary/internal/models"
8 | )
9 |
10 | func statHandler(w http.ResponseWriter, r *http.Request) {
11 | var guiData models.GuiData
12 |
13 | guiData.Config = AppConfig
14 | AllRecords = db.Select(AppConfig.DB)
15 |
16 | execTemplate(w, "stat", guiData)
17 | }
18 |
--------------------------------------------------------------------------------
/internal/web/templates/auth.html:
--------------------------------------------------------------------------------
1 | {{ define "auth" }}
2 |
3 |
4 |
5 |
6 |
40 |
41 |
42 |
● WARNING! Authentication is only safe when used over https and with a strong password.
43 |
● Expire after - when user session expires. Can be set with suffixes m(minute), h(hour), d(day) or M(month). Default: 7d.
44 |
● Login. For Auth to work, login and password must not be empty.
45 |
● Password is stored encrypted in config file. If you forgot your password, just set auth_password: field to empty there.
46 |
47 |
48 |
49 |
50 |
51 |
52 | {{ template "footer" }}
53 | {{ end }}
--------------------------------------------------------------------------------
/internal/web/templates/config.html:
--------------------------------------------------------------------------------
1 | {{ define "config" }}
2 |
3 |
4 |
5 |
6 |
49 |
50 |
51 |
52 |
55 |
56 |
57 |
58 |
Warning! This button will remove all your diary records
59 |
60 |
61 |
62 |
63 |
Colors
64 |
87 |
88 |
89 |
90 |
91 | Tags
92 |
98 |
99 |
107 |
108 |
109 | Actions
110 |
119 |
120 |
128 |
129 |
130 |
131 |
132 |
133 | {{ template "footer" }}
134 | {{ end }}
--------------------------------------------------------------------------------
/internal/web/templates/diary.html:
--------------------------------------------------------------------------------
1 | {{ define "diary"}}
2 |
3 |
4 |
5 |
6 |
7 |
22 |
23 |
24 | |
25 | Date |
26 | Tag |
27 | Name |
28 | Minus |
29 | Plus |
30 | Total |
31 | |
32 |
33 | {{ range .Records }}
34 |
35 | |
36 | {{ .Date }} |
37 | {{ .Tag }} |
38 | {{ .Name }} |
39 | -{{ .Minus }} |
40 | +{{ .Plus }} |
41 | {{ .Total }} |
42 |
43 |
44 | |
45 |
46 | {{ end }}
47 |
48 | |
49 | Summary |
50 | |
51 | |
52 | -{{ .OneRec.Minus }} |
53 | +{{ .OneRec.Plus }} |
54 |
55 | {{ if gt .OneRec.Total 0 }}
56 | {{ .OneRec.Total }}
57 | {{ else }}
58 | {{ .OneRec.Total }}
59 | {{ end }}
60 | |
61 | |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
87 | {{ template "footer" }}
88 | {{ end }}
--------------------------------------------------------------------------------
/internal/web/templates/footer.html:
--------------------------------------------------------------------------------
1 | {{ define "footer"}}
2 |
3 |
4 | {{ end }}
--------------------------------------------------------------------------------
/internal/web/templates/header.html:
--------------------------------------------------------------------------------
1 | {{ define "header"}}
2 |
3 |
4 |
5 | Resource Diary
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
37 |
38 |
39 |
75 | {{ end }}
--------------------------------------------------------------------------------
/internal/web/templates/index.html:
--------------------------------------------------------------------------------
1 | {{ define "index"}}
2 |
3 |
4 |
5 |
10 |
11 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
Today - {{ .OneRec.Date }}
49 |
50 |
51 |
52 | |
53 | Tag |
54 | Name |
55 | Minus |
56 | Plus |
57 | Total |
58 |
59 | {{ range .Records }}
60 |
61 | |
62 | {{ .Tag }} |
63 | {{ .Name }} |
64 | -{{ .Minus }} |
65 | +{{ .Plus }} |
66 | {{ .Total }} |
67 |
68 | {{ end }}
69 |
70 | Summary |
71 | -{{ .OneRec.Minus }} |
72 | +{{ .OneRec.Plus }} |
73 |
74 | {{ if gt .OneRec.Total 0 }}
75 | {{ .OneRec.Total }}
76 | {{ else }}
77 | {{ .OneRec.Total }}
78 | {{ end }}
79 | |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
256 | {{ template "footer" }}
257 | {{ end }}
--------------------------------------------------------------------------------
/internal/web/templates/login.html:
--------------------------------------------------------------------------------
1 | {{ define "login" }}
2 |
3 |
4 |
17 |
18 | {{ template "footer" }}
19 | {{ end }}
--------------------------------------------------------------------------------
/internal/web/templates/stat.html:
--------------------------------------------------------------------------------
1 | {{ define "stat" }}
2 |
3 |
4 |
5 |
6 |
7 | Stat
8 |
9 |
10 |
11 |
12 |
13 | {{ template "footer" }}
14 | {{ end }}
--------------------------------------------------------------------------------
/internal/web/var-const.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "embed"
5 |
6 | "github.com/aceberg/rediary/internal/auth"
7 | "github.com/aceberg/rediary/internal/models"
8 | )
9 |
10 | var (
11 | // auth config
12 | authConf auth.Conf
13 | // AppConfig - config for Web Gui
14 | AppConfig models.Conf
15 | // AllRecords - all records
16 | AllRecords []models.Record
17 | // TemplHTML - embed templates
18 | // //
19 | //go:embed templates/*
20 | TemplHTML embed.FS
21 | )
22 |
23 | // TemplPath - path to html templates
24 | const TemplPath = "templates/"
25 |
26 | // TemplPath - path to html templates
27 | // const TemplPath = "../../internal/web/templates/"
28 |
29 | // Icon - favicon
30 | const Icon = "iVBORw0KGgoAAAANSUhEUgAAAgAAAAIACAYAAAD0eNT6AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAOxAAADsQBlSsOGwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAACAASURBVHic7d13lF1V3f/x952WaZn0TJJJJ71CCL333jsiRRBFeERU8Kc+KqI8IIhYEUVgRHoooRq6ISG0kIRUUpj0SSaT6b3ce39/nAQhdco+Z5/yea111mKFyXfvuZm538/d55x9YohIWGUABwCTgRHASGAfIBvIA3K3fV0tUA3UA58DK7cdC4GPgWZPZy0iIiLtNg74OfAOTkNPdvKoA94C/hcY4+H3ISIiInuRD9wCLKDzDX9vxzzgZqCvJ9+ZiIiI7GQY8AecT+luN/4dj0bgEWC069+liIiIADAAp/m24n3j3/FoBQqBfm5+wyIiIlGWDtwIVGG/8e941AK3Al3c+uZFRESiaBzOVfm2G/3ejgXAWJdeAxERkUi5HOcTtu3m3tajHmelQkRERDogA/gn9ht6R4+HcU5biIiISBvlAK9iv4l39ngT6Gr4tREREQml3sBH2G/epo4Pt31PIiIisht9CMbFfu09lqFbBUVERHYprM1fIUBERGQ3wt78FQJERER2EJXmrxAgIiKyTdSav0KAiIhEXlSbv0KAiIhEVtSbv0KAiIhEjpq/QoCIiESMmr9CgIgvxGxPQCRC+gBvAxO8Hjgzvxt9jxtLjwOGkTsin6wB3UnvlkUyCa3VDTQUV1C7cgvlHxWx5Z1lNJVUez1FgMXAsUCpjcFFokYBQMQbVpp/nyNHM/TqI+l16AhiKW37dU/GE5S9t4rVD73L1lkrXJ7hThQCRDyiACDiPs+bf9dR/Rh369n0PGh4p+qUffA5S2+dTu3KEkMzaxOFABEPKACIuMvz5j/k64cy5senk9IlzUi9RFMry25/iXWPvW+kXhspBIi4LNX2BERCrA/wFjDRk9FiMcb8+HRGff8kYmkp5sqmpdD3mLFk9Mh2TgkkjZXek77AGcCzQK0nI4pEjAKAiDs8b/7jbzuHoVcc5toQ3ScPJnNAD0rfXupVCOgNnI5CgIgrFABEzLPS/AdferDrQ+WNG6AQIBISCgAiZoW2+W+nECASDgoAIuaEvvlvpxAgEnwKACJmRKb5b6cQIBJsCgAinRe55r+dQoBIcCkAiHROZJv/dgoBIsGkACDScZFv/tspBIgEjwKASMeo+e9AIUAkWBQARNpPzX83FAJEgkMBQKR91Pz3QiFAJBgUAETaTs2/jRQCRPxPAUCkbdT820khQMTfFABE9k7Nv4MUAkT8SwFAZM/U/DtJIUDEnxQARHZPzd8QhQAR/1EAENk1NX/DFAJE/EUBQGRnav4uUQgQ8Q8FAJGvUvN3mUKAiD8oAIj8l5q/RxQCROxTABBxqPl7TCFAxC4FABE1f2sUAkTsUQCQqFPzt0whQMQOBQCJMjV/n1AIEPGeAoBElZq/zygEiHhLAUCiSM3fpxQCRLyjACBRo+bvcwoBIt5QAJAoUfMPCIUAEfcpAEhUqPkHjEKAiLsUACQK1PwDSiFAxD0KABJ2av4BpxAg4g4FAAkzNf+QUAgQMU8BQMJKzT9kFAJEzFIAkDBS8w8phQARcxQAJGzU/ENOIUDEDAUACRM1/4hQCBDpPAUACQs1/4hRCBDpHAUACQM1/4hSCBDpOAUACTo1/4hTCBDpGAUACTI1fwEUAkQ6QgFAgkrNX75CIUCkfRQAJIjU/GWXFAJE2k4BQIJGzV/2SCFApG0UACRI1PylTRQCRPZOAUCCQs1f2kUhQGTPFAAkCNT8pUMUAkR2TwFA/E7NXzpFIUBk1xQAxM/U/MUIhQCRnSkAiF+p+YtRCgEiX6UAIH6k5i+uUAgQ+S8FAPEbNX9xlUKAiEMBQPxEzV88oRAgogAg/qHmL55SCJCoUwAQP1DzFysUAiTKFADENjV/sUohQKJKAUBs8rz5T/iVmr/sTCFAokgBQGyx0vwHXaLmL7umECBRowAgNqj5iy8pBEiUKACI19T8xdcUAiQqFADES2r+EggKARIFCgDiFTV/CRSFAAk7BQDxgpq/BJJCgISZAoC4Tc1fAk0hQMJKAUDcpOYvoaAQIGGkACBuUfOXUFEIkLBRABA3qPlLKCkESJgoAIhpav4SagoBEhYKAGKSmr9EgkKAhIECgJii5i+RohAgQacAICao+UskKQRIkCkASGep+UukKQRIUCkASGeo+YugECDBpAAgHaXmL/IlCgESNAoA0hFq/iK7oBAgQaIAIO2l5i+yBwoBEhQKANIeav4ibaAQIEGgACBtpeYv0g4KAeJ3CgDSFmr+Ih2gECB+pgAge6PmL9IJCgHiVwoAsidq/iIGKASIHykAyO6o+YsYpBAgfqMAILui5i/iAoUA8RMFANmRmr+IixQCxC8UAOTL1PxFPKAQIH6gACDbqfmLeEghQGxTABBQ8xexQiFAbFIAEDV/EYsUAsQWBYBoU/MX8QGFALFBASC61PxFfEQhQLymABBNav4iPqQQIF5SAIgeNX8RH1MIEK8oAESLmr9IACgEiBcUAKJDzV8kQBQCxG0KANGg5i8SQAoB4iYFgPBT8xcJMIUAcYsCQLip+YuEgEKAuEEBILzU/EVCRCFATFMACCc1f5EQUggQkxQAwkfNXyTEFALEFAWAcFHzF4kAhQAxQQEgPNT8RSJEIUA6SwEgHPoAb+NR84+lxJh45wUMuuhAL4YTkd3IGzeAzP7dKX17mZch4GRgGlDvyYjiGgWA4EsHXgK86cbbP/mr+Yv4Qt74Aq9XAvoChwGPAnFPRhRXKAAE32+AS70YSJ/8RfzJwkrAYJz+8bYno4krFACCbTBOCk9zfSR98hfxNQsrAVOBQqDGk9HEOAWAYLsFOMbtQfTJXyQYPF4JSAfKgVmujySuUAAItnuBfDcHiKXEmHDHBQw8f6qbw4iIIXnjC7wMAZnAQ66PIq6I2Z6AdFga0ASkuDaCbvUTCawNz8xl8Y+nkUy4mgLqgFw3BxD3uNc8xG19cPnfb8Lt56n5iwTUwPOnMv7X57k9TA4KAIGlABBcTW4PUPbeSpLxhNvDiIgLkvEEFR+vdn0YoNntQcQdCgDBVQE0ujnAplc+ZeEtTysEiARMMp5g4S1Ps/H5T9weqgwFgMBSAAiuJDDb7UGKp8/j05ueUAgQCYhkPMGiH02jePo8L4Zz/T1I3KO7AIItDzjV7UFqV5ZQv76c/OPHEUvRdaMifrX9k79HzR/gbmC+V4OJWXo3D7YsYCVQ4MVg/U+bzOR7LyGWqoUjEb/Z/snfg2X/7dYBo/DgeiRxh1YAgq0VKAHO9WIwrQSIXyRb4zRurqZhXRmNm6uoW7WF+nXlNKwvp6WyntbqRuKNLaRmZUQisFr45A/wTWChlwOKWXoXD4ffATd5NdiAs/Zj0t0XReKNVexKxhPULN9M5fy1VC3aQP3aMho2lNNYUt2m61JiqSlk9u9G9uBeZA/pTd6Y/vSYOpTcUf1CE2ItNf97gB96OaCYF47fAEnB2Y3rCq8GVAgQtzSsL6fkjSVseWsplQvXE683f5F5Wm4mPaYModfhI+l38kSyCnoYH8MLlpp/IXA1oCuDA04BIDwUAiSwmkqqWT/tIzbPWETNsk3eDh6L0W3iQPqdPJEBZ+9HZn43b8fvIDV/6SwFgHDxPATowkDpjKrFG1hbOJvilz4l2Wr/0fKxlBh9jh7D0CsPp9dhI21PZ7csXPAHav6howAQPloJEN/b8tZSVvzuNWo+8/jTfjvkjS9g5HdPoO/x42xP5Sv0yV9M0V0A4ZMEXgSGAvt6MWDN8s3UFZWSf+KE0FxYJe6omLeWhT94kqL736F5a63t6exRU2kNm15ewNZZy8kZ2tsX1wl4vMnPdoWo+YeSAkA4eR4CaleWUL+ujPzjxysEyE6aSmtYePNTLL/jFRo2VtieTrs0bq5i47NzqV25mZ5Th5GW08XKPPTJX0xTAAgvrQSIL2x+dSFzr36I6iUbbU+lU2pXbWHDtI9J755NtwkDPR1bn/zFDQoA4aaVALGmuayWed95hKL73yHR2GJ7OkYkmlrZ8vYyapYW0+vQEaRmZ7g+pj75i1sUAMJPKwHiueqlG/no8geoXhzsT/27U1dUyqYXF9Bz6jAy+7l326DzyV/NX9yhABANVlYCFAKiqXj6POZ9+xGay+tsT8VVrXVNbJw+j6x+3cgbN8B4/e3Nf+Pzav7iDgWA6NDpAHHdit/+m2W3v0yyNRr9IxlPUPLGEhLNrfQ+dATEzPyca9lfvKAAEC06HSDuSCZZ9n8vs/qBmbZnYkXF3DU0bamhzzFjiXUyBGjZX7yiABA9Oh0gZiWTLL3tRdYWzrY9E6uqF2/s9IqXlv3FSwoA0aTTAWJGMsninz7Lusc/sD0TX6hZvpmm0hr6Htf+3QO17C9eUwCIriTwAtAPmOrFgDodED6f//WdyC7770714o3E0lLoeeDwNv8dLfuLDQoA8ipaCZAOKHljCUt+9pwTJeUryj8oIntgT/LG7v3uAH3yF1sUAEQrAdJutatK+OSah0k0tdqeim+VzlxOn6NHk9k3b7dfo0/+YpMCgGynlQBpk9baRj646K++f5iPbcl4grL3VjLwvKmkdEnb5f/XJ3+xSQFAtrNyi6BCQPAs/eULlM1ZZXsaAC3AWmAhsApYAGwESrb9v644j8e2pqW6gfo1W+l/2uSv/Lmav/jBzrFUoiwBfGPbf1/hxYDFL8wHYNLdFxFLtfpeLW2wddYK1j/1ka3hS4CXgPeAD4EVQHwPX58OjAQOBg4HTgP6ujzHnWyesYjiF+cz4Mz9ADV/8Q997JJdSQEeBK70asABZ+2nEOBzrbWNzD7ldzQUV3o5bCPwFPAPYA6da2CpwJE4IfdCwP0n+WyT0SuXI1//IWldM9X8xTd0CkB2JYnzSWsIOh0g23x2xytsnb3Sq+HqgHuAC4AngHV0/n6DJLAGeB54AKchTsFZKXBVvKGZptJqSt5YouYvvqF3WtkTrQQIAA3ry3n3hLtJtOxpxd2Yx4CbgU0ejDUIuAu42IOxvFaImr/sgVYAZE+0EiAALPv1i1Qvcf3RvptxGvFvAK9uMagGnsW5kPBoINejcd1WiJq/7IUCgOzN9rsDtE9ARNUVlW7b8MfVHX8+AU4A5ro5yB58BjyOc7HgQEtzMKUQNX9pAwUAaatX8XAlQPsE+MfSX0ynZvlmN4eYBpwOlLs5SBvUAI8Co4HxlufSUYWo+UsbKQBIW2klIIKatlSz+KfPQcK1T/9PAJfh3LfvB63Ac3gYdg0qRM1f2kEBQNpLKwERsqZwNmXvuXbl/zPApez5Xn4btofdScBYy3Npq0LU/KWdFACkvXRhYEQk4wkW/fApWmsa3Sg/DzgTaHajuAHbf85PAAosz2VvClHzlw7QvVbSEQmcN5xCrwYsfmE+C29+imRc73Fe2frucrc2/akEzgbq3ShuUD1wPvavTdiTQtT8pYO0AiAdpZWAkPv8L29T85krt+J/C5jlRmEXVOM8Z+Ai2xPZhULU/KUTFACkMxQCQiqZSLLkZ88RbzC+Qv8q8CPTRV22DOfne4ztiXxJIWr+0kk6BSCdpdMBIVS9eAPNZcb34okDt5gu6pGbgAbbk9imEDV/MUArAGKCbhEMmfVPfkT5h0Wmyz4K/N10UY9UAvnAQZbnUYiavxiiACAmeX6LYHNFHX2PCcqdWsGx8nev0bjJ+AWAXwNKTRf10GLgeuy9bxai5i8G6RSAmOT56YB1j77v9dPVQi+ZSFK9rNh02VnAEtNFPbYe55oXGwpR8xfDFADEtMOAcV4O+NkdLxNv9MtGcsFXv2Yr8XrjF//9w3RBSx6yMGYhav7iAgUAMWUkzhaq7wIHejlw09ZaNr38qZdDhpoLn/7jwMumi1ryBs6tgV4pRM1fXKIAIJ2VAlwLzAfOsTWJLW8ttTV06NSYDwAf4O/NdNqjBXjLo7EKUfMXFykASGeMBmYDfwNybE6kevEGm8OHSt3aMtMl/2O6oGVvezBGIWr+4jIFAOmoC3Ge3X6I7YkANJm/Zz2ymsvqTJcM2/kZt686LUTNXzygACDtlQbcAzwJ5FqeyxdiqfpRNsWFDYDCFgA+xb0nGBai5i8e0bumtEcu8ArwfcBXu+9k9u9uewqh0VxuPACsM13QsjqcPQFMK0TNXzykACBt1RN4EzjR9kR2pfukgbanEArJeIKWSqMP6asGXHmesGWm9wMoRM1fPKYAIG3RH+f2PtvboO5W/gkTbE8hHJJJkomkyYphufp/Rw9gLtgUouYvFigAyN50A2YA421PZHeyB/Wk7/Ge7j0UXil6S2ijdcDdBuoUouYvlui3XfYkE3gBmGR7Insy5qdn6CJAQ2IpMYgZvbwjzP8wt+FsDNRRhaj5i0Vh/uWUzkkFHgOOsj2RPRl82SHkn+DbxYlAMvx0Rd/cKeKCVuBsnCdhttcfUPMXyxQAZHd+A5xrexJ7UnDeVMb9/Czb0widlHSjD7vrCWSbLOgz9Tgh4HqgLTsolQCXAt9DzV8sUwCQXTkV51Y/X0rPy2LC7ecx6TcXaOnfBV36dDVdMuy3aCSB+4ChwDU4KwLF2/4cYBPO7bPXAMOAJ7yfosjO0mxPQHxnAM65SV/d55+el0Xe+AL6Hj+OgedPJS030/aUQitzQHfq1xu9eH8isMJkQZ+qBR7cdoj4ngKAfFkK8CjQx8bgsZQYXccOoPu+g8kbN4Cc4X3I6JlLZn4eaV3V8L2S2a+b6ZIHAM+aLioinaMAIF92HXCMpyPGYvQ6eB8Kzt2fPkeNJqNXmK8ZCwYXAsChpguKSOcpAMh2vYFfeTVYSkYagy46kKHfOILswb28GlbaIGeY8QWgQ3FWlUpNFxaRjlMAkO1uB3q4PkosRsG5+zPq+ye58UlTDOg2aZDpkqnAmejcuIivKAAIwP44Vyi7KmdYHybcfh49Dxru9lDSCbkj+pKanUG8vtlk2StQABDxFd1DJeB8+nf1ZyH/pAkc8twNav4BEEtNodtE43fuHYFzMaCI+IQCgEzGzSf8xWKM/tGpTLnvctLzslwbRszqPnmwG2VvdKOoiHSMAoDcjEv3/MdSU5j0mwsYfu3RbpQXF/U5erQbZS8BprhRWETaTwEg2gYBF7pSORZj/K/OpeC8qa6UF3f1mDrMjVsyU4A/4bNNpkSiSgEg2q4D0t0oPOqmExl00YFulBYPxFJT6HucK49YPhS41o3CItI+CgDRFcNZkjWu77Fj2ec7x7pRWjzU76QJbpX+Pc72wCJikQJAdB2C8/ASo7IGdGfSby82/Ux5saDXYSPd2pkxE3gc6O5GcRFpGwWA6LrYjaLjbz+P9G662j8MUtJTGXzJwW6VnwBMxwkDImKBAkA0xYALTBfte/w4+hzpytXjYsngyw4hJT3VrfJH4Twat4tbA4jI7ikARNMYoJ/JgrHUFMb8+HSTJcUHuvTpSv/T93VziLOBl4Gubg4iIjtTAIimI00XzD9pAjlDe5suKz4w9BuHu31Nx/HAB4CWj0Q8pAAQTcYDwPBrjjJdUnwib1wBA85wdRUAYBzwEXA12idAxBMKANF0hMliuSPy6TbZ+BPkxEdG3XwKqZmubBnxZXnAP4DXgfFuDyYSdQoA0dMDZwdAY/qf6fqnQ99JNLfSsKGCxk2VJFritqfjuqwB3Rl6tfGFo905HvgU5+mBY70aVCRqtNQWPQfgLLUac/i/v0/XUUavKfSlho0VrH/yQ0reWEJdUSnJeAJwLoDMGzeA/JMmMujiA8nokWN5pu6I1zcz8/i7aCqp9nLYJM6KwCPAC0Cdl4OLhJkCQPRcCjxmqlh692yOn/uLUG/8E69vZsU9M1j7rzlfNP3dSc/LYvQtpzDIvfvnrSp9dzlzv/EQJJM2hm8EZgHvAHOBBUCpjYmIhIFrN/iKb50DHGOqWO/DRzLgjP1MlfOdxs1VfPT1v7PlzaVtanqJpla2vL2Mpi3V9Dl6DLGUcAWjnCG9aa1upHLBOhvDpwH7AMcBX8d5kuUV2/5sLQoDIu2iawCix+iD3nNH5Jss5ystVQ18fMUD1Czb1O6/u/7JD1l4y9N7XTEIotG3nELeuAG2p7HdMOB/gIXAn9HOgiJtpgAQPUY3XMkZ0stkOV9Z8ovnqV21pcN/v3j6vFCGgJSMNCbfeymp2Rm2p/JlqcD1wLvoGQMibaIAED1Gn+6S2T+c77WVC9ax6aUFna4T1hCQO6Iv+/7ha8RSffcWcgDOxYJptici4ne+++0V1xkNAKk54dzGfe2/5hirFdYQ0PfYsUz49bl+vAD0SOAW25MQ8TsFgOgxeo+aB5vDeC6ZSFL6n8+M1gxrCBh44YGMvOlE29PYlR8D4T0/JWKAAkD0tJgslmwN3yY4zaU1tFTWG68b1hAw4vrjGHL5YbansaNcnDsERGQ3FACip9Zksdb6ZpPlfKGhuNK12mENAeN+cRbDv23s7lJT9HhKkT1QAIgeswGgqsFkOV9oKnV3p7uwhoDRN5/C6B+d6qdrAqbYnoCInykARE+NyWJ1a7eaLOcLTVuMvkS7FNYQMPzao5ly39f9cotgNwxf8yISJgoA0VNuslj9mvAFgNpVJZ6ME9YQkH/iBA6Zdj05Q3vbngo4zxIQkV1QAIieVSaLVS3aaLKcL1Qv8e57Kp4+j09veiJ0IaDrmP4c9spNDLnicJvTqALMX80pEhIKANGzwmSxms+KaakOz3UAiaZWqpcVezrmplc+DeVKQGpmOuN+fib7/ekyuvQxugFlW31sY1CRoFAAiJ6VJoslE0nKPywyWdKq8g+LiDcYvVOyTcJ6OgCg36mTOOL1HzLoogO9Hvo5rwcUCRIFgOhZBzSZLLjp5U9NlrNqy9tLrY0d5hCQltOFeKOnwaoU+JeXA4oEjQJA9MQxvDS65a0lxEOwH0CiuZViA/v/d0YYQ0AynmDhzU9R/MJ8L4e9CcO3vIqEjQJANL1rsli8oYUNzwT/dGvJG0tc2QGwvcIUAiw1/z8Cj3k5oEgQKQBEk9EAAFD095mB3xZ49T+MvywdFoa7A5LxBIt+9LTXzf9hnE//IrIXqbYnIFaU4DwtzVgAbK1tJKugB3njC0yV9FTJm0tY86B/AgBA7coS6teXk3/8OGIpvtldr02++OQ/3fPmfw0Q3NQk4iEFgGhqBo4FhposWrlgHYMuOpDULsF6QmCiuZX51z9KS0Wd7anspOazTYELAZaW/dX8RdpJASC6ugBnmCwYb2gmXt9Mn6PHmCzrus//+jabX11oexq7FaQQoOYvEhwKANG1GudcqdGfgapFG+g+cSA5w/qYLOua6iUbWXiz/y+4C0IIUPMXCRYFgOhqAA4ERpsuvHXWSgacuR9puZmmSxvVUt3Ax5c/QHO5/5b+d8XPIUDNXyR4FACirQW40HTReGMLZe+tpP8Z+/r2eoBES5z51/2TqkUbbE+lXfwYAtT8RYJJASDalgOXAT1MF24uq6Vi3lr6n7YvKen++jFLJpIs/OGTbHnT3q5/neGnEKDmLxJc/npnFq8lcVYBTnOjeGNxJWVzVpF/4nhSs3zxfHgSLXEW/uBJNr1sd8e/zqr5bBN1RaXknzjBWgj44j5/3eonEkgKALIE+CaQ40bxxs1VlL79GX2PHkN6tyw3hmizlsp6PvlmIaXvLLM6D1Ns7hOg+/xFgk8BQFqBdOA4twZoLq9jw7NzyRnci9yR+W4Ns0cVH6/moyv+Qc1nm9we6o/AZ8C+bg8Edk4HaNlfJBwUAATgE+BSXLgWYLtEcyub/72QhvVldN9vCGk5Xdwa6ita65pYee/rLP7f52itbnB7uArgPOApnE2WQhcC1PxFwsMflxGLH5wNPO/FQGm5mexz/bEMuexQUrPduTYg2Rqn+IX5LL9nBk0l1a6MsQs/BO7Z9t8pwEPAFV4NPuDsKUy660Jiqe484kPNv11SgbHABKDfl46+QE+gZoevLwE2bDvWAkU4K0nBfsCG+JoCgHzZa8CJXg2W3j2bwV87hEEXH0TWgO5GarZU1rPx+U9Y89AsGoorjdRso6XAFKDpS38WmhCg5r9XPYFTgIOA/XFWf7I7WbMOZ3XuI+AD4A3AszQr4acAIF82GlgAeLuDTyxGj/2H0O+USfQ6ZAS5I/PbtZRdv76c8g8+Z/NriymbvYJEi+cfmuLAYcCHu/h/gQ8Bav67NRg4C2f17EggzeXxmoF3gBeAF4GNLo8nIacAIDu6DrjP5gTSu2eTN6Y/2UN7k1XQg4yeOaRmZxBLTaG1ppHW2iYaNpZTv7acmuWbaNxcZXO6AHcBP9rD/w9sCFDz30kqTtO/ATjG4jwSwKs4v6uv4c/XSnxOAUB25Rmci9lk7z4FDgYa9/J1gQsBav5f0QtnXtcBQyzPZUdFwF+A+4F6y3ORANFdALIrrwMX4eJdASFRARwPlLbha5M4y7ZD8fDugI5uFqRNfr6QgfNp/3ngdMDMxSpm9QBOAq7FCZqf4NzeK7JHCgCyK43A+8DXcPYIkJ0lgPNxLtBqK89DQEc2C9ImP4DTSC/DOd9+EV5fF9MxOTiB9DJgE84mXyK7pQAgu7MRWIjzsCB37isLtluARzrw96ysBLQ1BGjZH4AxwMs4n/y7WZ5LR3QHLsC5G2EWunNAdkMBQPZkBbAaOAddL/JlvwFu68Tf9+XpAC37EwNuBKbh/NsE3Wic17YSmGt5LuJDCgCyNwtxbj9ybavggHkQp0l0lq9OByTjCRbe8jTF0+d5MZXt/NT8BwHPAt8hXKe9uuBcuzAemIHzuywCKABI28zG+RRxItFeCXgI+DbmGpYvVgL++8k/ss3/YOBtYKLtibhoPM6dPf8BttidiogE0WU4nyCSETzuNPD67U4KUOjl99P/tMnJk1fcmTx5xZ3JgnOmeP1aPoR/riu5BGjA/s+XV0cNzo6FIiLtdipQi/03Mq+OFpxPqm7zPAQMOHtKcsDZkW3+MeAXOCsQuNbGOwAAIABJREFUtn/GvD6acYKPiEi77YdzgaDtNzK3jxI8fDYCFkKAx4dfmj84Kzq2Xw+bRwL4XqdfRRGJpK44t8HZfiNz63gbGGDs1Wq7GM6Obra/f9OHn5r/Hdh/PfxyXNfJ11JEIuwKnPOKtt/ITB0twE+w26zCthLgp+b/S+y/Hn464jh7BoiIdEgBzmpA0M+nzgQmGX5tOiosKwF+av43Yv/18OPRCBzd8ZdVRASOwtk3wPYbWnuPjcDl+O8Wx6CHAD81/2NwVndsvyZ+PSqA4R1+dUVEcJ6Jfi2wEvtvans7NuMs9+e48kqYkYJzz7zt16q9h5+a/2Cce99tvyZ+PxYAWR18jUVEvpACnIHzUCHbb2w7HkU4y8HZrn33ZgVtJcBPzT8L5+l4tl+ToBz3dexlliDy25KnhNOROE8WPB/oaWkO9cBLwOPAKzgXPwVJCs42xFdansfePIx/dvgDuAf4vq3BszNT2HdENvuPymHUoEz69UynX690sjJiNDQnaWxOUFrZwoYtLazY0MhHy+pYsrqBeCJpa8rg/J4+a3MC4g0FAPFSBs5zyy/GeWxpX5fHqwbeAZ7G2XK31uXx3Ob3EOC35n8gMAePtzzv1zOdc4/swdlH9ODofbuSnta+t9nqujivfVzF9FmVvDC7grpGz1/OTcBYoMrrgcVbCgBi01icCwePBKbi7Inf0QexJID1wHycq/ln4ZzTDNon/b3xawjwW/PPwFn6n+DVgAePy+W75/flvCN7kpFu5q21sjbOI69t5ffTSli9qclIzTb6K86DkSTEFADET9JxQsAIYCSQB+TiPN88B+fntQ7nwUR1OJ/wV+PsSlgEePoOaZHfQoDfmj/ArThb/bpu3NAs7vr2QE47pLtrYzS3JHnw1VJuKyxmc3mLa+N8SQI4DPjAi8HEDgUAkWCK4XxK+5blefix+Q8AVuHyFe2ZGSn8+poCbjw/n7RUb95KK2pa+eF963n431tJun+ZwBycECAhpccBiwTXK0A/nNMnNvix+YOz1e+hbg4weUQ2r909irMO70FKinefo7K6pHDW4T2YMiqHGR9V09js6ks/CPgQJ0xJCGkFQCTYbK0E+LX5D8E5JZTh1gBnHd6dx362DzmZdu90LCpu4owfr2TpmgY3h/kYOAjnFkEJGa0AiASf1ysBfm3+AL8FDnCr+A3n9qXw/w2ni6GL/DqjR9c0Lj6uJ/9ZUMPGra5dF1CAEwJWujWA2GP/p1hETPBqJcDPzb8fsI6O30myR9ef05c/3TiEmM/eNWvq4xzzveV8srzOrSFmAKe4VVzs8ctuXSLSOUmcR7v+zcUx/Nz8wXkypSvN//KTevuy+QN0zU7l1d+MZERBF7eGOBHn7hwJGZ0CEAkXt04H+L35x3C2IO5luvB+I7N5/tcj2r2hj5dyslI5bkoehTO20tJq/HR9DGcTrXdMFxa7FABEwsd0CPB78wfnaX/Gt/zt0TWNmX8cQ69uaaZLG9e3RzoDemfwwuxKN8qPAH6PLgYMFZ0CEAkfk6cDgtD8Aa5yo+g91w9iUF/Xbigw7qpTenPKQd3cKD0AZ2tlCREFAJFwMhECgtL8U4CTTRc9fv88rjy5t+myrvvLTUPI6uLKW/sZbhQVexQARMIribOf+x20b+k2CdxOMJo/wH5AH5MFYzG467pBvrzob2+G9e/Cd8525Tlbp7tRVOxRABAJtwTwE+BMYFkbvn4Jzhv9/xKM5g/OVepGnXtkD/YbmW26rGduuaSfGxsVTcLZHVBCQgFAJBpeBibiBIG/AfOA4m3HJ8D9OEu8k4BXLc2xo4wHgB9d2t90SU/17ZHOZScavyECnF0BJSQCuMAlIvKFNKAGyDRVcN8R2cx/cLypctbMW1HP/t9cYrrsncCPTRcVO7QCICJBNhyDzR/gG6cG78K/XZkyKptxQ40/EHF/0wXFHgUAEQmycaYLnnFYd9MlrTn9EOPfyxTTBcUeBQARCTKjAWDUoEyG9nNtS13PnXxQnumSvYAepouKHQoAIhJkRgPAMft1NVnOuqmjc0gx/y5fYLyiWKEAICJBZrQZjTd/ztyqrtmpjBpo9BIJUAAIDQUAEQkyo2vcLlw0Z90+BQoAsmsKACISZEYDwOD84Oz731YD+xh/QnI4bpMQBQARCTSjJ+3zcsL3gNS+PYwHAOMFxQ4FABEJMqMrAF2zwhcA0lKN7/fm/2cjS5soAIhIkBl9Dwviw3/2JtX8u7xWAEJCAUBEgqzRZLGGpqA8/6jtauqNf09GX3OxRwFARILMaDMqq241Wc4XKmqMf09VpguKHQoAIhJklSaLrStpNlnOFzaUGv+ejL7mYo8CgIgE2SaTxVZuCN/q9rK1xr+nCtMFxQ4FABEJss0mi81bUW+ynHXVdXHWljSZLrvGdEGxQwFARIJstcliHyytNVnOutmLakmYvQYwCXxutKJYowAgIkG2zGSxxasb3Dhnbs0786tNl9wANJguKnYoAIhIkC01WSyZhJfmhOMat2QSnp1p/HS90cAldikAiEiQLQGMnuR+ZEaZyXLWvL+kltWbjJ///9B0QbFHAUBEgqwRmGey4AdLa1lUFPxV7vumb3Gj7PtuFBU7tKcz9Nh2iEgwfQYcYrLgXU9s4l8/HW6ypKc2lDbz9DvlbpQuBYL7wnxVBRG/pTGEO1/vVX/gKuBsYCJg/GHZIhJsaakxFhVOYMzgYL49XHv3Gh54udT2NIKgEVgITAcexvBtpX4XpQCQBvwUuBnIsTwXEfG5Uw/uxiu/GWV7Gu22qKiB/a5eQjyRtD2VoKkF7gL+D4hbnosnwvfsy13rhpPwrgYyLM9FRAJg5YYmJu2TzdghWban0mbxRJJz/3cV67aE51ZGD2UAxwAHAS9i+OJSP4rCRYBpwNPAibYnIiLB8u171lBS0WJ7Gm12z1ObeX9JuDYzsuAk4Cki8AE59N8g8DOcT/4iIu1S35hg7eZmLjimp+2p7NXydY1c/MsiWuNa+jdgBNAMzLI9ETeFfQWgP845fxGRDpn2n3JmL/L/p+pb7l9PY7PZfX8j7kdAvu1JuCnsAeAqdMGfiHTSX54vsT2FPVqzuYmX3w/HDoY+0hW40vYk3BT2AHCW7QmISPDN+LDK11fV//vDKtMP/RFHqHtI2APARNsTEJHgq6yNs6HUvxcDLg7BzoU+Ndn2BNwU5gDQAwjO/Tsi4mtbK/0bALZWtdqeQlhlA91tT8ItYQ4A2bYnICLhkZnh37fLLulR2tPNc6G9jsy/P9EiIj4Ri8HQ/l1sT2O3hvl4buJfCgAiInsxZVQOOZn+fbs8YnJX21OQAPLvT7SIiE9ceIy/Hxh61OSu9O+VbnsaEjAKACIie9CjaxrXnNbH9jT2KD0txvcuCPWeNeICBQARkT2481sD6ZmXZnsae3Xj+f0YN1Q3PknbKQCIiOzGFSf35toz/P3pf7su6TGeuW2fQIQV8QcFABGRXfjm6X148EdDbU+jXcYOyeKte0czsI+eei57pwAgIvIlg/pm8PjPh/P3m4eSmhK8++v3HZHNvH+M56pTepOid3jZg+D9dLddAbDBVLHUWApDuvv/kaAiAEUVW43WGz4g3PeZ9+yaxqR9sjj14O6ccWh3MkKysc7akmYef6OMWQtrWFvSHImnBa4raTb9SOSBwEaTBf0iHD/lu2Y0AAzo2o2NN91hqpyIq2K3fcdoveTMA4zWE3HLwPM+ZePWZqMlCWkA0AKRiIhIBCkAiIiIRJACgIiISAQpAIiIiESQAoCIiEgEKQCIiIhEkAKAiIhIBCkAiIiIRJACgIiISAQpAIiIiESQAoCIiEgEKQCIiIhEkAKAiIhIBCkAiIiIRJACgIiISAQpAIiIiESQAoCIiEgEKQCIiIhEkAKAiIhIBCkAiIiIRJACgIiISAQpAIiIiESQAoCIiEgEKQCIiIhEkAKAiIhIBCkAiIiIRJACgIiISAQpAIiIiESQAoCIiEgEKQCIiIhEkAKAiIhIBCkAiIiIRJACgIiISAQpAIiIiERQmu0JiMh/xZMJqpsav/JnqbEU8rpkWpqRiISVAoCIxxpaW1iweT2fbFrHgs0bKK6pYmNNJVvqathSV0Mimdzp73RJTaNPTi79c7uRn5vHuN79mJRfwKT8gYzpnU96SqqF70REgkwBQMRlrYkE765dyYsrFvLOmhUsLd1EayLRrhpN8VY2VFeyoboSgJdXLPri/2WkpnHIwGGctM84TtpnHPv1H2h0/iISTgoAIi6IJxO8vGIx05bO49WVi6lorHdtrOZ4KzPXrmTm2pX85O0X6JvT1bWxRCQ8FABEDNpSV8PDC97n/k9msaayzNocRET2RgFAxIA1lWX8cuYrPLF4Lk3xVtvTERHZKwUAkU4oa6jj7jlv8IcP36GxtcX2dERE2kwBQKQDWhMJfvv+G9wx+7WdbtsTEQkCBQCRdlpSuomrXniEj4vX2p6KiEiHKQCItFFrIsFdc17ntpmv6jy/iASeAoBIG5Q11HHRM//grdXLbU9FRMQIBQCRvVhYspGzn7qf1ZZu6xMRcYMCgMgePLtsPldM/yd1Lc22pyIiYpQCgMhuPLF4LpdPL2z3tr0iIkGgACCyCw8tmMM3X3pslw/mEREJgxTbExDxmwfmvafmLyKhpwAg8iWvrFzMda88oeYvIqGnACCyzfzN67nomX8QT+qcv4iEnwKACFBcU8VZT96vq/1FJDIUACTyWhJxzn7qftZXV9ieioiIZ3QXgETeL2e+4qt9/XMyU8hITyEWg3g8SVVd3Op80lJjVscXEXcoAEikzVlfxJ2zX7c2/vhhWRwxqSuHTchl9OBMhg/oQq+8r/5axhNJtlS0snRNA4tXNzB7UQ1vzq2mstabYNAzT28TImGk32yJrJrmRi6f/k/PL/obPTiTy07oxSXH92KfAV32+vWpKTH690qnf690jts/jxvPzyeeSDJzQQ0P/3srz86soKHJve9h/NAs12qLiD0KABJZv3r333xeUerZeIdNzOWWS/pz+iHdSenk1TepKTGOnZLHsVPy+P3/tPL7aSX8+bkSV1YFTpiaZ7ymiNiniwAlkj6vKOWPH77jyVhD+3Xh2V+NYPafx3LmYZ1v/jvqlZfGr64uoOjJSdx4fr7Rc/aZGSlceUpvY/VExD8UACSSbnnzeZrira6OEYvB9y7IZ+kjEzj3yB6ujgXQo2sav/+fwcx/cDz7jcw2UvOmC/Pp3yvdSC0R8RcFAImcd9eu4rllC1wdo0/3NP591yjuvWEwWV28/TWbMCyL9/86ju9f2I9YJxYDDhmfy61XFpibmIj4igKARM6vZr3qav2RAzOZc984Tjqwm6vj7EmX9Bj3XD+IGXePol/P9n+CP2BMDi/fOZKMdN0CKBJWCgASKQtLNvJW0XLX6k8Zlc37fx3LiIK9X93vhRMP6MbCh9t+CiI1JcYN5/bl3T+N0e1/IiGn33CJlHs/eIsk7jzoZ8KwLF777eid7uO3rU/3NJ791Qje+qSae6eV8ObcKppavvoa9MpL45wje/Dd8/KZOFy3/YlEgb/eqURctKm2iicWz3WldkHvDF6/ZzS9u/n3V+q4/fM4bv886hsTLFvbQEVtnJSYM/eRAzON350gIv7m33crEcMeXfiRK1f+p6fFePLWfQJztXx2Zgr7j86xPQ0RsUyZXyJj2tJ5rtS9+7pBHD4x15XaIiJuUQCQSCiq2Mrc4nXG6x48Lpcbzu1rvK6IiNsUACQSnl76ifGL/9JSYzz4o6GkpuhWOREJHgUAiYSXViwyXvPrJ/ZinB6UIyIBpQAgodfY2sInhpf/09Ni/OIq7ZInIsGlACCh93HxWuNX/59zRA+G5GcYrSki4iUFAAm9OeuLjNf81pl9jNcUEfGSAoCE3gcbVxutN7BPBsfsl2e0poiI1xQAJPRWlG0xWu/Ug7t16il7IiJ+oAAgoZYkydrKMqM1Tz7I3lP+RERMUQCQUNtSV0NdS7PRmgeO1Ta6IhJ8CgASamsqy43W65WXRkFvXf0vIsGnACChVlJbbbTemCGZRuuJiNiiACCh1hhvMVqvT/dgPPFPRGRvFAAk1JrjcaP1euXpCdoiEg4KABJqzYZ3AExP0/1/IhIOCgASai2GVwCamhNG64mI2KIAIKGWnW72iv1GBQARCQkFAAm1Xllm79nfUGr2okIREVsUACTUemXnGq1XVNxktJ6IiC0KABJqplcAisuaqaoze12BiIgNCgASan1yzK4AJJMwZ3Gt0ZoiIjYoAEiodeuSRUHX7kZrzlpYY7SeiIgNCgASepP7DTRab/qsSqP1RERsUACQ0JucX2C03rK1DXy6qt5oTRERrykASOhNMhwAAP752lbjNUVEvKQAIKF3UMEw4zX/8fJWKmt1N4CIBJcCgITesO69GNO7n9GaNfVx/vJ8idGaIiJeUgCQSDh1xHjjNe96YjObyrQzoIgEkwKARMKpIycYr1ldF+enD2wwXldExAsKABIJRwzeh25dsozXLZyxldc/rjJeV0TEbQoAEgkZqWlcOvEA43WTSfj67at1KkBEAkcBQCLj2/sf4UrdLRUtXHrb5zS1JF2p75bWeJJksKYsIgal2Z6AiFcm5RdwyMDhvL+hyHjt/yyo4ao7injsZ/sQixkvb0RZdSuPzCjjhfcqWLCynqq6OKkpMQb2SeeQCblccHRPzji0O+lpPv0GRMQoBQCJlG/tf7grAQDgibfKyctJ5b6bhpLio7W1ZBL+8EwJtz68cacnGcYTSdaWNLO2pJwn3ypnREEXfnfDYM441OzzE0TEf3z0NiXivosnTGVIt56u1f/bi6Vc9uvPaWn1x9p6bUOC83++ipv+vK5NjzFetbGJM3+8kh/8Zb1OD4iEnAKAREqX1DR+cdRpro7xxFvlHP/95dYvDCwqbuKQ65by3LsV7f67v3t6Mzf+cZ0LsxIRv1AAkMi5fPJBxncG3NG7n9Yw5ZolvDG32tVxdufR18uYeu1SFq9u6HCNPz1XwhNvlRmclYj4iQKARE5qLIXbjj7d9XE2l7dw0g+Xc8X/rWZrVavr44Hzqf/sn67k67cXUVHT+TF/8Jf1NDQlDMxMRPxGAUAi6fxx+3HcsNGuj5NMwiOvbWXkpQu59eGNrj1AqHhrCzf9eR1jL1/EC7MrjdXdVNbC0++UG6snIv6hACCRFCPGA2dcRk56hifjVdbG+WVhMUMv/JTv/mEd81fWd7pmIgEzF9Tw9duLGHbxp/x+WgnNLuxF8OJ75gKFiPiHbgOUyBrWvRf/d9xZ3DhjmmdjVtXF+dNzJfzpuRLGDc3ipAPzOGFqNw4Yk0Pvbnv/dVxb0szshTW8+2kNL75XyeZy9y80nLu8zvUxRMR7CgASaTcccDTTls5j9rrPPR976ZoGlq5p4N6nnccK9+6WxpjBmfTqlkbX7FSyu6RQXR+nriHB+i3NrNrYSG2D9+fjt1R4c/2CiHhLAUAiLSUW4+nzr2HqA3dSXGP3oT5bq1qZvajW6hx2pbFZFwGKhJGuAZDI65/bjWnnf5OMVOVhEYkOBQAR4NBBw7n3pPNtT0NExDMKACLbfGfqkdxwwNG2pyEi4gkFAJEv+eMpF/Atlx4bLCLiJwoAIl8SI8Z9p17MZRMPtD0VERFXKQCI7CAlFqPw7Mu5dMIBtqciIuIaBQCRXUiNpfDouVfyi6NOI0bM9nRERIxTABDZjRgxbj3qNB4/7yoy09JtT0dExCgFAJG9uHj8VGZ87Qb653azPRUREWMUAETa4KghI1n6nZ9zyYSptqciImKEAoBIG3XPzOLxc7/BP8++gq4ZmbanIyLSKQoAIu10+aSDWPjtn3LBuCm2pyIi0mEKACIdMLR7L54+/xo+uPoWDh003PZ0RETaTQFApBMOKhjKrCt/wKPnXMmk/ALb0xERaTMFAJFOSonF+NrEA/n0Wz9l1pU/4PRRE7V3gIj4np5/KmLQ4YP34fDB17Fs62YeXfgRzyybx4qyLbanJSKyEwUAEReM7d2P2489k9uPPZNPSzbwzNL5vLpqMQtLNtKaSBgfLyUWY//+gzl15AROHTGegx68y/gYIhIuCgAiLpucP5DJ+QP51TFnUNvcxMfFa5mzvogPN65mVXkpayrLaGhtaXO9zLR0RvTsw6hefZnSbzAHFQzlgIIhdOuS5eJ3ISJhowAg4qHcjC4cM3QUxwwd9ZU/L62vZV1VOZtqqr4SBpriraTGUuiVlUPv7Fzyc7syoGs3XWMgIp2mACDiA32yc+mTnQv9bc9ERKJCdwGIiIhEkAKAiIhIBCkAiIiIRJACgIiISAQpAIiIiESQAoCIiEgEKQCIiIhEkAKAiIhIBCkAiIiIRJACgIiISAQpAIiIiESQAoCIiEgEKQCIiIhEkAKAiIhIBCkAiIiIRJACgIiISAQpAIiIiESQAoCIiEgEKQCIiIhEkAKAiIhIBCkAiIiIRJACgIiISAQpAIiIiERQmANAo9Fira0my4mIiAvqmxLGS5ou6BdhDgA1Ros1NZJIJk2WFBERgxIJqKmPmy5ba7qgX4Q5ADRvO4xoScRZX11hqpyIiBi2tqSJ1rjRD2qNQIvJgn4S5gAAUGWy2MKSjSbLiYiIQYuKGkyXNNpD/CbsAaDIZLF31iw3WU5ERAx6e1616ZJGe4jfhD0AGO3Yzy1bQBJdByAi4jfJJLwwu9J02c9MF/STsAcAo/94a6vKeWf1CpMlRUTEgLfnVbNmc5PpsqFe9g17AFhkuuBdc94wXVJERDrpzsc2uVHWeA/xk7AHgFmA0XtCXvt8Kf9etcRkSRER6YQ35lbz5ifGz/+3ArNNF/WTsAeAKuAT00VvnDGNuhZjdxiKiEgH1TYk+M7v1rhR+mPAeKrwk7AHAIC3TRdcWb6F6155wnRZERFph2QSvvXbNazaaPzcP7jQO/wmCgHgWTeK/mvhh9w68xU3SouISBv8/KGNPP5mmVvlXekdfhKFADAXWOxG4V/OfIX/99Z03RooIuKhZBJufXgjv36k2K0hlgDz3SruF1EIAACPuVX4N++9ziXPPkR1k9FnD4mIyC5U1cW58NZV/LLQteYP8Iibxf0iKgHgEcCVk0QATy35hMl/u50Xli90awgRkch77t0KJl21mGf+4+pzWRqBf7k5gF+k2Z6AR4qBfwLXujXAmsoyzn7qfg4eOIybDzmB00dNICM1Ki+viIg7mlqSvDynkrue2MRHy+q8GPJhwJVNBfwmZnsCHhqOs6uTJ125V1YOp4wYz9FDRzGx7wCG9ehNXpdMuigUiAdit33HaL3kzAOM1hPZlYamBDX1cYo2NbGoqIH/zK9hxkdVlFe3ejWFFmAksNarAW2KUgAAeAi4yvYkRMSsHl3TKOidzhGTunLeUT04bv8821P6io1bm5n2TgWzF9VQVNxETX2cnnlpjByYyTH7deWcI3rQM88fHw4SCZjxURXPz6rgvUW1FG9tpqrO6H5qfvYALq4U+03UAkA+zvMButueiIi459AJufzhu4OZOjrH6jw2l7fwk79v4JHXyogndn+3UE5mCv9zXj4/v2IAWV3sXZo1a2EN3/vTOuatqLc2B4vKgTFAqe2JeCXV9gQ8VgfUAqfanoiIuGf9lmYembGVwfkZTB6RbWUO7y2q5bibljN7US3Jvdwp3NKaZPaiWqbPruS0Q7rTPdf7t+Y/P7eFS28rYuPWFs/H9onvA+/anoSXorYCAE7omQMcaHsiIuKuWAye/MU+XHhMT0/Hnbu8jmO/t5ya+vYvnQ/Jz+CD+8fRr2e6CzPbtb+/VMq3frvGs/F86APgMCBheyJeimIAANgH5xkB3WxPRETclZ2ZwoIHxzNyYKYn49U1Jph01WKKijt+5/Hx++fx+j2jiXnwDj1vRT0HX7eUltbIbmhWCUwBVtueiNeisg/Ajj4HrrE9CRFxX31jgp88sMGz8e59enOnmj/Am59U89KcSkMz2rNb7l8f5eafBK4mgs0fohsAAJ4B7rU9CRFx37MzK1iz2bW9wL7QGk/yl+e3GKl179ObjdTZkwWr6nnL/GN0g+S3wHO2J2FLlAMAwA+IyJaPIlGWTMILs93/RP3h0jo2l5u5iG72olrX73+fPsvVHfX87gng/9mehE1RDwBJnFMBr9meiIi465Pl7u8i98HSWmO1WuNJFhU1GKu3K3OXR/J2P3Ae9XsVEbvob0dRDwDg7Px0PvC67YmIiHuKy9y/vW2T4TE2lDYbrbcjU6sVATMDOBMXnw8jwZMBPI6zKqBDh47wHW/gvrsMz/l8l+c71/B8/X48Cnh3f6XPaQXgv5qBy4C7cX5QRCRcvHjAi+ln1JYYrrcjV5+p6yNJ4A7g6zirvoICwI4SwC3AWTjbQopIeHzswRjvGazVjLNfiZvcru8HZcAZwE/Qhztpo8HATOwvWenQoaPzRwIYgvtiwApDc37Vg/lONjRXvx5vAwONvVoSKTHgcpxlONs/yDp06Oj48STeudrQnE/waL6vG5qvn47NOO/dUd3tVgzqAfweqMf+D7YOHTrad9TibP/tlRSch8p0Zs5ebk6zL84V8bb/nUwcdcA96Imv4oI+wK1ABfZ/0HXo0LH3IwFchPf642wv25E5rwT6ejzfKzo4V78cNcAfcF53EVd1B64FZuG8wdj+4dehQ8fORwPwNewZBHy6i3nt6Vi67e/ZcB3OhYe2/93aeiRwrtO6Bj3YTSwZDtwEvARUYf+XQocOHU5j2A/7MnFuP9vb6cMmnE+w2Xam+YVDgY+w/++3u6MSeAG4ERjqzksQHbpAwqw0nDedicAoYDTOD2keTkLNBbrYmpxIiG0FNuKce38O+I/V2ewsH7gE58K+iTjvBXU4dwy8CfwT/9yTH8OZ5znAYUAB0NOjsRtxrtmoxmn2a4Hl247FwHxXvV49AAAADElEQVQg7tFcQu//A4HRvqfVFRoVAAAAAElFTkSuQmCC"
31 |
--------------------------------------------------------------------------------
/internal/web/webgui.go:
--------------------------------------------------------------------------------
1 | package web
2 |
3 | import (
4 | "log"
5 | "net/http"
6 |
7 | "github.com/aceberg/rediary/internal/auth"
8 | "github.com/aceberg/rediary/internal/check"
9 | "github.com/aceberg/rediary/internal/conf"
10 | "github.com/aceberg/rediary/internal/db"
11 | "github.com/aceberg/rediary/internal/models"
12 | )
13 |
14 | // Gui - start web server
15 | func Gui(config models.Conf) {
16 |
17 | AppConfig, authConf = conf.Get(config.ConfPath)
18 | AppConfig.ConfPath = config.ConfPath
19 | AppConfig.Icon = Icon
20 |
21 | db.Create(AppConfig.DB)
22 | db.Migrate(AppConfig.DB)
23 | AllRecords = db.Select(AppConfig.DB)
24 |
25 | log.Println("INFO: starting web gui with", AppConfig.ConfPath)
26 |
27 | address := AppConfig.Host + ":" + AppConfig.Port
28 | log.Println("=================================== ")
29 | log.Printf("Web GUI at http://%s", address)
30 | log.Println("=================================== ")
31 |
32 | http.HandleFunc("/login/", loginHandler)
33 |
34 | http.HandleFunc("/", auth.Auth(indexHandler, &authConf))
35 | http.HandleFunc("/add_action/", auth.Auth(addActionHandler, &authConf))
36 | http.HandleFunc("/add_record/", auth.Auth(addRecordHandler, &authConf))
37 | http.HandleFunc("/add_tag/", auth.Auth(addTagHandler, &authConf))
38 | http.HandleFunc("/auth_conf/", auth.Auth(authConfHandler, &authConf))
39 | http.HandleFunc("/auth_save/", auth.Auth(saveAuthHandler, &authConf))
40 | http.HandleFunc("/clear/", auth.Auth(clearHandler, &authConf))
41 | http.HandleFunc("/config/", auth.Auth(configHandler, &authConf))
42 | http.HandleFunc("/del_action/", auth.Auth(delActionHandler, &authConf))
43 | http.HandleFunc("/del_record/", auth.Auth(delRecordHandler, &authConf))
44 | http.HandleFunc("/del_tag/", auth.Auth(delTagHandler, &authConf))
45 | http.HandleFunc("/diary/", auth.Auth(diaryHandler, &authConf))
46 | http.HandleFunc("/diary_show/", auth.Auth(diaryShowHandler, &authConf))
47 | http.HandleFunc("/save_colors/", auth.Auth(saveColorsHandler, &authConf))
48 | http.HandleFunc("/save_config/", auth.Auth(saveConfigHandler, &authConf))
49 | http.HandleFunc("/stat/", auth.Auth(statHandler, &authConf))
50 | err := http.ListenAndServe(address, nil)
51 | check.IfError(err)
52 | }
53 |
--------------------------------------------------------------------------------