├── .github └── workflows │ ├── docker-publish.yml │ ├── docker.yml │ └── go.yml ├── .gitignore ├── .gitlab-ci.yml ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── cmd └── v2ray-mu │ └── main.go ├── docker-compose.yml ├── go.mod ├── go.sum ├── pkg └── v2ray-manager │ ├── .gitignore │ ├── errors.go │ ├── manager.go │ ├── manager_test.go │ └── user.go └── server ├── config.go ├── init.go ├── manager.go ├── trojan.go ├── user.go └── utils.go /.github/workflows/docker-publish.yml: -------------------------------------------------------------------------------- 1 | name: Docker 2 | 3 | # This workflow uses actions that are not certified by GitHub. 4 | # They are provided by a third-party and are governed by 5 | # separate terms of service, privacy policy, and support 6 | # documentation. 7 | 8 | on: 9 | push: 10 | branches: [ "master" ] 11 | # Publish semver tags as releases. 12 | tags: [ 'v*.*.*' ] 13 | pull_request: 14 | branches: [ "master" ] 15 | 16 | env: 17 | # Use docker.io for Docker Hub if empty 18 | REGISTRY: ghcr.io 19 | # github.repository as / 20 | IMAGE_NAME: ${{ github.repository }} 21 | 22 | 23 | jobs: 24 | build: 25 | 26 | runs-on: ubuntu-latest 27 | permissions: 28 | contents: read 29 | packages: write 30 | # This is used to complete the identity challenge 31 | # with sigstore/fulcio when running outside of PRs. 32 | id-token: write 33 | 34 | steps: 35 | - name: Checkout repository 36 | uses: actions/checkout@v3 37 | 38 | # Install the cosign tool except on PR 39 | # https://github.com/sigstore/cosign-installer 40 | - name: Install cosign 41 | if: github.event_name != 'pull_request' 42 | uses: sigstore/cosign-installer@v3.3.0 43 | 44 | - name: Set up QEMU 45 | uses: docker/setup-qemu-action@v2 46 | 47 | - name: Set up Docker Buildx 48 | id: buildx 49 | uses: docker/setup-buildx-action@v2 50 | 51 | - name: Available platforms 52 | run: echo ${{ steps.buildx.outputs.platforms }} 53 | 54 | # Login against a Docker registry except on PR 55 | # https://github.com/docker/login-action 56 | - name: Log into registry ${{ env.REGISTRY }} 57 | if: github.event_name != 'pull_request' 58 | uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c 59 | with: 60 | registry: ${{ env.REGISTRY }} 61 | username: ${{ github.actor }} 62 | password: ${{ secrets.GITHUB_TOKEN }} 63 | 64 | # Extract metadata (tags, labels) for Docker 65 | # https://github.com/docker/metadata-action 66 | - name: Extract Docker metadata 67 | id: meta 68 | uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 69 | with: 70 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 71 | 72 | # Build and push Docker image with Buildx (don't push on PR) 73 | # https://github.com/docker/build-push-action 74 | - name: Build and push Docker image 75 | id: build-and-push 76 | uses: docker/build-push-action@v3 77 | with: 78 | platforms: linux/amd64,linux/arm64 79 | context: . 80 | push: ${{ github.event_name != 'pull_request' }} 81 | tags: ${{ steps.meta.outputs.tags }} 82 | labels: ${{ steps.meta.outputs.labels }} 83 | -------------------------------------------------------------------------------- /.github/workflows/docker.yml: -------------------------------------------------------------------------------- 1 | name: docker-ghcr 2 | 3 | # This workflow uses actions that are not certified by GitHub. 4 | # They are provided by a third-party and are governed by 5 | # separate terms of service, privacy policy, and support 6 | # documentation. 7 | 8 | on: 9 | push: 10 | branches: [ "master" ] 11 | # Publish semver tags as releases. 12 | tags: [ 'v*.*.*' ] 13 | pull_request: 14 | branches: [ "master" ] 15 | 16 | env: 17 | # Use docker.io for Docker Hub if empty 18 | REGISTRY: ghcr.io 19 | # github.repository as / 20 | IMAGE_NAME: ${{ github.repository }} 21 | 22 | 23 | jobs: 24 | build: 25 | 26 | runs-on: ubuntu-latest 27 | permissions: 28 | contents: read 29 | packages: write 30 | # This is used to complete the identity challenge 31 | # with sigstore/fulcio when running outside of PRs. 32 | id-token: write 33 | 34 | steps: 35 | - name: Checkout repository 36 | uses: actions/checkout@v3 37 | 38 | # Install the cosign tool except on PR 39 | # https://github.com/sigstore/cosign-installer 40 | - name: Install cosign 41 | if: github.event_name != 'pull_request' 42 | uses: sigstore/cosign-installer@v3.3.0 43 | 44 | 45 | # Workaround: https://github.com/docker/build-push-action/issues/461 46 | - name: Setup Docker buildx 47 | uses: docker/setup-buildx-action@79abd3f86f79a9d68a23c75a09a9a85889262adf 48 | 49 | # Login against a Docker registry except on PR 50 | # https://github.com/docker/login-action 51 | - name: Log into registry ${{ env.REGISTRY }} 52 | if: github.event_name != 'pull_request' 53 | uses: docker/login-action@28218f9b04b4f3f62068d7b6ce6ca5b26e35336c 54 | with: 55 | registry: ${{ env.REGISTRY }} 56 | username: ${{ github.actor }} 57 | password: ${{ secrets.GITHUB_TOKEN }} 58 | 59 | # Extract metadata (tags, labels) for Docker 60 | # https://github.com/docker/metadata-action 61 | - name: Extract Docker metadata 62 | id: meta 63 | uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38 64 | with: 65 | images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} 66 | 67 | # Build and push Docker image with Buildx (don't push on PR) 68 | # https://github.com/docker/build-push-action 69 | - name: Build and push Docker image 70 | id: build-and-push 71 | uses: docker/build-push-action@ac9327eae2b366085ac7f6a2d02df8aa8ead720a 72 | with: 73 | context: . 74 | push: ${{ github.event_name != 'pull_request' }} 75 | tags: ${{ steps.meta.outputs.tags }} 76 | labels: ${{ steps.meta.outputs.labels }} 77 | cache-from: type=gha 78 | cache-to: type=gha,mode=max 79 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | branches: [master] 8 | 9 | jobs: 10 | build: 11 | name: Build 12 | runs-on: ubuntu-latest 13 | steps: 14 | - name: Set up Go 1.x 15 | uses: actions/setup-go@v2 16 | with: 17 | go-version: ^1.24 18 | id: go 19 | 20 | - name: Check out code into the Go module directory 21 | uses: actions/checkout@v2 22 | 23 | - name: Get dependencies 24 | run: | 25 | go get -v -t -d ./... 26 | if [ -f Gopkg.toml ]; then 27 | curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh 28 | dep ensure 29 | fi 30 | 31 | - name: Build 32 | run: make build 33 | 34 | - name: Test 35 | run: go test -v ./... 36 | 37 | #- name: Run golangci-lint 38 | # uses: golangci/golangci-lint-action@v2.5.2 39 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | stages: 2 | - build 3 | - test 4 | - notify 5 | - deploy 6 | 7 | variables: 8 | IMAGE: orvice/mu-sync 9 | 10 | build:bin: 11 | stage: build 12 | image: golang 13 | script: 14 | - go mod download 15 | - make build 16 | 17 | build:docker: 18 | stage: build 19 | image: docker 20 | services: 21 | - docker:dind 22 | before_script: 23 | - docker login -u $CI_REGISTRY_USER -p $CI_JOB_TOKEN $CI_REGISTRY 24 | script: 25 | - docker build -t $CI_REGISTRY/$IMAGE:latest . 26 | - docker push $CI_REGISTRY/$IMAGE:latest 27 | 28 | test: 29 | stage: test 30 | image: golang 31 | allow_failure: true 32 | script: 33 | - go test -v ./... 34 | 35 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.24 as builder 2 | 3 | ARG ARG_GOPROXY 4 | ENV GOPROXY $ARG_GOPROXY 5 | 6 | WORKDIR /home/app 7 | COPY go.mod go.sum ./ 8 | 9 | RUN go mod download 10 | 11 | COPY . . 12 | RUN make build 13 | 14 | 15 | FROM quay.io/orvice/go-runtime:latest 16 | 17 | ENV PROJECT_NAME v2ray-mu 18 | 19 | COPY --from=builder /home/app/bin/${PROJECT_NAME} . 20 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 orvice 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 | .DEFAULT_GOAL := build 2 | 3 | APP_NAME=v2ray-mu 4 | APP_CMD_DIR=cmd/$(APP_NAME) 5 | APP_BINARY=bin/$(APP_NAME) 6 | APP_BINARY_UNIX=bin/$(APP_NAME)_unix_amd64 7 | 8 | all: build 9 | 10 | .PHONY: test 11 | test: ## test 12 | go test -v ./... 13 | 14 | 15 | .PHONY: build 16 | build: ## build 17 | CGO_ENABLED=0 go build -o $(APP_BINARY) -v cmd/$(APP_NAME)/main.go 18 | 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # v2ray-mu 2 | 3 | read usage from [docker-compose](https://github.com/orvice/mu-one/blob/master/docker-compose.yml) -------------------------------------------------------------------------------- /cmd/v2ray-mu/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "log/slog" 6 | "os" 7 | 8 | "github.com/google/gops/agent" 9 | "github.com/orvice/v2ray-mu/server" 10 | "github.com/weeon/utils/process" 11 | ) 12 | 13 | func main() { 14 | server.Init() 15 | 16 | server.InitWebApi() 17 | 18 | um, err := server.NewUserManager() 19 | if err != nil { 20 | slog.Error("NewUserManager failed", 21 | "error", err) 22 | os.Exit(0) 23 | } 24 | 25 | for _, v := range um { 26 | go func(v *server.UserManager) { 27 | _ = v.Run() 28 | }(v) 29 | } 30 | 31 | go func() { 32 | if err := agent.Listen(agent.Options{}); err != nil { 33 | log.Fatal(err) 34 | } 35 | }() 36 | 37 | process.WaitSignal() 38 | } 39 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "2" 2 | 3 | services: 4 | v2ray-mu: 5 | image: orvice/v2ray-mu 6 | restart: always 7 | volumes: 8 | - ./log:/var/log 9 | environment: 10 | - MU_URI=https://demo.sspanel.xyz/mu/v2/ 11 | - MU_NODE_ID=1 12 | - MU_TOKEN=forLove 13 | container_name: v2ray-mu 14 | network_mode: host 15 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/orvice/v2ray-mu 2 | 3 | require ( 4 | github.com/catpie/musdk-go v0.0.0-20230815021801-7d27a00f9c60 5 | github.com/google/gops v0.3.22 6 | github.com/p4gefau1t/trojan-go v0.10.6 7 | github.com/v2fly/v2ray-core/v5 v5.16.1 8 | github.com/weeon/log v0.0.0-20230815031624-ca3ca7b87ee5 9 | github.com/weeon/utils v0.0.0-20210724174708-113b40b2e152 10 | google.golang.org/grpc v1.63.2 11 | ) 12 | 13 | require ( 14 | github.com/cespare/xxhash/v2 v2.2.0 // indirect 15 | github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 // indirect 16 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect 17 | github.com/go-sql-driver/mysql v1.6.0 // indirect 18 | github.com/gofrs/uuid v4.0.0+incompatible // indirect 19 | github.com/golang/protobuf v1.5.4 // indirect 20 | github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 // indirect 21 | github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e // indirect 22 | github.com/weeon/contract v0.0.0-20190520152601-a4ee53bdb563 // indirect 23 | github.com/xtaci/smux v1.5.24 // indirect 24 | go.uber.org/atomic v1.7.0 // indirect 25 | go.uber.org/multierr v1.6.0 // indirect 26 | go.uber.org/zap v1.18.1 // indirect 27 | golang.org/x/crypto v0.36.0 // indirect 28 | golang.org/x/net v0.38.0 // indirect 29 | golang.org/x/sys v0.31.0 // indirect 30 | golang.org/x/text v0.23.0 // indirect 31 | golang.org/x/time v0.5.0 // indirect 32 | gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect 33 | gopkg.in/yaml.v3 v3.0.1 // indirect 34 | ) 35 | 36 | require ( 37 | github.com/adrg/xdg v0.4.0 // indirect 38 | github.com/nats-io/nats.go v1.11.1-0.20210623165838-4b75fc59ae30 // indirect 39 | github.com/nats-io/nkeys v0.3.0 // indirect 40 | github.com/nats-io/nuid v1.0.1 // indirect 41 | github.com/pires/go-proxyproto v0.7.0 // indirect 42 | github.com/pkg/errors v0.9.1 // indirect 43 | github.com/redis/go-redis/v9 v9.0.5 // indirect 44 | github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb // indirect 45 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect 46 | google.golang.org/protobuf v1.34.0 // indirect 47 | gopkg.in/yaml.v2 v2.4.0 // indirect 48 | ) 49 | 50 | go 1.23.0 51 | 52 | toolchain go1.24.1 53 | -------------------------------------------------------------------------------- /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 | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= 4 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= 5 | github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= 6 | github.com/adrg/xdg v0.4.0 h1:RzRqFcjH4nE5C6oTAxhBtoE2IRyjBSa62SCbyPidvls= 7 | github.com/adrg/xdg v0.4.0/go.mod h1:N6ag73EX4wyxeaoeHctc1mas01KZgsj5tYiAIwqJE/E= 8 | github.com/aead/cmac v0.0.0-20160719120800-7af84192f0b1 h1:+JkXLHME8vLJafGhOH4aoV2Iu8bR55nU6iKMVfYVLjY= 9 | github.com/aead/cmac v0.0.0-20160719120800-7af84192f0b1/go.mod h1:nuudZmJhzWtx2212z+pkuy7B6nkBqa+xwNXZHL1j8cg= 10 | github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU= 11 | github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY= 12 | github.com/andybalholm/brotli v1.0.6 h1:Yf9fFpf49Zrxb9NlQaluyE92/+X7UVHlhMNJN2sxfOI= 13 | github.com/andybalholm/brotli v1.0.6/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= 14 | github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= 15 | github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8= 16 | github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= 17 | github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d h1:zsO4lp+bjv5XvPTF58Vq+qgmZEYZttJK+CWtSZhKenI= 18 | github.com/boljen/go-bitmap v0.0.0-20151001105940-23cd2fb0ce7d/go.mod h1:f1iKL6ZhUWvbk7PdWVmOaak10o86cqMUYEmn1CZNGEI= 19 | github.com/bsm/ginkgo/v2 v2.7.0 h1:ItPMPH90RbmZJt5GtkcNvIRuGEdwlBItdNVoyzaNQao= 20 | github.com/bsm/ginkgo/v2 v2.7.0/go.mod h1:AiKlXPm7ItEHNc/2+OkrNG4E0ITzojb9/xWzvQ9XZ9w= 21 | github.com/bsm/gomega v1.26.0 h1:LhQm+AFcgV2M0WyKroMASzAzCAJVpAxQXv4SaI9a69Y= 22 | github.com/bsm/gomega v1.26.0/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0= 23 | github.com/bufbuild/protocompile v0.10.0 h1:+jW/wnLMLxaCEG8AX9lD0bQ5v9h1RUiMKOBOT5ll9dM= 24 | github.com/bufbuild/protocompile v0.10.0/go.mod h1:G9qQIQo0xZ6Uyj6CMNz0saGmx2so+KONo8/KrELABiY= 25 | github.com/catpie/musdk-go v0.0.0-20230815021801-7d27a00f9c60 h1:2PpsQ5gc13fFhvEG1qtObPAWFveq8TBcL8qbWBuP7cU= 26 | github.com/catpie/musdk-go v0.0.0-20230815021801-7d27a00f9c60/go.mod h1:4W31RomrUPiZpHE9E9biaDASJImNRJDcMjUBJCQQWaY= 27 | github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= 28 | github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 29 | github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= 30 | github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= 31 | github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= 32 | github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= 33 | github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= 34 | github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= 35 | github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= 36 | github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= 37 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 38 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 39 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 40 | github.com/dgryski/go-metro v0.0.0-20200812162917-85c65e2d0165/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= 41 | github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140 h1:y7y0Oa6UawqTFPCDw9JG6pdKt4F9pAhHv0B7FMGaGD0= 42 | github.com/dgryski/go-metro v0.0.0-20211217172704-adc40b04c140/go.mod h1:c9O8+fpSOX1DM8cPNSkX/qsBWdkD4yd2dpciOWQjpBw= 43 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= 44 | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= 45 | github.com/ebfe/bcrypt_pbkdf v0.0.0-20140212075826-3c8d2dcb253a h1:YtdtTUN1iH97s+6PUjLnaiKSQj4oG1/EZ3N9bx6g4kU= 46 | github.com/ebfe/bcrypt_pbkdf v0.0.0-20140212075826-3c8d2dcb253a/go.mod h1:/CZpbhAusDOobpcb9yubw46kdYjq0zRC0Wpg9a9zFQM= 47 | github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 48 | github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= 49 | github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= 50 | github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= 51 | github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= 52 | github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= 53 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= 54 | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= 55 | github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= 56 | github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= 57 | github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= 58 | github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= 59 | github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= 60 | github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= 61 | github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= 62 | github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4= 63 | github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0= 64 | github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 65 | github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= 66 | github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= 67 | github.com/go-ole/go-ole v1.2.6-0.20210915003542-8b1f7f90f6b1/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= 68 | github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= 69 | github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= 70 | github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= 71 | github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= 72 | github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= 73 | github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= 74 | github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= 75 | github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= 76 | github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= 77 | github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= 78 | github.com/go-redis/redis/v8 v8.5.0/go.mod h1:YmEcgBDttjnkbMzDAhDtQxY9yVA7jMN6PCR5HeMvqFE= 79 | github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= 80 | github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= 81 | github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= 82 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= 83 | github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= 84 | github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= 85 | github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= 86 | github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= 87 | github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= 88 | github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= 89 | github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= 90 | github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= 91 | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 92 | github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= 93 | github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= 94 | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= 95 | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= 96 | github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= 97 | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= 98 | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= 99 | github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= 100 | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 101 | github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= 102 | github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= 103 | github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= 104 | github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= 105 | github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= 106 | github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= 107 | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 108 | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= 109 | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 110 | github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 111 | github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= 112 | github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= 113 | github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= 114 | github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= 115 | github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8= 116 | github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo= 117 | github.com/google/gops v0.3.22 h1:lyvhDxfPLHAOR2xIYwjPhN387qHxyU21Sk9sz/GhmhQ= 118 | github.com/google/gops v0.3.22/go.mod h1:7diIdLsqpCihPSX3fQagksT/Ku/y4RL9LHTlKyEUDl8= 119 | github.com/google/pprof v0.0.0-20230602150820-91b7bce49751 h1:hR7/MlvK23p6+lIw9SN1TigNLn9ZnF3W4SYRKq2gAHs= 120 | github.com/google/pprof v0.0.0-20230602150820-91b7bce49751/go.mod h1:Jh3hGz2jkYak8qXPD19ryItVnUgpgeqzdkY/D0EaeuA= 121 | github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= 122 | github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= 123 | github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= 124 | github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= 125 | github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= 126 | github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= 127 | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= 128 | github.com/jhump/protoreflect v1.16.0 h1:54fZg+49widqXYQ0b+usAFHbMkBGR4PpXrsHc8+TBDg= 129 | github.com/jhump/protoreflect v1.16.0/go.mod h1:oYPd7nPvcBw/5wlDfm/AVmU9zH9BgqGCI469pGxfj/8= 130 | github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= 131 | github.com/keybase/go-ps v0.0.0-20190827175125-91aafc93ba19/go.mod h1:hY+WOq6m2FpbvyrI93sMaypsttvaIL5nhVR92dTMUcQ= 132 | github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= 133 | github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= 134 | github.com/klauspost/compress v1.11.12/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= 135 | github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4= 136 | github.com/klauspost/compress v1.17.4/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= 137 | github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg= 138 | github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= 139 | github.com/klauspost/reedsolomon v1.11.7 h1:9uaHU0slncktTEEg4+7Vl7q7XUNMBUOK4R9gnKhMjAU= 140 | github.com/klauspost/reedsolomon v1.11.7/go.mod h1:4bXRN+cVzMdml6ti7qLouuYi32KHJ5MGv0Qd8a47h6A= 141 | github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= 142 | github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= 143 | github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= 144 | github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= 145 | github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= 146 | github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= 147 | github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= 148 | github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= 149 | github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= 150 | github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= 151 | github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40 h1:EnfXoSqDfSNJv0VBNqY/88RNnhSGYkrHaO0mmFGbVsc= 152 | github.com/lunixbochs/struc v0.0.0-20200707160740-784aaebc1d40/go.mod h1:vy1vK6wD6j7xX6O6hXe621WabdtNkou2h7uRtTfRMyg= 153 | github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= 154 | github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0= 155 | github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY= 156 | github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= 157 | github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= 158 | github.com/mustafaturan/bus v1.0.2 h1:2x3ErwZ0uUPwwZ5ZZoknEQprdaxr68Yl3mY8jDye1Ws= 159 | github.com/mustafaturan/bus v1.0.2/go.mod h1:h7gfehm8TThv4Dcaa+wDQG7r7j6p74v+7ftr0Rq9i1Q= 160 | github.com/mustafaturan/monoton v1.0.0 h1:8SCej+JiNn0lyps7V+Jzc1CRAkDR4EZPWrTupQ61YCQ= 161 | github.com/mustafaturan/monoton v1.0.0/go.mod h1:FOnE7NV3s3EWPXb8/7+/OSdiMBbdlkV0Lz8p1dc+vy8= 162 | github.com/nats-io/jwt v1.2.2 h1:w3GMTO969dFg+UOKTmmyuu7IGdusK+7Ytlt//OYH/uU= 163 | github.com/nats-io/jwt v1.2.2/go.mod h1:/xX356yQA6LuXI9xWW7mZNpxgF2mBmGecH+Fj34sP5Q= 164 | github.com/nats-io/jwt/v2 v2.0.3 h1:i/O6cmIsjpcQyWDYNcq2JyZ3/VTF8SJ4JWluI5OhpvI= 165 | github.com/nats-io/jwt/v2 v2.0.3/go.mod h1:VRP+deawSXyhNjXmxPCHskrR6Mq50BqpEI5SEcNiGlY= 166 | github.com/nats-io/nats-server/v2 v2.3.4 h1:WcNa6HDFX8gjZPHb8CJ9wxRHEjJSlhWUb/MKb6/mlUY= 167 | github.com/nats-io/nats-server/v2 v2.3.4/go.mod h1:3mtbaN5GkCo/Z5T3nNj0I0/W1fPkKzLiDC6jjWJKp98= 168 | github.com/nats-io/nats.go v1.11.1-0.20210623165838-4b75fc59ae30 h1:9GqilBhZaR3xYis0JgMlJjNw933WIobdjKhilXm+Vls= 169 | github.com/nats-io/nats.go v1.11.1-0.20210623165838-4b75fc59ae30/go.mod h1:BPko4oXsySz4aSWeFgOHLZs3G4Jq4ZAyE6/zMCxRT6w= 170 | github.com/nats-io/nkeys v0.2.0/go.mod h1:XdZpAbhgyyODYqjTawOnIOI7VlbKSarI9Gfy1tqEu/s= 171 | github.com/nats-io/nkeys v0.3.0 h1:cgM5tL53EvYRU+2YLXIK0G2mJtK12Ft9oeooSZMA2G8= 172 | github.com/nats-io/nkeys v0.3.0/go.mod h1:gvUNGjVcM2IPr5rCsRsC6Wb3Hr2CQAm08dsxtV6A5y4= 173 | github.com/nats-io/nuid v1.0.1 h1:5iA8DT8V7q8WK2EScv2padNa/rTESc1KdnPw4TC2paw= 174 | github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= 175 | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= 176 | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= 177 | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= 178 | github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4= 179 | github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= 180 | github.com/onsi/ginkgo/v2 v2.10.0 h1:sfUl4qgLdvkChZrWCYndY2EAu9BRIw1YphNAzy1VNWs= 181 | github.com/onsi/ginkgo/v2 v2.10.0/go.mod h1:UDQOh5wbQUlMnkLfVaIUMtQ1Vus92oM+P2JX1aulgcE= 182 | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= 183 | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= 184 | github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= 185 | github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= 186 | github.com/p4gefau1t/trojan-go v0.10.6 h1:nCXHM+uV61rj4KKMNXPqBZBkz8GoR6sAjOUH00AmB34= 187 | github.com/p4gefau1t/trojan-go v0.10.6/go.mod h1:UIfweBPVjNP/F4+lnfdtlw2OmdlDJnVnF50DUFwte8k= 188 | github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= 189 | github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= 190 | github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= 191 | github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= 192 | github.com/pion/dtls/v2 v2.2.7 h1:cSUBsETxepsCSFSxC3mc/aDo14qQLMSL+O6IjG28yV8= 193 | github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s= 194 | github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY= 195 | github.com/pion/logging v0.2.2/go.mod h1:k0/tDVsRCX2Mb2ZEmTqNa7CWsQPc+YYCB7Q+5pahoms= 196 | github.com/pion/randutil v0.1.0 h1:CFG1UdESneORglEsnimhUjf33Rwjubwj6xfiOXBa3mA= 197 | github.com/pion/randutil v0.1.0/go.mod h1:XcJrSMMbbMRhASFVOlj/5hQial/Y8oH/HVo7TBZq+j8= 198 | github.com/pion/sctp v1.8.7 h1:JnABvFakZueGAn4KU/4PSKg+GWbF6QWbKTWZOSGJjXw= 199 | github.com/pion/sctp v1.8.7/go.mod h1:g1Ul+ARqZq5JEmoFy87Q/4CePtKnTJ1QCL9dBBdN6AU= 200 | github.com/pion/transport/v2 v2.2.5 h1:iyi25i/21gQck4hfRhomF6SktmUQjRsRW4WJdhfc3Kc= 201 | github.com/pion/transport/v2 v2.2.5/go.mod h1:q2U/tf9FEfnSBGSW6w5Qp5PFWRLRj3NjLhCCgpRK4p0= 202 | github.com/pires/go-proxyproto v0.7.0 h1:IukmRewDQFWC7kfnb66CSomk2q/seBuilHBYFwyq0Hs= 203 | github.com/pires/go-proxyproto v0.7.0/go.mod h1:Vz/1JPY/OACxWGQNIRY2BeyDmpoaWmEP40O9LbuiFR4= 204 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 205 | github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= 206 | github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= 207 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 208 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 209 | github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= 210 | github.com/quic-go/quic-go v0.43.0 h1:sjtsTKWX0dsHpuMJvLxGqoQdtgJnbAPWY+W+5vjYW/g= 211 | github.com/quic-go/quic-go v0.43.0/go.mod h1:132kz4kL3F9vxhW3CtQJLDVwcFe5wdWeJXXijhsO57M= 212 | github.com/redis/go-redis/v9 v9.0.5 h1:CuQcn5HIEeK7BgElubPP8CGtE0KakrnbBSTLjathl5o= 213 | github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= 214 | github.com/refraction-networking/utls v1.6.5 h1:Jlfqgs/t1Uy6FHHQ8Fz9ZTrRmP/zS7d/NZw7BLahaL8= 215 | github.com/refraction-networking/utls v1.6.5/go.mod h1:BC3O4vQzye5hqpmDTWUqi4P5DDhzJfkV1tdqtawQIH0= 216 | github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3 h1:f/FNXud6gA3MNr8meMVVGxhp+QBTqY91tM8HjEuMjGg= 217 | github.com/riobard/go-bloom v0.0.0-20200614022211-cdc8013cb5b3/go.mod h1:HgjTstvQsPGkxUsCd2KWxErBblirPizecHcpD3ffK+s= 218 | github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= 219 | github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= 220 | github.com/secure-io/siv-go v0.0.0-20180922214919-5ff40651e2c4 h1:zOjq+1/uLzn/Xo40stbvjIY/yehG0+mfmlsiEmc0xmQ= 221 | github.com/secure-io/siv-go v0.0.0-20180922214919-5ff40651e2c4/go.mod h1:aI+8yClBW+1uovkHw6HM01YXnYB8vohtB9C83wzx34E= 222 | github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb h1:XfLJSPIOUX+osiMraVgIrMR27uMXnRJWGm1+GL8/63U= 223 | github.com/seiflotfy/cuckoofilter v0.0.0-20220411075957-e3b120b3f5fb/go.mod h1:bR6DqgcAl1zTcOX8/pE2Qkj9XO00eCNqmKb7lXP8EAg= 224 | github.com/shirou/gopsutil/v3 v3.21.9/go.mod h1:YWp/H8Qs5fVmf17v7JNZzA0mPJ+mS2e9JdiUF9LlKzQ= 225 | github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= 226 | github.com/streadway/amqp v1.0.0/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= 227 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 228 | github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 229 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 230 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= 231 | github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= 232 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 233 | github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 234 | github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= 235 | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= 236 | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 237 | github.com/tklauser/go-sysconf v0.3.9/go.mod h1:11DU/5sG7UexIrp/O6g35hrWzu0JxlwQ3LSFUzyeuhs= 238 | github.com/tklauser/numcpus v0.3.0/go.mod h1:yFGUr7TUHQRAhyqBcEg0Ge34zDBAsIvJJcyE6boqnA8= 239 | github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf h1:7PflaKRtU4np/epFxRXlFhlzLXZzKFrH5/I4so5Ove0= 240 | github.com/txthinking/runnergroup v0.0.0-20210608031112-152c7c4432bf/go.mod h1:CLUSJbazqETbaR+i0YAhXBICV9TrKH93pziccMhmhpM= 241 | github.com/txthinking/socks5 v0.0.0-20210716140126-fa1f52a8f2da h1:7x8pJcBTdKTBpQbRjZZc9o6CDquXBbvm9UIrR6ZSRJ4= 242 | github.com/txthinking/socks5 v0.0.0-20210716140126-fa1f52a8f2da/go.mod h1:7NloQcrxaZYKURWph5HLxVDlIwMHJXCPkeWPtpftsIg= 243 | github.com/txthinking/x v0.0.0-20210326105829-476fab902fbe h1:gMWxZxBFRAXqoGkwkYlPX2zvyyKNWJpxOxCrjqJkm5A= 244 | github.com/txthinking/x v0.0.0-20210326105829-476fab902fbe/go.mod h1:WgqbSEmUYSjEV3B1qmee/PpP2NYEz4bL9/+mF1ma+s4= 245 | github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= 246 | github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= 247 | github.com/v2fly/BrowserBridge v0.0.0-20210430233438-0570fc1d7d08 h1:4Yh46CVE3k/lPq6hUbEdbB1u1anRBXLewm3k+L0iOMc= 248 | github.com/v2fly/BrowserBridge v0.0.0-20210430233438-0570fc1d7d08/go.mod h1:KAuQNm+LWQCOFqdBcUgihPzRpVXRKzGbTNhfEfRZ4wY= 249 | github.com/v2fly/VSign v0.0.0-20201108000810-e2adc24bf848 h1:p1UzXK6VAutXFFQMnre66h7g1BjRKUnLv0HfmmRoz7w= 250 | github.com/v2fly/VSign v0.0.0-20201108000810-e2adc24bf848/go.mod h1:p80Bv154ZtrGpXMN15slDCqc9UGmfBuUzheDFBYaW/M= 251 | github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e h1:5QefA066A1tF8gHIiADmOVOV5LS43gt3ONnlEl3xkwI= 252 | github.com/v2fly/ss-bloomring v0.0.0-20210312155135-28617310f63e/go.mod h1:5t19P9LBIrNamL6AcMQOncg/r10y3Pc01AbHeMhwlpU= 253 | github.com/v2fly/v2ray-core/v4 v4.42.1 h1:oQwW7dSpzx+nY3SrWw25OXVOcXNtwLFZ6BanqMufYdk= 254 | github.com/v2fly/v2ray-core/v4 v4.42.1/go.mod h1:YrWpRau9RYPHZLJXJIoVHjSXwL5DhGuIlTnA1i9FG98= 255 | github.com/v2fly/v2ray-core/v5 v5.16.1 h1:hIuRzCJhmRYqCA76hGiNLkAHopgbNt91L871wlJ/yUU= 256 | github.com/v2fly/v2ray-core/v5 v5.16.1/go.mod h1:3pWIBTmNagMKpzd9/QicXq/7JZCQt716GsGZdBNmYkU= 257 | github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI= 258 | github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U= 259 | github.com/weeon/contract v0.0.0-20190520152601-a4ee53bdb563 h1:85ZbMhxMMQx5ZVOE/XQPAnWrpXzaEK5E8zsvGNrdFZI= 260 | github.com/weeon/contract v0.0.0-20190520152601-a4ee53bdb563/go.mod h1:Lu4Rx+OfCPH1ljtEpsravnbAYjVCwGKYe1kd1oNIwX0= 261 | github.com/weeon/log v0.0.0-20210217051817-63fe9a730962/go.mod h1:rN93jso34yAuu9dWgUQKtE9EymCBIOzSD+vUifqygOw= 262 | github.com/weeon/log v0.0.0-20230815031624-ca3ca7b87ee5 h1:Uv7QnawePxgZJf64VDVVybD81BPVQU6ngPsZGREPRdQ= 263 | github.com/weeon/log v0.0.0-20230815031624-ca3ca7b87ee5/go.mod h1:93aYjha4mN/waGpck60r2j1glKeereHJr2+QnbA0XbA= 264 | github.com/weeon/utils v0.0.0-20210724174708-113b40b2e152 h1:TKiakS6CgYTOEhygFnghOMeEpNLp30i+J2k3l75Os1g= 265 | github.com/weeon/utils v0.0.0-20210724174708-113b40b2e152/go.mod h1:C6cV42NO0BOhJ6RfnfYrwVwCizpaEKY/Fos+VY6WrZs= 266 | github.com/xiaokangwang/VLite v0.0.0-20220418190619-cff95160a432 h1:I/ATawgO2RerCq9ACwL0wBB8xNXZdE3J+93MCEHReRs= 267 | github.com/xiaokangwang/VLite v0.0.0-20220418190619-cff95160a432/go.mod h1:QN7Go2ftTVfx0aCTh9RXHV8pkpi0FtmbwQw40dy61wQ= 268 | github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0= 269 | github.com/xtaci/smux v1.5.24 h1:77emW9dtnOxxOQ5ltR+8BbsX1kzcOxQ5gB+aaV9hXOY= 270 | github.com/xtaci/smux v1.5.24/go.mod h1:OMlQbT5vcgl2gb49mFkYo6SMf+zP3rcjcwQz7ZU7IGY= 271 | github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 272 | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= 273 | go.opentelemetry.io/otel v0.16.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA= 274 | go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= 275 | go.starlark.net v0.0.0-20230612165344-9532f5667272 h1:2/wtqS591wZyD2OsClsVBKRPEvBsQt/Js+fsCiYhwu8= 276 | go.starlark.net v0.0.0-20230612165344-9532f5667272/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= 277 | go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= 278 | go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= 279 | go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= 280 | go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= 281 | go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0= 282 | go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= 283 | go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= 284 | go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= 285 | go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= 286 | go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= 287 | go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= 288 | go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= 289 | go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= 290 | go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= 291 | go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= 292 | go.uber.org/zap v1.18.1 h1:CSUJ2mjFszzEWt4CdKISEuChVIXGBn3lAPwkRGyVrc4= 293 | go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= 294 | go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35 h1:nJAwRlGWZZDOD+6wni9KVUNHMpHko/OnRwsrCYeAzPo= 295 | go4.org/netipx v0.0.0-20230303233057-f1b76eb4bb35/go.mod h1:TQvodOM+hJTioNQJilmLXu08JNb8i+ccq418+KWu1/Y= 296 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 297 | golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 298 | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= 299 | golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 300 | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= 301 | golang.org/x/crypto v0.0.0-20210314154223-e6e6c4f2bb5b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= 302 | golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 303 | golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34= 304 | golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc= 305 | golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= 306 | golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 h1:Di6/M8l0O2lCLc6VVRWhgCiApHV8MnQurBnFSHsQtNY= 307 | golang.org/x/exp v0.0.0-20230725093048-515e97ebf090/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= 308 | golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= 309 | golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= 310 | golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 311 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= 312 | golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= 313 | golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 314 | golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 315 | golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 316 | golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA= 317 | golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= 318 | golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 319 | golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 320 | golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 321 | golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 322 | golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= 323 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 324 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= 325 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 326 | golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 327 | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= 328 | golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= 329 | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 330 | golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= 331 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 332 | golang.org/x/net v0.38.0 h1:vRMAPTMaeGqVhG5QyLJHqNDwecKTomGeqbnfZyKlBI8= 333 | golang.org/x/net v0.38.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8= 334 | golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= 335 | golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= 336 | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 337 | golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 338 | golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 339 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 340 | golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 341 | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 342 | golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= 343 | golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 344 | golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 345 | golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 346 | golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 347 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 348 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 349 | golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 350 | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 351 | golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 352 | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 353 | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 354 | golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 355 | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 356 | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 357 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 358 | golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 359 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 360 | golang.org/x/sys v0.0.0-20210816074244-15123e1e1f71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 361 | golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 362 | golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 363 | golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= 364 | golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 365 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 366 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 367 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 368 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 369 | golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= 370 | golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= 371 | golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 372 | golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= 373 | golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 374 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 375 | golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 376 | golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= 377 | golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= 378 | golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= 379 | golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= 380 | golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 381 | golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 382 | golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 383 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 384 | golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= 385 | golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 386 | golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= 387 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg= 388 | golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= 389 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 390 | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 391 | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 392 | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 393 | google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= 394 | google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= 395 | google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= 396 | google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= 397 | google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 398 | google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= 399 | google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= 400 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de h1:cZGRis4/ot9uVm639a+rHCUaG0JJHEsdyzSQTMX+suY= 401 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de/go.mod h1:H4O17MA/PE9BsGx3w+a+W2VOLLD1Qf7oJneAoU6WktY= 402 | google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= 403 | google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= 404 | google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= 405 | google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= 406 | google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= 407 | google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0= 408 | google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= 409 | google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= 410 | google.golang.org/grpc v1.63.2 h1:MUeiw1B2maTVZthpU5xvASfTh3LDbxHd6IJ6QQVU+xM= 411 | google.golang.org/grpc v1.63.2/go.mod h1:WAX/8DgncnokcFUldAxq7GeB5DXHDbMF+lLvDomNkRA= 412 | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= 413 | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= 414 | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= 415 | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= 416 | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= 417 | google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 418 | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 419 | google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= 420 | google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= 421 | google.golang.org/protobuf v1.34.0 h1:Qo/qEd2RZPCf2nKuorzksSknv0d3ERwp1vFG38gSmH4= 422 | google.golang.org/protobuf v1.34.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= 423 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 424 | gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 425 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= 426 | gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 427 | gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= 428 | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= 429 | gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= 430 | gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= 431 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= 432 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 433 | gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 434 | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 435 | gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 436 | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 437 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 438 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 439 | gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 440 | gopkg.in/yaml.v3 v3.0.0-20200605160147-a5ece683394c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 441 | gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 442 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 443 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 444 | gvisor.dev/gvisor v0.0.0-20231020174304-b8a429915ff1 h1:qDCwdCWECGnwQSQC01Dpnp09fRHxJs9PbktotUqG+hs= 445 | gvisor.dev/gvisor v0.0.0-20231020174304-b8a429915ff1/go.mod h1:8hmigyCdYtw5xJGfQDJzSH5Ju8XEIDBnpyi8+O6GRt8= 446 | honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 447 | honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= 448 | honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= 449 | lukechampine.com/blake3 v1.3.0 h1:sJ3XhFINmHSrYCgl958hscfIa3bw8x4DqMP3u1YvoYE= 450 | lukechampine.com/blake3 v1.3.0/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k= 451 | rsc.io/goversion v1.2.0/go.mod h1:Eih9y/uIBS3ulggl7KNJ09xGSLcuNaLgmvvqa07sgfo= 452 | -------------------------------------------------------------------------------- /pkg/v2ray-manager/.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.dll 4 | *.so 5 | *.dylib 6 | 7 | # Test binary, build with `go test -c` 8 | *.test 9 | 10 | # Output of the go coverage tool, specifically when used with LiteIDE 11 | *.out 12 | 13 | # Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736 14 | .glide/ 15 | -------------------------------------------------------------------------------- /pkg/v2ray-manager/errors.go: -------------------------------------------------------------------------------- 1 | package v2raymanager 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | ) 7 | 8 | var ( 9 | TODOErr = fmt.Errorf("TODO error ") 10 | ) 11 | 12 | func IsNotFoundError(e error) bool { 13 | if e == nil { 14 | return false 15 | } 16 | return strings.Contains(e.Error(), "not found") 17 | } 18 | 19 | func IsAlreadyExistsError(e error) bool { 20 | if e == nil { 21 | return false 22 | } 23 | return strings.Contains(e.Error(), "already exists") 24 | } 25 | -------------------------------------------------------------------------------- /pkg/v2ray-manager/manager.go: -------------------------------------------------------------------------------- 1 | package v2raymanager 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "log/slog" 8 | "strings" 9 | 10 | "github.com/v2fly/v2ray-core/v5/app/proxyman/command" 11 | statscmd "github.com/v2fly/v2ray-core/v5/app/stats/command" 12 | "github.com/v2fly/v2ray-core/v5/common/protocol" 13 | "github.com/v2fly/v2ray-core/v5/common/serial" 14 | "github.com/v2fly/v2ray-core/v5/proxy/vmess" 15 | "google.golang.org/grpc" 16 | "google.golang.org/grpc/credentials/insecure" 17 | ) 18 | 19 | type Manager struct { 20 | client command.HandlerServiceClient 21 | statsClient statscmd.StatsServiceClient 22 | 23 | inBoundTag string 24 | logger *slog.Logger 25 | } 26 | 27 | const ( 28 | UplinkFormat = "user>>>%s>>>traffic>>>uplink" 29 | DownlinkFormat = "user>>>%s>>>traffic>>>downlink" 30 | ) 31 | 32 | type TrafficInfo struct { 33 | Up, Down int64 34 | } 35 | 36 | func NewManager(addr, tag string, l *slog.Logger) (*Manager, error) { 37 | slog.Info("create new mgr", "addr", addr) 38 | cc, err := grpc.Dial(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) 39 | if err != nil { 40 | slog.Error("grpc dail failed", "addr", addr) 41 | return nil, err 42 | } 43 | client := command.NewHandlerServiceClient(cc) 44 | statsClient := statscmd.NewStatsServiceClient(cc) 45 | m := &Manager{ 46 | client: client, 47 | statsClient: statsClient, 48 | inBoundTag: tag, 49 | logger: l, 50 | } 51 | if m.logger == nil { 52 | m.logger = slog.New(slog.NewJSONHandler(io.Discard, &slog.HandlerOptions{})) 53 | } 54 | return m, nil 55 | } 56 | 57 | func (m *Manager) SetLogger(l *slog.Logger) { 58 | m.logger = l 59 | } 60 | 61 | // return is exist,and error 62 | func (m *Manager) AddUser(ctx context.Context, u User) (bool, error) { 63 | resp, err := m.client.AlterInbound(ctx, &command.AlterInboundRequest{ 64 | Tag: m.inBoundTag, 65 | Operation: serial.ToTypedMessage(&command.AddUserOperation{ 66 | User: &protocol.User{ 67 | Level: u.GetLevel(), 68 | Email: u.GetEmail(), 69 | Account: serial.ToTypedMessage(&vmess.Account{ 70 | Id: u.GetUUID(), 71 | AlterId: u.GetAlterID(), 72 | SecuritySettings: &protocol.SecurityConfig{Type: protocol.SecurityType_AUTO}, 73 | }), 74 | }, 75 | }), 76 | }) 77 | if err != nil && !IsAlreadyExistsError(err) { 78 | m.logger.Error("failed to call add user", 79 | "resp", resp, 80 | "error", err, 81 | ) 82 | return false, err 83 | } 84 | return IsAlreadyExistsError(err), nil 85 | } 86 | 87 | func (m *Manager) RemoveUser(ctx context.Context, u User) error { 88 | resp, err := m.client.AlterInbound(ctx, &command.AlterInboundRequest{ 89 | Tag: m.inBoundTag, 90 | Operation: serial.ToTypedMessage(&command.RemoveUserOperation{ 91 | Email: u.GetEmail(), 92 | }), 93 | }) 94 | if err != nil { 95 | m.logger.Error("failed to call remove user : ", "error", err) 96 | return TODOErr 97 | } 98 | m.logger.Debug("call remove user resp: ", "resp", resp) 99 | 100 | return nil 101 | } 102 | 103 | // @todo error handle 104 | func (m *Manager) GetTrafficAndReset(ctx context.Context, u User) (TrafficInfo, error) { 105 | ti := TrafficInfo{} 106 | up, err := m.statsClient.GetStats(ctx, &statscmd.GetStatsRequest{ 107 | Name: fmt.Sprintf(UplinkFormat, u.GetEmail()), 108 | Reset_: true, 109 | }) 110 | if err != nil && !IsNotFoundError(err) { 111 | m.logger.Error("get traffic user ", "u", u, "error", err) 112 | return ti, err 113 | } 114 | 115 | down, err := m.statsClient.GetStats(ctx, &statscmd.GetStatsRequest{ 116 | Name: fmt.Sprintf(DownlinkFormat, u.GetEmail()), 117 | Reset_: true, 118 | }) 119 | if err != nil && !IsNotFoundError(err) { 120 | m.logger.Error("get traffic user fail", 121 | "user", u, 122 | "error", err) 123 | return ti, nil 124 | } 125 | 126 | if up != nil { 127 | ti.Up = up.Stat.Value 128 | } 129 | if down != nil { 130 | ti.Down = down.Stat.Value 131 | } 132 | return ti, nil 133 | } 134 | 135 | type UserData struct { 136 | User User 137 | TrafficInfo TrafficInfo 138 | } 139 | 140 | func (m *Manager) GetUserList(ctx context.Context, reset bool) ([]UserData, error) { 141 | resp, err := m.statsClient.QueryStats(ctx, &statscmd.QueryStatsRequest{ 142 | Reset_: reset, 143 | }) 144 | if err != nil { 145 | return nil, err 146 | } 147 | 148 | var users = make(map[string]UserData) 149 | 150 | for _, v := range resp.Stat { 151 | 152 | email := getEmailFromStatName(v.GetName()) 153 | uuid := getUUDIFromEmail(email) 154 | 155 | if _, ok := users[uuid]; !ok { 156 | users[uuid] = UserData{ 157 | TrafficInfo: TrafficInfo{}, 158 | } 159 | } 160 | 161 | u := user{ 162 | email: email, 163 | uuid: uuid, 164 | } 165 | ti := users[uuid].TrafficInfo 166 | 167 | if strings.Contains(v.GetName(), "downlink") { 168 | ti.Down = v.Value 169 | } else { 170 | ti.Up = v.Value 171 | } 172 | 173 | users[uuid] = UserData{ 174 | User: u, 175 | TrafficInfo: ti, 176 | } 177 | 178 | } 179 | 180 | var data = make([]UserData, 0, len(users)) 181 | for _, v := range users { 182 | data = append(data, v) 183 | } 184 | 185 | return data, nil 186 | } 187 | 188 | func getEmailFromStatName(s string) string { 189 | arr := strings.Split(s, ">>>") 190 | if len(arr) > 1 { 191 | return arr[1] 192 | } 193 | return s 194 | } 195 | 196 | func getUUDIFromEmail(s string) string { 197 | arr := strings.Split(s, "@") 198 | if len(arr) > 0 { 199 | return arr[0] 200 | } 201 | return s 202 | } 203 | -------------------------------------------------------------------------------- /pkg/v2ray-manager/manager_test.go: -------------------------------------------------------------------------------- 1 | package v2raymanager 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "log/slog" 7 | "os" 8 | "testing" 9 | ) 10 | 11 | func TestManager(t *testing.T) { 12 | addr := os.Getenv("ADDR") 13 | l := slog.New(slog.NewJSONHandler(io.Discard, &slog.HandlerOptions{})) 14 | cli, err := NewManager(addr, "api", l) 15 | 16 | if err != nil { 17 | t.Error(err) 18 | return 19 | } 20 | resp, err := cli.GetUserList(context.Background(), false) 21 | if err != nil { 22 | t.Error(err) 23 | return 24 | } 25 | 26 | t.Logf("len %d", len(resp)) 27 | 28 | for _, v := range resp { 29 | t.Log(v.User.GetUUID(), v.TrafficInfo.Down, v.TrafficInfo.Up) 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /pkg/v2ray-manager/user.go: -------------------------------------------------------------------------------- 1 | package v2raymanager 2 | 3 | type User interface { 4 | GetEmail() string 5 | GetUUID() string 6 | GetAlterID() uint32 7 | GetLevel() uint32 8 | } 9 | 10 | var _ User = user{} 11 | 12 | type user struct { 13 | email string 14 | uuid string 15 | alterID uint32 16 | level uint32 17 | } 18 | 19 | func (u user) GetEmail() string { 20 | return u.email 21 | } 22 | 23 | func (u user) GetUUID() string { 24 | return u.uuid 25 | } 26 | 27 | func (u user) GetLevel() uint32 { 28 | return u.level 29 | } 30 | 31 | func (u user) GetAlterID() uint32 { 32 | return u.alterID 33 | } 34 | -------------------------------------------------------------------------------- /server/config.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "log/slog" 5 | "time" 6 | 7 | "github.com/weeon/utils" 8 | ) 9 | 10 | var ( 11 | cfg = new(Config) 12 | ) 13 | 14 | type Config struct { 15 | WebApi WebApiCfg 16 | Base BaseCfg 17 | SyncTime time.Duration 18 | 19 | TrojanApiServerAddr string 20 | 21 | V2rayClientAddr string 22 | V2rayTag string 23 | 24 | LogPath string 25 | } 26 | 27 | type BaseCfg struct { 28 | } 29 | 30 | type WebApiCfg struct { 31 | Url string 32 | Token string 33 | NodeID string 34 | } 35 | 36 | func initCfg() { 37 | cfg.WebApi = WebApiCfg{ 38 | Url: utils.GetEnv("MU_URI"), 39 | Token: utils.GetEnv("MU_TOKEN"), 40 | NodeID: utils.GetEnv("MU_NODE_ID"), 41 | } 42 | st := utils.GetEnvInt("SYNC_TIME", 60) 43 | cfg.SyncTime = time.Second * time.Duration(st) 44 | cfg.TrojanApiServerAddr = utils.GetEnv("TROJAN_API_SERVER_ADDR") 45 | cfg.V2rayClientAddr = utils.GetEnv("V2RAY_ADDR") 46 | cfg.V2rayTag = utils.GetEnv("V2RAY_TAG") 47 | cfg.LogPath = utils.GetEnv("LOG_DIR", "/var/log/v2ray-mu/") 48 | slog.Info("config", 49 | "v2ray_tag", cfg.V2rayTag, 50 | "v2ray_addr", cfg.V2rayClientAddr) 51 | } 52 | -------------------------------------------------------------------------------- /server/init.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "os" 5 | 6 | "log/slog" 7 | 8 | "github.com/catpie/musdk-go" 9 | "github.com/weeon/log" 10 | ) 11 | 12 | var ( 13 | apiClient *musdk.Client 14 | ) 15 | 16 | var ( 17 | logger *slog.Logger 18 | tl *slog.Logger // traffic logger 19 | // sdkLogger *slog.Logger 20 | tjLogger *slog.Logger 21 | ) 22 | 23 | func Init() { 24 | initCfg() 25 | 26 | textHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{}) 27 | logger = slog.New(textHandler) 28 | 29 | tl = slog.New(textHandler) 30 | // sdkLogger = slog.New(textHandler) 31 | tjLogger = slog.New(textHandler) 32 | } 33 | 34 | func InitWebApi() { 35 | logger.Info("init mu api") 36 | log.SetupStdoutLogger() 37 | cfg := cfg.WebApi 38 | apiClient = musdk.NewClient(cfg.Url, cfg.Token, cfg.NodeID, musdk.TypeV2ray, logger) 39 | apiClient.SetLogger(logger) 40 | go apiClient.UpdateTrafficDaemon() 41 | } 42 | -------------------------------------------------------------------------------- /server/manager.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "log/slog" 6 | "strings" 7 | 8 | "github.com/catpie/musdk-go" 9 | v2raymanager "github.com/orvice/v2ray-mu/pkg/v2ray-manager" 10 | "github.com/weeon/log" 11 | "github.com/weeon/utils/task" 12 | ) 13 | 14 | func getV2rayManager() ([]*v2raymanager.Manager, error) { 15 | arr := strings.Split(cfg.V2rayClientAddr, ",") 16 | slog.Info("v2ray clients", "addr", arr) 17 | var vms = make([]*v2raymanager.Manager, len(arr)) 18 | for k, v := range arr { 19 | vm, err := v2raymanager.NewManager(v, cfg.V2rayTag, logger) 20 | if err != nil { 21 | slog.Error("new mgr failed", "addr", v) 22 | return nil, err 23 | } 24 | vms[k] = vm 25 | } 26 | return vms, nil 27 | } 28 | 29 | func getTrojanMgrs() ([]*TrojanMgr, error) { 30 | arr := strings.Split(cfg.TrojanApiServerAddr, ",") 31 | var trojanMgrs = make([]*TrojanMgr, len(arr)) 32 | for k, v := range arr { 33 | tm, err := newTrojanMgr(v) 34 | if err != nil { 35 | return nil, err 36 | } 37 | trojanMgrs[k] = tm 38 | } 39 | return trojanMgrs, nil 40 | } 41 | 42 | func (u *UserManager) v2rayCheck() error { 43 | ctx := context.Background() 44 | logger.Info("check users from mu") 45 | users, err := apiClient.GetUsers() 46 | if err != nil { 47 | logger.Error("get users fail ", 48 | "error", err, 49 | ) 50 | return err 51 | } 52 | logger.Info("get users from mu", "len", len(users)) 53 | 54 | v2Users, err := u.vm.GetUserList(ctx, true) 55 | if err != nil { 56 | logger.Error("get users list error", 57 | "error", err.Error()) 58 | } 59 | 60 | apiUsersMap := make(map[string]musdk.User) 61 | v2UsersMap := make(map[string]v2raymanager.User) 62 | 63 | for _, user := range users { 64 | logger.Debug("api users map add ", "uuid", user.V2rayUser.UUID) 65 | apiUsersMap[user.V2rayUser.UUID] = user 66 | } 67 | for _, user := range v2Users { 68 | v2UsersMap[user.User.GetUUID()] = user.User 69 | } 70 | 71 | // check remove user 72 | for _, v := range v2Users { 73 | logger.Info("v2 user check ", "uuid", v.User.GetUUID()) 74 | uu, ok := apiUsersMap[v.User.GetUUID()] 75 | if !ok { 76 | logger.Info("v2 user not in api should be removed", "uuid", v.User.GetUUID()) 77 | u.vm.RemoveUser(ctx, v.User) 78 | } 79 | 80 | if uu.Enable == 0 { 81 | logger.Info("user should be removed", "uuid", v.User.GetUUID()) 82 | u.vm.RemoveUser(ctx, v.User) 83 | } 84 | 85 | } 86 | 87 | for _, v := range users { 88 | 89 | if v.Enable == 0 { 90 | continue 91 | } 92 | 93 | _, ok := v2UsersMap[v.V2rayUser.UUID] 94 | if !ok { 95 | logger.Info("user may be should be add", "uuid", v.V2rayUser.UUID) 96 | u.addUser(ctx, &v.V2rayUser) 97 | } 98 | } 99 | 100 | var logCount int 101 | 102 | logger.Info("start v2 user data check len ", "len", len(v2Users)) 103 | 104 | for _, vv := range v2Users { 105 | logger.Info("v2 user check ", "uuid", vv.User.GetUUID()) 106 | apiU, ok := apiUsersMap[vv.User.GetUUID()] 107 | if !ok { 108 | logger.Info("not found in api users ", "uuid", vv.User.GetUUID()) 109 | continue 110 | } 111 | 112 | if vv.TrafficInfo.Up == 0 && vv.TrafficInfo.Down == 0 { 113 | continue 114 | } 115 | 116 | logCount++ 117 | 118 | trafficLog := musdk.UserTrafficLog{ 119 | UserId: apiU.Id, 120 | U: vv.TrafficInfo.Up, 121 | D: vv.TrafficInfo.Down, 122 | } 123 | 124 | if vv.TrafficInfo.Up == 0 && vv.TrafficInfo.Down == 0 { 125 | continue 126 | } 127 | 128 | logCount++ 129 | 130 | tl.Info("save traffice log", 131 | "user_id", apiU.Id, 132 | "uuid", vv.User.GetUUID(), 133 | "traffic Log", trafficLog, 134 | ) 135 | apiClient.SaveTrafficLog(trafficLog) 136 | } 137 | 138 | logger.Info("finish traffic log post len", "len", logCount) 139 | 140 | return nil 141 | } 142 | 143 | func (u *UserManager) addUser(ctx context.Context, user v2raymanager.User) { 144 | exist, err := u.vm.AddUser(ctx, user) 145 | if err != nil { 146 | logger.Error("add user error", "uuid", user.GetUUID(), "err", err) 147 | return 148 | } 149 | if !exist { 150 | logger.Info("add user success", "uuid", user.GetUUID()) 151 | } 152 | 153 | logger.Info("add user result: AlreadyExists", "uuid", user.GetUUID()) 154 | } 155 | 156 | func (u *UserManager) Run() error { 157 | switch u.targetType { 158 | case v2ray: 159 | task.NewTaskAndRun("check_users", cfg.SyncTime, u.v2rayCheck, task.SetTaskLogger(log.GetDefault())) 160 | case trojan: 161 | task.NewTaskAndRun("check_users", cfg.SyncTime, u.trojanCheck, task.SetTaskLogger(log.GetDefault())) 162 | } 163 | return nil 164 | 165 | } 166 | 167 | func (u *UserManager) Down() { 168 | u.cancel() 169 | } 170 | 171 | func (u *UserManager) trojanCheck() error { 172 | ctx, cancel := context.WithCancel(u.ctx) 173 | defer cancel() 174 | 175 | logger.Info("[trojan] check users from mu") 176 | users, err := apiClient.GetUsers() 177 | if err != nil { 178 | tjLogger.Error("[trojan] get users fail ", 179 | "error", err, 180 | ) 181 | return err 182 | } 183 | tjLogger.Info("[trojan] get users from mu", "len", len(users)) 184 | 185 | var trafficLogCount int 186 | var trafficLogs = make([]musdk.UserTrafficLog, 0) 187 | 188 | // add all users 189 | for _, user := range users { 190 | tjLogger.Info("[trojan] start get user ", "id", user.Id, "uuid", user.V2rayUser.UUID) 191 | resp, err := u.tm.GetUser(ctx, user.V2rayUser.UUID) 192 | tjLogger.Info(" [trojan] get user reploy ", "resp", resp, "uuid", user.V2rayUser.UUID) 193 | 194 | if err != nil { 195 | tjLogger.Error("[trojan] get user fail ", 196 | "error", err, 197 | ) 198 | continue 199 | } 200 | 201 | if resp != nil && resp.Status != nil { 202 | status, ok := u.tm.userStatusMap[user.Id] 203 | if ok { 204 | u := int64(resp.Status.TrafficTotal.UploadTraffic) - int64(status.TrafficTotal.UploadTraffic) 205 | d := int64(resp.Status.TrafficTotal.DownloadTraffic) - int64(status.TrafficTotal.DownloadTraffic) 206 | if u > 0 && d > 0 { 207 | trafficLog := musdk.UserTrafficLog{ 208 | UserId: user.Id, 209 | U: int64(u), 210 | D: int64(d), 211 | } 212 | 213 | trafficLogs = append(trafficLogs, trafficLog) 214 | 215 | tjLogger.Info("[trojan] save raffice log", 216 | "user_id", user.Id, 217 | "traffic_log", trafficLog, 218 | ) 219 | trafficLogCount++ 220 | apiClient.SaveTrafficLog(trafficLog) 221 | } 222 | } 223 | 224 | u.tm.userStatusMap[user.Id] = resp.Status 225 | } 226 | 227 | if user.Enable == 0 { 228 | 229 | tjLogger.Info("[trojan] user is disable", "id", user.Id, "uuid", user.V2rayUser.UUID) 230 | 231 | if resp == nil { 232 | continue 233 | } 234 | 235 | if resp.Status == nil { 236 | tjLogger.Info("[trojan] user status is nil", "id", user.Id, "uuid", user.V2rayUser.UUID) 237 | continue 238 | } 239 | 240 | // remove user 241 | logger.Info("[trojan] start remove user ", "id", user.Id, "uuid", user.V2rayUser.UUID, "user.hash", resp.Status.User.Hash) 242 | err = u.tm.RemoveUser(ctx, user.V2rayUser.UUID, resp.Status.User.Hash) 243 | if err != nil { 244 | tjLogger.Error("[trojan] trojan remove ", "uuid", user.V2rayUser.UUID, "err", err) 245 | continue 246 | } 247 | 248 | tjLogger.Info("delete trojan user success ", "uuid", user.V2rayUser.UUID) 249 | 250 | continue 251 | } 252 | 253 | tjLogger.Info("[trojan] user is enable", "id", user.Id, "uuid", user.V2rayUser.UUID) 254 | 255 | tjLogger.Info("check user is exist ", "uuid", user.V2rayUser.UUID) 256 | if resp.Success && resp.Status != nil { 257 | tjLogger.Info("[trojan] user exist", "uuid", user.V2rayUser.UUID) 258 | continue 259 | } 260 | 261 | tjLogger.Info("[trojan] add trojan user ", "uuid", user.V2rayUser.UUID) 262 | err = u.tm.AddUser(ctx, user.V2rayUser.UUID) 263 | if err != nil { 264 | tjLogger.Error("[trojan] add trojan user error", 265 | "error", err, 266 | ) 267 | continue 268 | } 269 | 270 | tjLogger.Info("[trojan] add trojan user success", "uuid", user.V2rayUser.UUID) 271 | } 272 | 273 | tjLogger.Info("traffic log count ", "count", trafficLogCount) 274 | tjLogger.Info("traffic logs", 275 | "traffic_logs", trafficLogs, 276 | ) 277 | 278 | return nil 279 | } 280 | -------------------------------------------------------------------------------- /server/trojan.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "io" 6 | "log" 7 | "time" 8 | 9 | "github.com/p4gefau1t/trojan-go/api/service" 10 | "google.golang.org/grpc" 11 | ) 12 | 13 | type TrojanMgr struct { 14 | client service.TrojanServerServiceClient 15 | 16 | userStatusMap map[int64]*service.UserStatus 17 | } 18 | 19 | func newTrojanMgr(addr string) (*TrojanMgr, error) { 20 | conn, err := grpc.Dial(addr, grpc.WithInsecure()) 21 | if err != nil { 22 | return nil, err 23 | } 24 | client := service.NewTrojanServerServiceClient(conn) 25 | 26 | return &TrojanMgr{ 27 | client: client, 28 | userStatusMap: make(map[int64]*service.UserStatus), 29 | }, nil 30 | } 31 | 32 | func (t *TrojanMgr) ListUsers() ([]*service.UserStatus, error) { 33 | stream, err := t.client.ListUsers(context.Background(), &service.ListUsersRequest{}) 34 | if err != nil { 35 | log.Printf("failed to call grpc command: %v", err) 36 | } 37 | var out = make([]*service.UserStatus, 0) 38 | for { 39 | reply, err := stream.Recv() 40 | if err == io.EOF { 41 | break 42 | } 43 | if err != nil { 44 | log.Printf("faild to recv: %v", err) 45 | return out, nil 46 | } 47 | out = append(out, reply.Status) 48 | } 49 | return out, nil 50 | } 51 | 52 | func (t *TrojanMgr) GetUser(ctx context.Context, password string) (*service.GetUsersResponse, error) { 53 | var err error 54 | 55 | ctx, cancel := context.WithTimeout(ctx, time.Second*10) 56 | defer cancel() 57 | 58 | stream, err := t.client.GetUsers(ctx) 59 | if err != nil { 60 | return nil, err 61 | } 62 | 63 | err = stream.Send(&service.GetUsersRequest{ 64 | User: &service.User{ 65 | Password: password, 66 | }, 67 | }) 68 | 69 | if err != nil { 70 | tjLogger.Error("[trojan] get user fail ", 71 | "error", err, 72 | ) 73 | return nil, err 74 | } 75 | 76 | resp, err := stream.Recv() 77 | if err != nil { 78 | tjLogger.Error("[trojan] get user fail ", 79 | "error", err, 80 | ) 81 | return nil, err 82 | } 83 | return resp, nil 84 | } 85 | 86 | func (t *TrojanMgr) RemoveUser(ctx context.Context, password, hash string) error { 87 | var err error 88 | 89 | ctx, cancel := context.WithTimeout(ctx, time.Second*10) 90 | defer cancel() 91 | 92 | stream, err := t.client.SetUsers(ctx) 93 | if err != nil { 94 | return err 95 | } 96 | 97 | err = stream.Send(&service.SetUsersRequest{ 98 | Operation: service.SetUsersRequest_Delete, 99 | Status: &service.UserStatus{ 100 | User: &service.User{ 101 | Password: password, 102 | }, 103 | }, 104 | }) 105 | 106 | if err != nil { 107 | tjLogger.Error("[trojan] remove user fail ", 108 | "error", err, 109 | ) 110 | return err 111 | } 112 | 113 | resp, err := stream.Recv() 114 | if err != nil { 115 | tjLogger.Error("[trojan] remove user fail ", 116 | "error", err, 117 | ) 118 | return err 119 | } 120 | tjLogger.Info("[trojan] remove user success ", 121 | "resp", resp, 122 | ) 123 | return nil 124 | } 125 | 126 | func (t *TrojanMgr) AddUser(ctx context.Context, password string) error { 127 | var err error 128 | 129 | ctx, cancel := context.WithTimeout(ctx, time.Second*10) 130 | defer cancel() 131 | 132 | stream, err := t.client.SetUsers(ctx) 133 | if err != nil { 134 | return err 135 | } 136 | 137 | err = stream.Send(&service.SetUsersRequest{ 138 | Operation: service.SetUsersRequest_Add, 139 | Status: &service.UserStatus{ 140 | User: &service.User{ 141 | Password: password, 142 | }, 143 | }, 144 | }) 145 | 146 | if err != nil { 147 | tjLogger.Error("[trojan] add user fail ", 148 | "error", err, 149 | ) 150 | return err 151 | } 152 | 153 | resp, err := stream.Recv() 154 | if err != nil { 155 | tjLogger.Error("[trojan] add user fail ", 156 | "error", err, 157 | ) 158 | return err 159 | } 160 | tjLogger.Info("[trojan] add user success ", 161 | "resp", resp, 162 | ) 163 | return nil 164 | } 165 | -------------------------------------------------------------------------------- /server/user.go: -------------------------------------------------------------------------------- 1 | package server 2 | 3 | import ( 4 | "context" 5 | "sync" 6 | 7 | "github.com/catpie/musdk-go" 8 | v2raymanager "github.com/orvice/v2ray-mu/pkg/v2ray-manager" 9 | ) 10 | 11 | const ( 12 | v2ray = 0 13 | trojan = 1 14 | ) 15 | 16 | type UserManager struct { 17 | users map[int64]musdk.User 18 | usersMu *sync.RWMutex 19 | ctx context.Context 20 | cancel func() 21 | 22 | vm *v2raymanager.Manager 23 | tm *TrojanMgr 24 | targetType int 25 | } 26 | 27 | func NewUserManager() ([]*UserManager, error) { 28 | ctx, cancel := context.WithCancel(context.Background()) 29 | vms, err := getV2rayManager() 30 | if err != nil { 31 | return nil, err 32 | } 33 | tms, tjErr := getTrojanMgrs() 34 | 35 | ums := make([]*UserManager, len(vms)+len(tms)) 36 | for k, v := range vms { 37 | ums[k] = &UserManager{ 38 | users: make(map[int64]musdk.User), 39 | usersMu: new(sync.RWMutex), 40 | ctx: ctx, 41 | cancel: cancel, 42 | vm: v, 43 | targetType: v2ray, 44 | } 45 | } 46 | if tjErr == nil { 47 | for k, v := range tms { 48 | ums[len(vms)+k] = &UserManager{ 49 | users: make(map[int64]musdk.User), 50 | usersMu: new(sync.RWMutex), 51 | ctx: ctx, 52 | cancel: cancel, 53 | tm: v, 54 | targetType: trojan, 55 | } 56 | } 57 | } 58 | 59 | return ums, nil 60 | } 61 | 62 | func (u *UserManager) GetUser(id int64) (musdk.User, bool) { 63 | user, ok := u.users[id] 64 | return user, ok 65 | } 66 | -------------------------------------------------------------------------------- /server/utils.go: -------------------------------------------------------------------------------- 1 | package server 2 | --------------------------------------------------------------------------------