mirror of
https://github.com/Ernous/TorrServerJellyfin.git
synced 2025-12-19 13:36:09 +05:00
Merge branch 'master' into 230-torrents-category
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -25,12 +26,12 @@ import (
|
||||
)
|
||||
|
||||
type args struct {
|
||||
Port string `arg:"-p" help:"web server port, default 8090"`
|
||||
Port string `arg:"-p" help:"web server port (default 8090)"`
|
||||
Ssl bool `help:"enables https"`
|
||||
SslPort string `help:"web server ssl port, If not set, will be set to default 8091 or taken from db(if stored previously). Accepted if --ssl enabled."`
|
||||
SslCert string `help:"path to ssl cert file. If not set, will be taken from db(if stored previously) or default self-signed certificate/key will be generated. Accepted if --ssl enabled."`
|
||||
SslKey string `help:"path to ssl key file. If not set, will be taken from db(if stored previously) or default self-signed certificate/key will be generated. Accepted if --ssl enabled."`
|
||||
Path string `arg:"-d" help:"database dir path"`
|
||||
Path string `arg:"-d" help:"database and config dir path"`
|
||||
LogPath string `arg:"-l" help:"server log file path"`
|
||||
WebLogPath string `arg:"-w" help:"web access log file path"`
|
||||
RDB bool `arg:"-r" help:"start in read-only DB mode"`
|
||||
@@ -38,10 +39,11 @@ type args struct {
|
||||
DontKill bool `arg:"-k" help:"don't kill server on signal"`
|
||||
UI bool `arg:"-u" help:"open torrserver page in browser"`
|
||||
TorrentsDir string `arg:"-t" help:"autoload torrents from dir"`
|
||||
TorrentAddr string `help:"Torrent client address, default :32000"`
|
||||
TorrentAddr string `help:"Torrent client address, like 127.0.0.1:1337 (default :PeersListenPort)"`
|
||||
PubIPv4 string `arg:"-4" help:"set public IPv4 addr"`
|
||||
PubIPv6 string `arg:"-6" help:"set public IPv6 addr"`
|
||||
SearchWA bool `arg:"-s" help:"search without auth"`
|
||||
MaxSize string `arg:"-m" help:"max allowed stream size (in Bytes)"`
|
||||
}
|
||||
|
||||
func (args) Version() string {
|
||||
@@ -104,6 +106,13 @@ func main() {
|
||||
go watchTDir(params.TorrentsDir)
|
||||
}
|
||||
|
||||
if params.MaxSize != "" {
|
||||
maxSize, err := strconv.ParseInt(params.MaxSize, 10, 64)
|
||||
if err == nil {
|
||||
settings.MaxSize = maxSize
|
||||
}
|
||||
}
|
||||
|
||||
server.Start(params.Port, params.SslPort, params.SslCert, params.SslKey, params.Ssl, params.RDB, params.SearchWA)
|
||||
log.TLogln(server.WaitServer())
|
||||
log.Close()
|
||||
|
||||
@@ -65,7 +65,7 @@ func Start() {
|
||||
FriendlyName: getDefaultFriendlyName(),
|
||||
NoTranscode: true,
|
||||
NoProbe: true,
|
||||
StallEventSubscribe: true,
|
||||
StallEventSubscribe: false,
|
||||
Icons: []dms.Icon{
|
||||
{
|
||||
Width: 48,
|
||||
|
||||
@@ -62,7 +62,7 @@ const docTemplate = `{
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Test file size",
|
||||
"description": "Test file size (in MB)",
|
||||
"name": "size",
|
||||
"in": "path",
|
||||
"required": true
|
||||
@@ -98,7 +98,7 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/ffp": {
|
||||
"/ffp/{hash}/{id}": {
|
||||
"get": {
|
||||
"description": "Gather informations using ffprobe.",
|
||||
"produces": [
|
||||
@@ -113,14 +113,14 @@ const docTemplate = `{
|
||||
"type": "string",
|
||||
"description": "Torrent hash",
|
||||
"name": "hash",
|
||||
"in": "query",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "File index in torrent",
|
||||
"name": "id",
|
||||
"in": "query",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
@@ -148,32 +148,6 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/msx": {
|
||||
"get": {
|
||||
"description": "Multi usage endpoint.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"MSX"
|
||||
],
|
||||
"summary": "Multi usage endpoint",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Magnet/hash/link to torrent",
|
||||
"name": "link",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Data returned according to query"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/msx/imdb": {
|
||||
"get": {
|
||||
"description": "Get MSX IMDB informations.",
|
||||
@@ -191,7 +165,7 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/msx/imdb/:id": {
|
||||
"/msx/imdb/{id}": {
|
||||
"get": {
|
||||
"description": "Get MSX IMDB informations.",
|
||||
"produces": [
|
||||
@@ -217,7 +191,33 @@ const docTemplate = `{
|
||||
}
|
||||
}
|
||||
},
|
||||
"/play": {
|
||||
"/msx/{pth}": {
|
||||
"get": {
|
||||
"description": "Multi usage endpoint.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"MSX"
|
||||
],
|
||||
"summary": "Multi usage endpoint",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Route MSX pages",
|
||||
"name": "link",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Data returned according to path"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/play/{hash}/{id}": {
|
||||
"get": {
|
||||
"description": "Play given torrent referenced by hash.",
|
||||
"produces": [
|
||||
@@ -232,21 +232,15 @@ const docTemplate = `{
|
||||
"type": "string",
|
||||
"description": "Torrent hash",
|
||||
"name": "hash",
|
||||
"in": "query",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "File index in torrent",
|
||||
"name": "id",
|
||||
"in": "query",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"description": "Not authenticated",
|
||||
"name": "not_auth",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -458,7 +452,7 @@ const docTemplate = `{
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Get m3u from last play",
|
||||
"description": "Get M3U from last played file",
|
||||
"name": "fromlast",
|
||||
"in": "query"
|
||||
},
|
||||
@@ -475,17 +469,10 @@ const docTemplate = `{
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "File index in torrent",
|
||||
"name": "poster",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Set poster link of torrent",
|
||||
"name": "not_auth",
|
||||
"name": "poster",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Test file size",
|
||||
"description": "Test file size (in MB)",
|
||||
"name": "size",
|
||||
"in": "path",
|
||||
"required": true
|
||||
@@ -91,7 +91,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/ffp": {
|
||||
"/ffp/{hash}/{id}": {
|
||||
"get": {
|
||||
"description": "Gather informations using ffprobe.",
|
||||
"produces": [
|
||||
@@ -106,14 +106,14 @@
|
||||
"type": "string",
|
||||
"description": "Torrent hash",
|
||||
"name": "hash",
|
||||
"in": "query",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "File index in torrent",
|
||||
"name": "id",
|
||||
"in": "query",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
@@ -141,32 +141,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/msx": {
|
||||
"get": {
|
||||
"description": "Multi usage endpoint.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"MSX"
|
||||
],
|
||||
"summary": "Multi usage endpoint",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Magnet/hash/link to torrent",
|
||||
"name": "link",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Data returned according to query"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/msx/imdb": {
|
||||
"get": {
|
||||
"description": "Get MSX IMDB informations.",
|
||||
@@ -184,7 +158,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/msx/imdb/:id": {
|
||||
"/msx/imdb/{id}": {
|
||||
"get": {
|
||||
"description": "Get MSX IMDB informations.",
|
||||
"produces": [
|
||||
@@ -210,7 +184,33 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"/play": {
|
||||
"/msx/{pth}": {
|
||||
"get": {
|
||||
"description": "Multi usage endpoint.",
|
||||
"produces": [
|
||||
"application/json"
|
||||
],
|
||||
"tags": [
|
||||
"MSX"
|
||||
],
|
||||
"summary": "Multi usage endpoint",
|
||||
"parameters": [
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Route MSX pages",
|
||||
"name": "link",
|
||||
"in": "path",
|
||||
"required": true
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Data returned according to path"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"/play/{hash}/{id}": {
|
||||
"get": {
|
||||
"description": "Play given torrent referenced by hash.",
|
||||
"produces": [
|
||||
@@ -225,21 +225,15 @@
|
||||
"type": "string",
|
||||
"description": "Torrent hash",
|
||||
"name": "hash",
|
||||
"in": "query",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "File index in torrent",
|
||||
"name": "id",
|
||||
"in": "query",
|
||||
"in": "path",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"description": "Not authenticated",
|
||||
"name": "not_auth",
|
||||
"in": "query"
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
@@ -451,7 +445,7 @@
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Get m3u from last play",
|
||||
"description": "Get M3U from last played file",
|
||||
"name": "fromlast",
|
||||
"in": "query"
|
||||
},
|
||||
@@ -468,17 +462,10 @@
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "File index in torrent",
|
||||
"name": "poster",
|
||||
"in": "query",
|
||||
"required": true
|
||||
},
|
||||
{
|
||||
"type": "string",
|
||||
"description": "Set poster link of torrent",
|
||||
"name": "not_auth",
|
||||
"name": "poster",
|
||||
"in": "query",
|
||||
"required": true
|
||||
}
|
||||
|
||||
@@ -332,7 +332,7 @@ paths:
|
||||
get:
|
||||
description: Download the test file of given size (for speed testing purpose).
|
||||
parameters:
|
||||
- description: Test file size
|
||||
- description: Test file size (in MB)
|
||||
in: path
|
||||
name: size
|
||||
required: true
|
||||
@@ -360,17 +360,17 @@ paths:
|
||||
summary: Tests server status
|
||||
tags:
|
||||
- API
|
||||
/ffp:
|
||||
/ffp/{hash}/{id}:
|
||||
get:
|
||||
description: Gather informations using ffprobe.
|
||||
parameters:
|
||||
- description: Torrent hash
|
||||
in: query
|
||||
in: path
|
||||
name: hash
|
||||
required: true
|
||||
type: string
|
||||
- description: File index in torrent
|
||||
in: query
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
@@ -393,12 +393,12 @@ paths:
|
||||
summary: Get HTML of magnet links
|
||||
tags:
|
||||
- Pages
|
||||
/msx:
|
||||
/msx/{pth}:
|
||||
get:
|
||||
description: Multi usage endpoint.
|
||||
parameters:
|
||||
- description: Magnet/hash/link to torrent
|
||||
in: query
|
||||
- description: Route MSX pages
|
||||
in: path
|
||||
name: link
|
||||
required: true
|
||||
type: string
|
||||
@@ -406,7 +406,7 @@ paths:
|
||||
- application/json
|
||||
responses:
|
||||
"200":
|
||||
description: Data returned according to query
|
||||
description: Data returned according to path
|
||||
summary: Multi usage endpoint
|
||||
tags:
|
||||
- MSX
|
||||
@@ -421,7 +421,7 @@ paths:
|
||||
summary: Get MSX IMDB informations
|
||||
tags:
|
||||
- MSX
|
||||
/msx/imdb/:id:
|
||||
/msx/imdb/{id}:
|
||||
get:
|
||||
description: Get MSX IMDB informations.
|
||||
parameters:
|
||||
@@ -438,24 +438,20 @@ paths:
|
||||
summary: Get MSX IMDB informations
|
||||
tags:
|
||||
- MSX
|
||||
/play:
|
||||
/play/{hash}/{id}:
|
||||
get:
|
||||
description: Play given torrent referenced by hash.
|
||||
parameters:
|
||||
- description: Torrent hash
|
||||
in: query
|
||||
in: path
|
||||
name: hash
|
||||
required: true
|
||||
type: string
|
||||
- description: File index in torrent
|
||||
in: query
|
||||
in: path
|
||||
name: id
|
||||
required: true
|
||||
type: string
|
||||
- description: Not authenticated
|
||||
in: query
|
||||
name: not_auth
|
||||
type: boolean
|
||||
produces:
|
||||
- application/octet-stream
|
||||
responses:
|
||||
@@ -592,7 +588,7 @@ paths:
|
||||
in: query
|
||||
name: m3u
|
||||
type: string
|
||||
- description: Get m3u from last play
|
||||
- description: Get M3U from last played file
|
||||
in: query
|
||||
name: fromlast
|
||||
type: string
|
||||
@@ -605,14 +601,9 @@ paths:
|
||||
name: title
|
||||
required: true
|
||||
type: string
|
||||
- description: File index in torrent
|
||||
in: query
|
||||
name: poster
|
||||
required: true
|
||||
type: string
|
||||
- description: Set poster link of torrent
|
||||
in: query
|
||||
name: not_auth
|
||||
name: poster
|
||||
required: true
|
||||
type: string
|
||||
produces:
|
||||
|
||||
@@ -2,51 +2,52 @@ module server
|
||||
|
||||
go 1.20
|
||||
|
||||
replace github.com/anacrolix/torrent v1.53.1 => github.com/tsynik/torrent v1.2.11
|
||||
replace github.com/anacrolix/torrent v1.54.1 => github.com/tsynik/torrent v1.2.16
|
||||
|
||||
require (
|
||||
github.com/agnivade/levenshtein v1.1.1
|
||||
github.com/alexflint/go-arg v1.4.3
|
||||
github.com/anacrolix/dms v1.6.0
|
||||
github.com/anacrolix/log v0.14.5
|
||||
github.com/anacrolix/missinggo v1.3.0
|
||||
github.com/anacrolix/log v0.15.0
|
||||
github.com/anacrolix/missinggo/v2 v2.7.3
|
||||
github.com/anacrolix/publicip v0.3.0
|
||||
github.com/anacrolix/torrent v1.53.1
|
||||
github.com/gin-contrib/cors v1.4.0
|
||||
github.com/anacrolix/torrent v1.54.1
|
||||
github.com/gin-contrib/cors v1.5.0
|
||||
github.com/gin-contrib/location v0.0.2
|
||||
github.com/gin-gonic/gin v1.9.1
|
||||
github.com/kljensen/snowball v0.8.0
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8
|
||||
github.com/kljensen/snowball v0.9.0
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/swaggo/files v1.0.1
|
||||
github.com/swaggo/gin-swagger v1.6.0
|
||||
github.com/swaggo/swag v1.16.2
|
||||
go.etcd.io/bbolt v1.3.8
|
||||
golang.org/x/image v0.14.0
|
||||
golang.org/x/time v0.4.0
|
||||
github.com/swaggo/swag v1.16.3
|
||||
go.etcd.io/bbolt v1.3.9
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225
|
||||
golang.org/x/image v0.15.0
|
||||
golang.org/x/time v0.5.0
|
||||
gopkg.in/vansante/go-ffprobe.v2 v2.1.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/RoaringBitmap/roaring v1.6.0 // indirect
|
||||
github.com/RoaringBitmap/roaring v1.9.0 // indirect
|
||||
github.com/alecthomas/atomic v0.1.0-alpha2 // indirect
|
||||
github.com/alexflint/go-scalar v1.2.0 // indirect
|
||||
github.com/anacrolix/chansync v0.3.0 // indirect
|
||||
github.com/anacrolix/dht/v2 v2.21.0 // indirect
|
||||
github.com/anacrolix/chansync v0.4.0 // indirect
|
||||
github.com/anacrolix/dht/v2 v2.21.1 // indirect
|
||||
github.com/anacrolix/ffprobe v1.1.0 // indirect
|
||||
github.com/anacrolix/generics v0.0.0-20230911070922-5dd7545c6b13 // indirect
|
||||
github.com/anacrolix/generics v0.0.1 // indirect
|
||||
github.com/anacrolix/missinggo v1.3.0 // indirect
|
||||
github.com/anacrolix/missinggo/perf v1.0.0 // indirect
|
||||
github.com/anacrolix/missinggo/v2 v2.7.3 // indirect
|
||||
github.com/anacrolix/multiless v0.3.1-0.20221221005021-2d12701f83f7 // indirect
|
||||
github.com/anacrolix/stm v0.5.0 // indirect
|
||||
github.com/anacrolix/sync v0.5.1 // indirect
|
||||
github.com/anacrolix/upnp v0.1.3 // indirect
|
||||
github.com/anacrolix/upnp v0.1.4 // indirect
|
||||
github.com/anacrolix/utp v0.2.0 // indirect
|
||||
github.com/benbjohnson/immutable v0.4.3 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.11.0 // indirect
|
||||
github.com/bits-and-blooms/bitset v1.13.0 // indirect
|
||||
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect
|
||||
github.com/bytedance/sonic v1.10.2 // indirect
|
||||
github.com/bytedance/sonic v1.11.1 // indirect
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
|
||||
github.com/chenzhuoyu/iasm v0.9.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
@@ -55,38 +56,38 @@ require (
|
||||
github.com/frankban/quicktest v1.14.6 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 // indirect
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/spec v0.20.9 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.2 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.4 // indirect
|
||||
github.com/go-openapi/spec v0.20.14 // indirect
|
||||
github.com/go-openapi/swag v0.22.9 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
github.com/go-playground/validator/v10 v10.16.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.18.0 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||
github.com/leodido/go-urn v1.2.4 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/leodido/go-urn v1.4.0 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mschoch/smat v0.2.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.1.1 // indirect
|
||||
github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529 // indirect
|
||||
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 // indirect
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||
golang.org/x/arch v0.6.0 // indirect
|
||||
golang.org/x/crypto v0.15.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sync v0.5.0 // indirect
|
||||
golang.org/x/sys v0.14.0 // indirect
|
||||
github.com/ugorji/go/codec v1.2.12 // indirect
|
||||
golang.org/x/arch v0.7.0 // indirect
|
||||
golang.org/x/crypto v0.19.0 // indirect
|
||||
golang.org/x/net v0.21.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.17.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/tools v0.15.0 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
golang.org/x/tools v0.18.0 // indirect
|
||||
google.golang.org/protobuf v1.32.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
179
server/go.sum
179
server/go.sum
@@ -8,8 +8,8 @@ github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6Xge
|
||||
github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w=
|
||||
github.com/RoaringBitmap/roaring v0.4.17/go.mod h1:D3qVegWTmfCaX4Bl5CrBE9hfrSrrXIr8KVNvRsDi1NI=
|
||||
github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo=
|
||||
github.com/RoaringBitmap/roaring v1.6.0 h1:dc7kRiroETgJcHhWX6BerXkZz2b3JgLGg9nTURJL/og=
|
||||
github.com/RoaringBitmap/roaring v1.6.0/go.mod h1:plvDsJQpxOC5bw8LRteu/MLWHsHez/3y6cubLI4/1yE=
|
||||
github.com/RoaringBitmap/roaring v1.9.0 h1:lwKhr90/j0jVXJyh5X+vQN1VVn77rQFfYnh6RDRGCcE=
|
||||
github.com/RoaringBitmap/roaring v1.9.0/go.mod h1:6AXUsoIEzDTFFQCe1RbGA6uFONMhvejWj5rqITANK90=
|
||||
github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
|
||||
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
|
||||
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
|
||||
@@ -25,10 +25,10 @@ github.com/alexflint/go-arg v1.4.3/go.mod h1:3PZ/wp/8HuqRZMUUgu7I+e1qcpUbvmS258m
|
||||
github.com/alexflint/go-scalar v1.1.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
||||
github.com/alexflint/go-scalar v1.2.0 h1:WR7JPKkeNpnYIOfHRa7ivM21aWAdHD0gEWHCx+WQBRw=
|
||||
github.com/alexflint/go-scalar v1.2.0/go.mod h1:LoFvNMqS1CPrMVltza4LvnGKhaSpc3oyLEBUZVhhS2o=
|
||||
github.com/anacrolix/chansync v0.3.0 h1:lRu9tbeuw3wl+PhMu/r+JJCRu5ArFXIluOgdF0ao6/U=
|
||||
github.com/anacrolix/chansync v0.3.0/go.mod h1:DZsatdsdXxD0WiwcGl0nJVwyjCKMDv+knl1q2iBjA2k=
|
||||
github.com/anacrolix/dht/v2 v2.21.0 h1:8nzI+faaynY9jOKmVgdmBZVrTo8B7ZE/LKEgN3Vl/Bs=
|
||||
github.com/anacrolix/dht/v2 v2.21.0/go.mod h1:SDGC+sEs1pnO2sJGYuhvIis7T8749dDHNfcjtdH4e3g=
|
||||
github.com/anacrolix/chansync v0.4.0 h1:Md0HM7zYCAO4KwNwgcIRgxNsMxiRuk7D1Ha0Uo+2y60=
|
||||
github.com/anacrolix/chansync v0.4.0/go.mod h1:DZsatdsdXxD0WiwcGl0nJVwyjCKMDv+knl1q2iBjA2k=
|
||||
github.com/anacrolix/dht/v2 v2.21.1 h1:s1rKkfLLcmBHKv4v/mtMkIeHIEptzEFiB6xVu54+5/o=
|
||||
github.com/anacrolix/dht/v2 v2.21.1/go.mod h1:SDGC+sEs1pnO2sJGYuhvIis7T8749dDHNfcjtdH4e3g=
|
||||
github.com/anacrolix/dms v1.6.0 h1:v2g1Y+Fc/ICSEc+7M6B92oFcfcqa5LXYPhE4Hcm5tVA=
|
||||
github.com/anacrolix/dms v1.6.0/go.mod h1:5fAMpBcPFG4WQFh91zhf2E7/KYZ3/WmmRAf/WMoL0Q0=
|
||||
github.com/anacrolix/envpprof v0.0.0-20180404065416-323002cec2fa/go.mod h1:KgHhUaQMc8cC0+cEflSgCFNFbKwi5h54gqtVn8yhP7c=
|
||||
@@ -38,14 +38,14 @@ github.com/anacrolix/ffprobe v1.0.0/go.mod h1:BIw+Bjol6CWjm/CRWrVLk2Vy+UYlkgmBZ0
|
||||
github.com/anacrolix/ffprobe v1.1.0 h1:eKBudnERW9zRJ0+ge6FzkQ0pWLyq142+FJrwRwSRMT4=
|
||||
github.com/anacrolix/ffprobe v1.1.0/go.mod h1:MXe+zG/RRa5OdIf5+VYYfS/CfsSqOH7RrvGIqJBzqhI=
|
||||
github.com/anacrolix/generics v0.0.0-20230113004304-d6428d516633/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8=
|
||||
github.com/anacrolix/generics v0.0.0-20230911070922-5dd7545c6b13 h1:qwOprPTDMM3BASJRf84mmZnTXRsPGGJ8xoHKQS7m3so=
|
||||
github.com/anacrolix/generics v0.0.0-20230911070922-5dd7545c6b13/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8=
|
||||
github.com/anacrolix/generics v0.0.1 h1:4WVhK6iLb3UAAAQP6I3uYlMOHcp9FqJC9j4n81Wv9Ks=
|
||||
github.com/anacrolix/generics v0.0.1/go.mod h1:ff2rHB/joTV03aMSSn/AZNnaIpUw0h3njetGsaXcMy8=
|
||||
github.com/anacrolix/log v0.3.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgwU9jwU=
|
||||
github.com/anacrolix/log v0.6.0/go.mod h1:lWvLTqzAnCWPJA08T2HCstZi0L1y2Wyvm3FJgwU9jwU=
|
||||
github.com/anacrolix/log v0.13.1/go.mod h1:D4+CvN8SnruK6zIFS/xPoRJmtvtnxs+CSfDQ+BFxZ68=
|
||||
github.com/anacrolix/log v0.14.2/go.mod h1:1OmJESOtxQGNMlUO5rcv96Vpp9mfMqXXbe2RdinFLdY=
|
||||
github.com/anacrolix/log v0.14.5 h1:OkMjBquVSRb742LkecSGDGaGpNoSrw4syRIm0eRdmrg=
|
||||
github.com/anacrolix/log v0.14.5/go.mod h1:1OmJESOtxQGNMlUO5rcv96Vpp9mfMqXXbe2RdinFLdY=
|
||||
github.com/anacrolix/log v0.15.0 h1:QIhbW5NDUL6P1Aml+ZfdaXJ+QFAnrO0K1EpFYs/nh9M=
|
||||
github.com/anacrolix/log v0.15.0/go.mod h1:m0poRtlr41mriZlXBQ9SOVZ8yZBkLjOkDhd5Li5pITA=
|
||||
github.com/anacrolix/missinggo v1.1.0/go.mod h1:MBJu3Sk/k3ZfGYcS7z18gwfu72Ey/xopPFJJbTi5yIo=
|
||||
github.com/anacrolix/missinggo v1.1.2-0.20190815015349-b888af804467/go.mod h1:MBJu3Sk/k3ZfGYcS7z18gwfu72Ey/xopPFJJbTi5yIo=
|
||||
github.com/anacrolix/missinggo v1.2.1/go.mod h1:J5cMhif8jPmFoC3+Uvob3OXXNIhOUikzMt+uUjeM21Y=
|
||||
@@ -70,8 +70,8 @@ github.com/anacrolix/sync v0.5.1/go.mod h1:BbecHL6jDSExojhNtgTFSBcdGerzNc64tz3DC
|
||||
github.com/anacrolix/tagflag v0.0.0-20180109131632-2146c8d41bf0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
|
||||
github.com/anacrolix/tagflag v1.0.0/go.mod h1:1m2U/K6ZT+JZG0+bdMK6qauP49QT4wE5pmhJXOKKCHw=
|
||||
github.com/anacrolix/tagflag v1.1.0/go.mod h1:Scxs9CV10NQatSmbyjqmqmeQNwGzlNe0CMUMIxqHIG8=
|
||||
github.com/anacrolix/upnp v0.1.3 h1:NlYEhE75adz2npEJKjbqyqnyW9qU4STookvSNXBJ5ao=
|
||||
github.com/anacrolix/upnp v0.1.3/go.mod h1:Qyhbqo69gwNWvEk1xNTXsS5j7hMHef9hdr984+9fIic=
|
||||
github.com/anacrolix/upnp v0.1.4 h1:+2t2KA6QOhm/49zeNyeVwDu1ZYS9dB9wfxyVvh/wk7U=
|
||||
github.com/anacrolix/upnp v0.1.4/go.mod h1:Qyhbqo69gwNWvEk1xNTXsS5j7hMHef9hdr984+9fIic=
|
||||
github.com/anacrolix/utp v0.2.0 h1:65Cdmr6q9WSw2KsM+rtJFu7rqDzLl2bdysf4KlNPcFI=
|
||||
github.com/anacrolix/utp v0.2.0/go.mod h1:HGk4GYQw1O/3T1+yhqT/F6EcBd+AAwlo9dYErNy7mj8=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
@@ -82,17 +82,17 @@ github.com/benbjohnson/immutable v0.4.3/go.mod h1:qJIKKSmdqz1tVzNtst1DZzvaqOU1on
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/bits-and-blooms/bitset v1.11.0 h1:RMyy2mBBShArUAhfVRZJ2xyBO58KCBCtZFShw3umo6k=
|
||||
github.com/bits-and-blooms/bitset v1.11.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bits-and-blooms/bitset v1.13.0 h1:bAQ9OPNFYbGHV6Nez0tmNI0RiEu7/hxlYJRUA0wFAVE=
|
||||
github.com/bits-and-blooms/bitset v1.13.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
|
||||
github.com/bradfitz/iter v0.0.0-20140124041915-454541ec3da2/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo=
|
||||
github.com/bradfitz/iter v0.0.0-20190303215204-33e6a9893b0c/go.mod h1:PyRFw1Lt2wKX4ZVSQ2mk+PeDa1rxyObEDlApuIsUKuo=
|
||||
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 h1:GKTyiRCL6zVf5wWaqKnf+7Qs6GbEPfd4iMOitWzXJx8=
|
||||
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8/go.mod h1:spo1JLcs67NmW1aVLEgtA8Yy1elc+X8y5SRW1sFW4Og=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
|
||||
github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
|
||||
github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
|
||||
github.com/bytedance/sonic v1.11.1 h1:JC0+6c9FoWYYxakaoa+c5QTtJeiSZNeByOBhXtAFSn4=
|
||||
github.com/bytedance/sonic v1.11.1/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||
@@ -122,14 +122,14 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
|
||||
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
|
||||
github.com/gin-contrib/cors v1.4.0 h1:oJ6gwtUl3lqV0WEIwM/LxPF1QZ5qe2lGWdY2+bz7y0g=
|
||||
github.com/gin-contrib/cors v1.4.0/go.mod h1:bs9pNM0x/UsmHPBWT2xZz9ROh8xYjYkiURUfmBoMlcs=
|
||||
github.com/gin-contrib/cors v1.5.0 h1:DgGKV7DDoOn36DFkNtbHrjoRiT5ExCe+PC9/xp7aKvk=
|
||||
github.com/gin-contrib/cors v1.5.0/go.mod h1:TvU7MAZ3EwrPLI2ztzTt3tqgvBCq+wn8WpZmfADjupI=
|
||||
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
|
||||
github.com/gin-contrib/location v0.0.2 h1:QZKh1+K/LLR4KG/61eIO3b7MLuKi8tytQhV6texLgP4=
|
||||
github.com/gin-contrib/location v0.0.2/go.mod h1:NGoidiRlf0BlA/VKSVp+g3cuSMeTmip/63PhEjRhUAc=
|
||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
|
||||
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
|
||||
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
|
||||
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
|
||||
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
||||
@@ -142,36 +142,25 @@ github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2
|
||||
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
|
||||
github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
|
||||
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
|
||||
github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
|
||||
github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
|
||||
github.com/go-openapi/spec v0.20.9 h1:xnlYNQAwKd2VQRRfwTEI0DcK+2cbuvI/0c7jx3gA8/8=
|
||||
github.com/go-openapi/spec v0.20.9/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
|
||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
||||
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/swag v0.22.4 h1:QLMzNJnMGPRNDCbySlcj1x01tzU8/9LTTL9hZZZogBU=
|
||||
github.com/go-openapi/swag v0.22.4/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||
github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbXz58sAx6Q=
|
||||
github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
|
||||
github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU=
|
||||
github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4=
|
||||
github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do=
|
||||
github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw=
|
||||
github.com/go-openapi/swag v0.22.9 h1:XX2DssF+mQKM2DHsbgZK74y/zj4mo9I99+89xUmuZCE=
|
||||
github.com/go-openapi/swag v0.22.9/go.mod h1:3/OXnFfnMAwBD099SwYRk7GD3xOrr1iL7d/XNLXVVwE=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
|
||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||
github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
|
||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||
github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI=
|
||||
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||
github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE=
|
||||
github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
|
||||
github.com/go-playground/validator/v10 v10.18.0 h1:BvolUXjp4zuvkZ5YN5t7ebzbhlUtPsPm2S9NAZ5nl9U=
|
||||
github.com/go-playground/validator/v10 v10.18.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
@@ -189,7 +178,6 @@ github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:x
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
@@ -200,8 +188,9 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
@@ -227,31 +216,25 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/kljensen/snowball v0.8.0 h1:WU4cExxK6sNW33AiGdbn4e8RvloHrhkAssu2mVJ11kg=
|
||||
github.com/kljensen/snowball v0.8.0/go.mod h1:OGo5gFWjaeXqCu4iIrMl5OYip9XUJHGOU5eSkPjVg2A=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/kljensen/snowball v0.9.0 h1:OpXkQBcic6vcPG+dChOGLIA/GNuVg47tbbIJ2s7Keas=
|
||||
github.com/kljensen/snowball v0.9.0/go.mod h1:OGo5gFWjaeXqCu4iIrMl5OYip9XUJHGOU5eSkPjVg2A=
|
||||
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
|
||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
|
||||
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
|
||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
|
||||
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
|
||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
@@ -267,18 +250,16 @@ github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
|
||||
github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
|
||||
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
|
||||
github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
|
||||
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
|
||||
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@@ -305,6 +286,7 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529 h1:18kd+8ZUlt/ARXhljq+14TwAoKa61q6dX8jtwOf6DH8=
|
||||
github.com/rs/dnscache v0.0.0-20230804202142-fc85eb664529/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA=
|
||||
github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 h1:GHRpF1pTW19a8tTFrMLUcfWwyC0pnifVo2ClaLq+hP8=
|
||||
@@ -323,57 +305,53 @@ github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/swaggo/files v1.0.1 h1:J1bVJ4XHZNq0I46UU90611i9/YzdrF7x92oX1ig5IdE=
|
||||
github.com/swaggo/files v1.0.1/go.mod h1:0qXmMNH6sXNf+73t65aKeB+ApmgxdnkQzVTAj2uaMUg=
|
||||
github.com/swaggo/gin-swagger v1.6.0 h1:y8sxvQ3E20/RCyrXeFfg60r6H0Z+SwpTjMYsMm+zy8M=
|
||||
github.com/swaggo/gin-swagger v1.6.0/go.mod h1:BG00cCEy294xtVpyIAHG6+e2Qzj/xKlRdOqDkvq0uzo=
|
||||
github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04=
|
||||
github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E=
|
||||
github.com/swaggo/swag v1.16.3 h1:PnCYjPCah8FK4I26l2F/KQ4yz3sILcVUN3cTlBFA9Pg=
|
||||
github.com/swaggo/swag v1.16.3/go.mod h1:DImHIuOFXKpMFAQjcC7FG4m3Dg4+QuUgUzJmKjI/gRk=
|
||||
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
|
||||
github.com/tsynik/torrent v1.2.11 h1:wPJfxhO/ri10T1Xfi4X8DftwOF3A8geZ4cRQWKxnC2s=
|
||||
github.com/tsynik/torrent v1.2.11/go.mod h1:AjuETm1Xae+Vk31UrvrSrb29bBunwMKGZLXK6T+AgPo=
|
||||
github.com/tsynik/torrent v1.2.16 h1:jEXIkdPKIOerO+8b/12wTvEoLnjGFcHX7dMitTmrWH0=
|
||||
github.com/tsynik/torrent v1.2.16/go.mod h1:c/K0Twt8E0qXJj02tl5FmjhGXSl0XzbFYrzkXTGqU+w=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
|
||||
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
|
||||
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||
github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.etcd.io/bbolt v1.3.8 h1:xs88BrvEv273UsB79e0hcVrlUWmS0a8upikMFhSyAtA=
|
||||
go.etcd.io/bbolt v1.3.8/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
|
||||
go.etcd.io/bbolt v1.3.9 h1:8x7aARPEXiXbHmtUwAIv7eV2fQFHrLLavdiJ3uzJXoI=
|
||||
go.etcd.io/bbolt v1.3.9/go.mod h1:zaO32+Ti0PK1ivdPtgMESzuzL2VPoIG1PCQNvOdo/dE=
|
||||
go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||
golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc=
|
||||
golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
|
||||
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
||||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20220428152302-39d4317da171/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa h1:FRnLl4eNAQl8hwxVVC17teOw8kdjVDVAiFMtgUdTSRQ=
|
||||
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa/go.mod h1:zk2irFbV9DP96SEBUUAy67IdHUaZuSnrz1n472HUCLE=
|
||||
golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
|
||||
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
golang.org/x/image v0.15.0 h1:kOELfmgrmJlw4Cdb7g/QGuB3CvDrXbqEIww/pNtNBm8=
|
||||
golang.org/x/image v0.15.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
@@ -381,6 +359,7 @@ golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHl
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20211013180041-c96bc1413d57/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.15.0 h1:SernR4v+D55NyBH2QiEQrlBAnj1ECL6AGrA5+dPaMY8=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
@@ -397,8 +376,8 @@ golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20220524220425-1d687d428aca/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -409,8 +388,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -427,17 +406,15 @@ golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -449,8 +426,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY=
|
||||
golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -460,8 +437,8 @@ golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.8-0.20211029000441-d6a9af8af023/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8=
|
||||
golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk=
|
||||
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -480,16 +457,13 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
@@ -500,10 +474,7 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
|
||||
@@ -45,7 +45,7 @@ func Start(port, sslport, sslCert, sslKey string, sslEnabled, roSets, searchWA b
|
||||
l.Close()
|
||||
}
|
||||
if err != nil {
|
||||
log.TLogln("Port", sslport, "already in use! Please set different port for HTTPS. Abort")
|
||||
log.TLogln("Port", sslport, "already in use! Please set different ssl port for HTTPS. Abort")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ func Start(port, sslport, sslCert, sslKey string, sslEnabled, roSets, searchWA b
|
||||
l.Close()
|
||||
}
|
||||
if err != nil {
|
||||
log.TLogln("Port", port, "already in use! Please set different sslport for HTTP. Abort")
|
||||
log.TLogln("Port", port, "already in use! Please set different port for HTTP. Abort")
|
||||
os.Exit(1)
|
||||
}
|
||||
// remove old disk caches
|
||||
|
||||
@@ -15,7 +15,7 @@ type TDB struct {
|
||||
db *bolt.DB
|
||||
}
|
||||
|
||||
func NewTDB() *TDB {
|
||||
func NewTDB() TorrServerDB {
|
||||
db, err := bolt.Open(filepath.Join(Path, "config.db"), 0o666, &bolt.Options{Timeout: 5 * time.Second})
|
||||
if err != nil {
|
||||
log.TLogln(err)
|
||||
@@ -68,10 +68,6 @@ func (v *TDB) Get(xpath, name string) []byte {
|
||||
}
|
||||
|
||||
func (v *TDB) Set(xpath, name string, value []byte) {
|
||||
if ReadOnly {
|
||||
return
|
||||
}
|
||||
|
||||
spath := strings.Split(xpath, "/")
|
||||
if len(spath) == 0 {
|
||||
return
|
||||
@@ -139,10 +135,6 @@ func (v *TDB) List(xpath string) []string {
|
||||
}
|
||||
|
||||
func (v *TDB) Rem(xpath, name string) {
|
||||
if ReadOnly {
|
||||
return
|
||||
}
|
||||
|
||||
spath := strings.Split(xpath, "/")
|
||||
if len(spath) == 0 {
|
||||
return
|
||||
|
||||
70
server/settings/dbreadcache.go
Normal file
70
server/settings/dbreadcache.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package settings
|
||||
|
||||
import "server/log"
|
||||
|
||||
type DBReadCache struct {
|
||||
db TorrServerDB
|
||||
listCache map[string][]string
|
||||
dataCache map[[2]string][]byte
|
||||
}
|
||||
|
||||
func NewDBReadCache(db TorrServerDB) TorrServerDB {
|
||||
cdb := &DBReadCache{
|
||||
db: db,
|
||||
listCache: map[string][]string{},
|
||||
dataCache: map[[2]string][]byte{},
|
||||
}
|
||||
return cdb
|
||||
}
|
||||
|
||||
func (v *DBReadCache) CloseDB() {
|
||||
v.db.CloseDB()
|
||||
v.db = nil
|
||||
v.listCache = nil
|
||||
v.dataCache = nil
|
||||
}
|
||||
|
||||
func (v *DBReadCache) Get(xPath, name string) []byte {
|
||||
cacheKey := v.makeDataCacheKey(xPath, name)
|
||||
if data, ok := v.dataCache[cacheKey]; ok {
|
||||
return data
|
||||
}
|
||||
data := v.db.Get(xPath, name)
|
||||
v.dataCache[cacheKey] = data
|
||||
return data
|
||||
}
|
||||
|
||||
func (v *DBReadCache) Set(xPath, name string, value []byte) {
|
||||
if ReadOnly {
|
||||
log.TLogln("DB.Set: Read-only DB mode!", name)
|
||||
return
|
||||
}
|
||||
cacheKey := v.makeDataCacheKey(xPath, name)
|
||||
v.dataCache[cacheKey] = value
|
||||
delete(v.listCache, xPath)
|
||||
v.db.Set(xPath, name, value)
|
||||
}
|
||||
|
||||
func (v *DBReadCache) List(xPath string) []string {
|
||||
if names, ok := v.listCache[xPath]; ok {
|
||||
return names
|
||||
}
|
||||
names := v.db.List(xPath)
|
||||
v.listCache[xPath] = names
|
||||
return names
|
||||
}
|
||||
|
||||
func (v *DBReadCache) Rem(xPath, name string) {
|
||||
if ReadOnly {
|
||||
log.TLogln("DB.Rem: Read-only DB mode!", name)
|
||||
return
|
||||
}
|
||||
cacheKey := v.makeDataCacheKey(xPath, name)
|
||||
delete(v.dataCache, cacheKey)
|
||||
delete(v.listCache, xPath)
|
||||
v.db.Rem(xPath, name)
|
||||
}
|
||||
|
||||
func (v *DBReadCache) makeDataCacheKey(xPath, name string) [2]string {
|
||||
return [2]string{xPath, name}
|
||||
}
|
||||
159
server/settings/jsondb.go
Normal file
159
server/settings/jsondb.go
Normal file
@@ -0,0 +1,159 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"server/log"
|
||||
)
|
||||
|
||||
type JsonDB struct {
|
||||
Path string
|
||||
filenameDelimiter string
|
||||
filenameExtension string
|
||||
fileMode fs.FileMode
|
||||
xPathDelimeter string
|
||||
}
|
||||
|
||||
var jsonDbLocks = make(map[string]*sync.Mutex)
|
||||
|
||||
func NewJsonDB() TorrServerDB {
|
||||
settingsDB := &JsonDB{
|
||||
Path: Path,
|
||||
filenameDelimiter: ".",
|
||||
filenameExtension: ".json",
|
||||
fileMode: fs.FileMode(0o666),
|
||||
xPathDelimeter: "/",
|
||||
}
|
||||
return settingsDB
|
||||
}
|
||||
|
||||
func (v *JsonDB) CloseDB() {
|
||||
// Not necessary
|
||||
}
|
||||
|
||||
func (v *JsonDB) Set(xPath, name string, value []byte) {
|
||||
var err error = nil
|
||||
jsonObj := map[string]interface{}{}
|
||||
|
||||
if err := json.Unmarshal(value, &jsonObj); err == nil {
|
||||
if filename, err := v.xPathToFilename(xPath); err == nil {
|
||||
v.lock(filename)
|
||||
defer v.unlock(filename)
|
||||
if root, err := v.readJsonFileAsMap(filename); err == nil {
|
||||
root[name] = jsonObj
|
||||
if err = v.writeMapAsJsonFile(filename, root); err == nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
v.log(fmt.Sprintf("Set: error writing entry %s->%s", xPath, name), err)
|
||||
}
|
||||
|
||||
func (v *JsonDB) Get(xPath, name string) []byte {
|
||||
var err error = nil
|
||||
if filename, err := v.xPathToFilename(xPath); err == nil {
|
||||
v.lock(filename)
|
||||
defer v.unlock(filename)
|
||||
if root, err := v.readJsonFileAsMap(filename); err == nil {
|
||||
if jsonData, ok := root[name]; ok {
|
||||
if byteData, err := json.Marshal(jsonData); err == nil {
|
||||
return byteData
|
||||
}
|
||||
} else {
|
||||
// We assume this is not 'error' but 'no entry' which is normal
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
v.log(fmt.Sprintf("Get: error reading entry %s->%s", xPath, name), err)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *JsonDB) List(xPath string) []string {
|
||||
var err error = nil
|
||||
if filename, err := v.xPathToFilename(xPath); err == nil {
|
||||
v.lock(filename)
|
||||
defer v.unlock(filename)
|
||||
if root, err := v.readJsonFileAsMap(filename); err == nil {
|
||||
nameList := make([]string, 0, len(root))
|
||||
for k := range root {
|
||||
nameList = append(nameList, k)
|
||||
}
|
||||
return nameList
|
||||
}
|
||||
}
|
||||
v.log(fmt.Sprintf("List: error reading entries in xPath %s", xPath), err)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *JsonDB) Rem(xPath, name string) {
|
||||
var err error = nil
|
||||
if filename, err := v.xPathToFilename(xPath); err == nil {
|
||||
v.lock(filename)
|
||||
defer v.unlock(filename)
|
||||
if root, err := v.readJsonFileAsMap(filename); err == nil {
|
||||
delete(root, name)
|
||||
v.writeMapAsJsonFile(filename, root)
|
||||
return
|
||||
}
|
||||
}
|
||||
v.log(fmt.Sprintf("Rem: error removing entry %s->%s", xPath, name), err)
|
||||
}
|
||||
|
||||
func (v *JsonDB) lock(filename string) {
|
||||
var mtx sync.Mutex
|
||||
if mtx, ok := jsonDbLocks[filename]; !ok {
|
||||
mtx = new(sync.Mutex)
|
||||
jsonDbLocks[v.Path] = mtx
|
||||
}
|
||||
mtx.Lock()
|
||||
}
|
||||
|
||||
func (v *JsonDB) unlock(filename string) {
|
||||
if mtx, ok := jsonDbLocks[filename]; ok {
|
||||
mtx.Unlock()
|
||||
}
|
||||
}
|
||||
|
||||
func (v *JsonDB) xPathToFilename(xPath string) (string, error) {
|
||||
if pathComponents := strings.Split(xPath, v.xPathDelimeter); len(pathComponents) > 0 {
|
||||
return strings.ToLower(strings.Join(pathComponents, v.filenameDelimiter) + v.filenameExtension), nil
|
||||
}
|
||||
return "", errors.New("xPath has no components")
|
||||
}
|
||||
|
||||
func (v *JsonDB) readJsonFileAsMap(filename string) (map[string]interface{}, error) {
|
||||
var err error = nil
|
||||
jsonData := map[string]interface{}{}
|
||||
path := filepath.Join(v.Path, filename)
|
||||
if fileData, err := os.ReadFile(path); err == nil {
|
||||
err = json.Unmarshal(fileData, &jsonData)
|
||||
}
|
||||
return jsonData, err
|
||||
}
|
||||
|
||||
func (v *JsonDB) writeMapAsJsonFile(filename string, o map[string]interface{}) error {
|
||||
var err error = nil
|
||||
path := filepath.Join(v.Path, filename)
|
||||
|
||||
if fileData, err := json.MarshalIndent(o, "", " "); err == nil {
|
||||
err = os.WriteFile(path, fileData, v.fileMode)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (v *JsonDB) log(s string, params ...interface{}) {
|
||||
if len(params) > 0 {
|
||||
log.TLogln(fmt.Sprintf("JsonDB: %s: %s", s, fmt.Sprint(params...)))
|
||||
} else {
|
||||
log.TLogln(fmt.Sprintf("JsonDB: %s", s))
|
||||
}
|
||||
}
|
||||
@@ -2,13 +2,17 @@ package settings
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"server/log"
|
||||
"server/web/api/utils"
|
||||
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
var dbTorrentsName = []byte("Torrents")
|
||||
@@ -22,7 +26,8 @@ type torrentOldDB struct {
|
||||
Timestamp int64
|
||||
}
|
||||
|
||||
func Migrate() {
|
||||
// Migrate from torrserver.db to config.db
|
||||
func Migrate1() {
|
||||
if _, err := os.Lstat(filepath.Join(Path, "torrserver.db")); os.IsNotExist(err) {
|
||||
return
|
||||
}
|
||||
@@ -100,3 +105,87 @@ func Migrate() {
|
||||
func b2i(v []byte) int64 {
|
||||
return int64(binary.BigEndian.Uint64(v))
|
||||
}
|
||||
|
||||
/*
|
||||
=== Migrate 2 ===
|
||||
|
||||
Migrate 'Settings' and 'Viewed' buckets from BBolt ('config.db')
|
||||
to separate JSON files ('settings.json' and 'viewed.json')
|
||||
|
||||
'Torrents' data continues to remain in the BBolt database ('config.db')
|
||||
due to the fact that BLOBs are stored there
|
||||
|
||||
To make user be able to roll settings back, no data is deleted from 'config.db' file.
|
||||
*/
|
||||
func Migrate2(bboltDB, jsonDB TorrServerDB) error {
|
||||
var err error = nil
|
||||
|
||||
const XPATH_SETTINGS = "Settings"
|
||||
const NAME_BITTORR = "BitTorr"
|
||||
const XPATH_VIEWED = "Viewed"
|
||||
|
||||
if BTsets != nil {
|
||||
msg := "Migrate0002 MUST be called before initializing BTSets"
|
||||
log.TLogln(msg)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
isByteArraysEqualJson := func(a, b []byte) (bool, error) {
|
||||
var objectA interface{}
|
||||
var objectB interface{}
|
||||
var err error = nil
|
||||
if err = json.Unmarshal(a, &objectA); err == nil {
|
||||
if err = json.Unmarshal(b, &objectB); err == nil {
|
||||
return reflect.DeepEqual(objectA, objectB), nil
|
||||
} else {
|
||||
err = fmt.Errorf("Error unmashalling B: %s", err.Error())
|
||||
}
|
||||
} else {
|
||||
err = fmt.Errorf("Error unmashalling A: %s", err.Error())
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
migrateXPath := func(xPath, name string) error {
|
||||
if jsonDB.Get(xPath, name) == nil {
|
||||
bboltDBBlob := bboltDB.Get(xPath, name)
|
||||
if bboltDBBlob != nil {
|
||||
log.TLogln(fmt.Sprintf("Attempting to migrate %s->%s from TDB to JsonDB", xPath, name))
|
||||
jsonDB.Set(xPath, name, bboltDBBlob)
|
||||
jsonDBBlob := jsonDB.Get(xPath, name)
|
||||
if isEqual, err := isByteArraysEqualJson(bboltDBBlob, jsonDBBlob); err == nil {
|
||||
if isEqual {
|
||||
log.TLogln(fmt.Sprintf("Migrated %s->%s successful", xPath, name))
|
||||
} else {
|
||||
msg := fmt.Sprintf("Failed to migrate %s->%s TDB to JsonDB: equality check failed", xPath, name)
|
||||
log.TLogln(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
} else {
|
||||
msg := fmt.Sprintf("Failed to migrate %s->%s TDB to JsonDB: %s", xPath, name, err)
|
||||
log.TLogln(msg)
|
||||
return errors.New(msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
if err = migrateXPath(XPATH_SETTINGS, NAME_BITTORR); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
jsonDBViewedNames := jsonDB.List(XPATH_VIEWED)
|
||||
if len(jsonDBViewedNames) <= 0 {
|
||||
bboltDBViewedNames := bboltDB.List(XPATH_VIEWED)
|
||||
if len(bboltDBViewedNames) > 0 {
|
||||
for _, name := range bboltDBViewedNames {
|
||||
err = migrateXPath(XPATH_VIEWED, name)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
@@ -8,7 +9,7 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
tdb *TDB
|
||||
tdb TorrServerDB
|
||||
Path string
|
||||
Port string
|
||||
Ssl bool
|
||||
@@ -19,18 +20,40 @@ var (
|
||||
PubIPv4 string
|
||||
PubIPv6 string
|
||||
TorAddr string
|
||||
MaxSize int64
|
||||
)
|
||||
|
||||
func InitSets(readOnly, searchWA bool) {
|
||||
ReadOnly = readOnly
|
||||
SearchWA = searchWA
|
||||
tdb = NewTDB()
|
||||
if tdb == nil {
|
||||
log.TLogln("Error open db:", filepath.Join(Path, "config.db"))
|
||||
|
||||
bboltDB := NewTDB()
|
||||
if bboltDB == nil {
|
||||
log.TLogln("Error open bboltDB:", filepath.Join(Path, "config.db"))
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
jsonDB := NewJsonDB()
|
||||
if jsonDB == nil {
|
||||
log.TLogln("Error open jsonDB")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
dbRouter := NewXPathDBRouter()
|
||||
// First registered DB becomes default route
|
||||
dbRouter.RegisterRoute(jsonDB, "Settings")
|
||||
dbRouter.RegisterRoute(jsonDB, "Viewed")
|
||||
dbRouter.RegisterRoute(bboltDB, "Torrents")
|
||||
|
||||
tdb = NewDBReadCache(dbRouter)
|
||||
|
||||
// We migrate settings here, it must be done before loadBTSets()
|
||||
if err := Migrate2(bboltDB, jsonDB); err != nil {
|
||||
log.TLogln(fmt.Sprintf("Migrate2 failed"))
|
||||
os.Exit(1)
|
||||
}
|
||||
loadBTSets()
|
||||
Migrate()
|
||||
Migrate1()
|
||||
}
|
||||
|
||||
func CloseDB() {
|
||||
|
||||
9
server/settings/torrserverdb.go
Normal file
9
server/settings/torrserverdb.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package settings
|
||||
|
||||
type TorrServerDB interface {
|
||||
CloseDB()
|
||||
Get(xPath, name string) []byte
|
||||
Set(xPath, name string, value []byte)
|
||||
List(xPath string) []string
|
||||
Rem(xPath, name string)
|
||||
}
|
||||
119
server/settings/xpathdbrouter.go
Normal file
119
server/settings/xpathdbrouter.go
Normal file
@@ -0,0 +1,119 @@
|
||||
package settings
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"server/log"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
type XPathDBRouter struct {
|
||||
dbs []TorrServerDB
|
||||
routes []string
|
||||
route2db map[string]TorrServerDB
|
||||
dbNames map[TorrServerDB]string
|
||||
}
|
||||
|
||||
func NewXPathDBRouter() *XPathDBRouter {
|
||||
router := &XPathDBRouter{
|
||||
dbs: []TorrServerDB{},
|
||||
dbNames: map[TorrServerDB]string{},
|
||||
routes: []string{},
|
||||
route2db: map[string]TorrServerDB{},
|
||||
}
|
||||
return router
|
||||
}
|
||||
|
||||
func (v *XPathDBRouter) RegisterRoute(db TorrServerDB, xPath string) error {
|
||||
newRoute := v.xPathToRoute(xPath)
|
||||
|
||||
if slices.Contains(v.routes, newRoute) {
|
||||
return errors.New(fmt.Sprintf("route \"%s\" already in routing table", newRoute))
|
||||
}
|
||||
|
||||
// First DB becomes Default DB with default route
|
||||
if len(v.dbs) == 0 && len(newRoute) != 0 {
|
||||
v.RegisterRoute(db, "")
|
||||
}
|
||||
|
||||
if !slices.Contains(v.dbs, db) {
|
||||
v.dbs = append(v.dbs, db)
|
||||
v.dbNames[db] = reflect.TypeOf(db).Elem().Name()
|
||||
v.log(fmt.Sprintf("Registered new DB \"%s\", total %d DBs registered", v.getDBName(db), len(v.dbs)))
|
||||
}
|
||||
|
||||
v.route2db[newRoute] = db
|
||||
v.routes = append(v.routes, newRoute)
|
||||
|
||||
// Sort routes by length descending.
|
||||
// It is important later to help selecting
|
||||
// most suitable route in getDBForXPath(xPath)
|
||||
sort.Slice(v.routes, func(iLeft, iRight int) bool {
|
||||
return len(v.routes[iLeft]) > len(v.routes[iRight])
|
||||
})
|
||||
v.log(fmt.Sprintf("Registered new route \"%s\" for DB \"%s\", total %d routes", newRoute, v.getDBName(db), len(v.routes)))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *XPathDBRouter) xPathToRoute(xPath string) string {
|
||||
return strings.ToLower(strings.TrimSpace(xPath))
|
||||
}
|
||||
|
||||
func (v *XPathDBRouter) getDBForXPath(xPath string) TorrServerDB {
|
||||
if len(v.dbs) == 0 {
|
||||
return nil
|
||||
}
|
||||
lookup_route := v.xPathToRoute(xPath)
|
||||
var db TorrServerDB = nil
|
||||
// Expected v.routes sorted by length descending
|
||||
for _, route_prefix := range v.routes {
|
||||
if strings.HasPrefix(lookup_route, route_prefix) {
|
||||
db = v.route2db[route_prefix]
|
||||
break
|
||||
}
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
||||
func (v *XPathDBRouter) Get(xPath, name string) []byte {
|
||||
return v.getDBForXPath(xPath).Get(xPath, name)
|
||||
}
|
||||
|
||||
func (v *XPathDBRouter) Set(xPath, name string, value []byte) {
|
||||
v.getDBForXPath(xPath).Set(xPath, name, value)
|
||||
}
|
||||
|
||||
func (v *XPathDBRouter) List(xPath string) []string {
|
||||
return v.getDBForXPath(xPath).List(xPath)
|
||||
}
|
||||
|
||||
func (v *XPathDBRouter) Rem(xPath, name string) {
|
||||
v.getDBForXPath(xPath).Rem(xPath, name)
|
||||
}
|
||||
|
||||
func (v *XPathDBRouter) CloseDB() {
|
||||
for _, db := range v.dbs {
|
||||
db.CloseDB()
|
||||
}
|
||||
v.dbs = nil
|
||||
v.routes = nil
|
||||
v.route2db = nil
|
||||
v.dbNames = nil
|
||||
}
|
||||
|
||||
func (v *XPathDBRouter) getDBName(db TorrServerDB) string {
|
||||
return v.dbNames[db]
|
||||
}
|
||||
|
||||
func (v *XPathDBRouter) log(s string, params ...interface{}) {
|
||||
if len(params) > 0 {
|
||||
log.TLogln(fmt.Sprintf("XPathDBRouter: %s: %s", s, fmt.Sprint(params...)))
|
||||
} else {
|
||||
log.TLogln(fmt.Sprintf("XPathDBRouter: %s", s))
|
||||
}
|
||||
}
|
||||
@@ -150,19 +150,24 @@ func SetTorrent(hashHex, title, poster, data string) *Torrent {
|
||||
}
|
||||
|
||||
func RemTorrent(hashHex string) {
|
||||
if sets.ReadOnly {
|
||||
log.TLogln("API RemTorrent: Read-only DB mode!", hashHex)
|
||||
return
|
||||
}
|
||||
hash := metainfo.NewHashFromHex(hashHex)
|
||||
if sets.BTsets.UseDisk && hashHex != "" && hashHex != "/" {
|
||||
name := filepath.Join(sets.BTsets.TorrentsSavePath, hashHex)
|
||||
ff, _ := os.ReadDir(name)
|
||||
for _, f := range ff {
|
||||
os.Remove(filepath.Join(name, f.Name()))
|
||||
}
|
||||
err := os.Remove(name)
|
||||
if err != nil {
|
||||
log.TLogln("Error remove cache:", err)
|
||||
if bts.RemoveTorrent(hash) {
|
||||
if sets.BTsets.UseDisk && hashHex != "" && hashHex != "/" {
|
||||
name := filepath.Join(sets.BTsets.TorrentsSavePath, hashHex)
|
||||
ff, _ := os.ReadDir(name)
|
||||
for _, f := range ff {
|
||||
os.Remove(filepath.Join(name, f.Name()))
|
||||
}
|
||||
err := os.Remove(name)
|
||||
if err != nil {
|
||||
log.TLogln("Error remove cache:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
bts.RemoveTorrent(hash)
|
||||
RemTorrentDB(hash)
|
||||
}
|
||||
|
||||
@@ -199,6 +204,7 @@ func DropTorrent(hashHex string) {
|
||||
|
||||
func SetSettings(set *sets.BTSets) {
|
||||
if sets.ReadOnly {
|
||||
log.TLogln("API SetSettings: Read-only DB mode!")
|
||||
return
|
||||
}
|
||||
sets.SetBTSets(set)
|
||||
@@ -215,6 +221,7 @@ func SetSettings(set *sets.BTSets) {
|
||||
|
||||
func SetDefSettings() {
|
||||
if sets.ReadOnly {
|
||||
log.TLogln("API SetDefSettings: Read-only DB mode!")
|
||||
return
|
||||
}
|
||||
sets.SetDefaultConfig()
|
||||
|
||||
@@ -88,14 +88,13 @@ func (bt *BTServer) configure(ctx context.Context) {
|
||||
upnpID := "TorrServer/" + version.Version
|
||||
cliVers := userAgent
|
||||
|
||||
// bt.config.AlwaysWantConns = true
|
||||
bt.config.Debug = settings.BTsets.EnableDebug
|
||||
bt.config.DisableIPv6 = !settings.BTsets.EnableIPv6
|
||||
bt.config.DisableTCP = settings.BTsets.DisableTCP
|
||||
bt.config.DisableUTP = settings.BTsets.DisableUTP
|
||||
// https://github.com/anacrolix/torrent/issues/703
|
||||
// bt.config.DisableWebtorrent = true // TODO: check memory usage
|
||||
// bt.config.DisableWebseeds = false
|
||||
// bt.config.DisableWebtorrent = true // NE
|
||||
// bt.config.DisableWebseeds = false // NE
|
||||
bt.config.NoDefaultPortForwarding = settings.BTsets.DisableUPNP
|
||||
bt.config.NoDHT = settings.BTsets.DisableDHT
|
||||
bt.config.DisablePEX = settings.BTsets.DisablePEX
|
||||
@@ -109,13 +108,13 @@ func (bt *BTServer) configure(ctx context.Context) {
|
||||
bt.config.EstablishedConnsPerTorrent = settings.BTsets.ConnectionsLimit
|
||||
bt.config.TotalHalfOpenConns = 500
|
||||
// Encryption/Obfuscation
|
||||
bt.config.EncryptionPolicy = torrent.EncryptionPolicy{
|
||||
ForceEncryption: settings.BTsets.ForceEncrypt,
|
||||
}
|
||||
// bt.config.HeaderObfuscationPolicy = torrent.HeaderObfuscationPolicy{
|
||||
// RequirePreferred: settings.BTsets.ForceEncrypt,
|
||||
// Preferred: true,
|
||||
// }
|
||||
bt.config.EncryptionPolicy = torrent.EncryptionPolicy{ // OE
|
||||
ForceEncryption: settings.BTsets.ForceEncrypt, // OE
|
||||
} // OE
|
||||
// bt.config.HeaderObfuscationPolicy = torrent.HeaderObfuscationPolicy{ // NE
|
||||
// RequirePreferred: settings.BTsets.ForceEncrypt, // NE
|
||||
// Preferred: true, // NE
|
||||
// } // NE
|
||||
if settings.BTsets.DownloadRateLimit > 0 {
|
||||
bt.config.DownloadRateLimiter = utils.Limit(settings.BTsets.DownloadRateLimit * 1024)
|
||||
}
|
||||
@@ -130,21 +129,8 @@ func (bt *BTServer) configure(ctx context.Context) {
|
||||
log.Println("Set listen port", settings.BTsets.PeersListenPort)
|
||||
bt.config.ListenPort = settings.BTsets.PeersListenPort
|
||||
} else {
|
||||
// lport := 32000
|
||||
// for {
|
||||
// log.Println("Check listen port", lport)
|
||||
// l, err := net.Listen("tcp", ":"+strconv.Itoa(lport))
|
||||
// if l != nil {
|
||||
// l.Close()
|
||||
// }
|
||||
// if err == nil {
|
||||
// break
|
||||
// }
|
||||
// lport++
|
||||
// }
|
||||
// log.Println("Set listen port", lport)
|
||||
log.Println("Set listen port to random autoselect (0)")
|
||||
bt.config.ListenPort = 0 // lport
|
||||
bt.config.ListenPort = 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,10 +186,11 @@ func (bt *BTServer) ListTorrents() map[metainfo.Hash]*Torrent {
|
||||
return list
|
||||
}
|
||||
|
||||
func (bt *BTServer) RemoveTorrent(hash torrent.InfoHash) {
|
||||
func (bt *BTServer) RemoveTorrent(hash torrent.InfoHash) bool {
|
||||
if torr, ok := bt.torrents[hash]; ok {
|
||||
torr.Close()
|
||||
return torr.Close()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func isPrivateIP(ip net.IP) bool {
|
||||
|
||||
@@ -62,7 +62,7 @@ func (t *Torrent) Preload(index int, size int64) {
|
||||
// Запуск лога в отдельном потоке
|
||||
go func() {
|
||||
for t.Stat == state.TorrentPreload {
|
||||
stat := fmt.Sprint(file.Torrent().InfoHash().HexString(), " ", utils2.Format(float64(t.PreloadedBytes)), "/", utils2.Format(float64(t.PreloadSize)), " Speed:", utils2.Format(t.DownloadSpeed), " Peers:[", t.Torrent.Stats().ConnectedSeeders, "]", t.Torrent.Stats().ActivePeers, "/", t.Torrent.Stats().TotalPeers)
|
||||
stat := fmt.Sprint(file.Torrent().InfoHash().HexString(), " ", utils2.Format(float64(t.PreloadedBytes)), "/", utils2.Format(float64(t.PreloadSize)), " Speed:", utils2.Format(t.DownloadSpeed), " Peers:", t.Torrent.Stats().ActivePeers, "/", t.Torrent.Stats().TotalPeers, " [Seeds:", t.Torrent.Stats().ConnectedSeeders, "]")
|
||||
log.TLogln("Preload:", stat)
|
||||
t.AddExpiredTime(time.Second * time.Duration(settings.BTsets.TorrentDisconnectTimeout))
|
||||
time.Sleep(time.Second)
|
||||
@@ -158,7 +158,7 @@ func (t *Torrent) Preload(index int, size int64) {
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
log.TLogln("End preload:", file.Torrent().InfoHash().HexString(), "Peers:[", t.Torrent.Stats().ConnectedSeeders, "]", t.Torrent.Stats().ActivePeers, "/", t.Torrent.Stats().TotalPeers)
|
||||
log.TLogln("End preload:", file.Torrent().InfoHash().HexString(), "Peers:", t.Torrent.Stats().ActivePeers, "/", t.Torrent.Stats().TotalPeers, "[ Seeds:", t.Torrent.Stats().ConnectedSeeders, "]")
|
||||
}
|
||||
|
||||
func (t *Torrent) findFileIndex(index int) *torrent.File {
|
||||
|
||||
@@ -314,6 +314,21 @@ func (c *Cache) NewReader(file *torrent.File) *Reader {
|
||||
return newReader(file, c)
|
||||
}
|
||||
|
||||
func (c *Cache) GetUseReaders() int {
|
||||
if c == nil {
|
||||
return 0
|
||||
}
|
||||
c.muReaders.Lock()
|
||||
defer c.muReaders.Unlock()
|
||||
readers := 0
|
||||
for reader := range c.readers {
|
||||
if reader.isUse {
|
||||
readers++
|
||||
}
|
||||
}
|
||||
return readers
|
||||
}
|
||||
|
||||
func (c *Cache) Readers() int {
|
||||
if c == nil {
|
||||
return 0
|
||||
|
||||
@@ -25,20 +25,20 @@ func NewStorage(capacity int64) *Storage {
|
||||
}
|
||||
|
||||
func (s *Storage) OpenTorrent(info *metainfo.Info, infoHash metainfo.Hash) (ts.TorrentImpl, error) {
|
||||
// capFunc := func() (int64, bool) {
|
||||
// return s.capacity, true
|
||||
// }
|
||||
// capFunc := func() (int64, bool) { // NE
|
||||
// return s.capacity, true // NE
|
||||
// } // NE
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
ch := NewCache(s.capacity, s)
|
||||
ch.Init(info, infoHash)
|
||||
s.caches[infoHash] = ch
|
||||
return ch, nil
|
||||
// return ts.TorrentImpl{
|
||||
// Piece: ch.Piece,
|
||||
// Close: ch.Close,
|
||||
// Capacity: &capFunc,
|
||||
// }, nil
|
||||
return ch, nil // OE
|
||||
// return ts.TorrentImpl{ // NE
|
||||
// Piece: ch.Piece, // NE
|
||||
// Close: ch.Close, // NE
|
||||
// Capacity: &capFunc, // NE
|
||||
// }, nil // NE
|
||||
}
|
||||
|
||||
func (s *Storage) CloseHash(hash metainfo.Hash) {
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/dms/dlna"
|
||||
"github.com/anacrolix/missinggo/httptoo"
|
||||
"github.com/anacrolix/missinggo/v2/httptoo"
|
||||
"github.com/anacrolix/torrent"
|
||||
|
||||
mt "server/mimetype"
|
||||
@@ -47,6 +47,10 @@ func (t *Torrent) Stream(fileID int, req *http.Request, resp http.ResponseWriter
|
||||
if file == nil {
|
||||
return fmt.Errorf("file with id %v not found", fileID)
|
||||
}
|
||||
if int64(sets.MaxSize) > 0 && file.Length() > int64(sets.MaxSize) {
|
||||
log.Println("file", file.DisplayPath(), "size exceeded max allowed", sets.MaxSize, "bytes")
|
||||
return fmt.Errorf("file size exceeded max allowed %d bytes", sets.MaxSize)
|
||||
}
|
||||
|
||||
reader := t.NewReader(file)
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
utils2 "server/utils"
|
||||
|
||||
"github.com/anacrolix/torrent"
|
||||
"github.com/anacrolix/torrent/metainfo"
|
||||
|
||||
@@ -266,7 +268,10 @@ func (t *Torrent) drop() {
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Torrent) Close() {
|
||||
func (t *Torrent) Close() bool {
|
||||
if t.cache != nil && t.cache.GetUseReaders() > 0 {
|
||||
return false
|
||||
}
|
||||
t.Stat = state.TorrentClosed
|
||||
|
||||
t.bt.mu.Lock()
|
||||
@@ -274,6 +279,7 @@ func (t *Torrent) Close() {
|
||||
t.bt.mu.Unlock()
|
||||
|
||||
t.drop()
|
||||
return true
|
||||
}
|
||||
|
||||
func (t *Torrent) Status() *state.TorrentStatus {
|
||||
@@ -329,7 +335,7 @@ func (t *Torrent) Status() *state.TorrentStatus {
|
||||
|
||||
files := t.Files()
|
||||
sort.Slice(files, func(i, j int) bool {
|
||||
return files[i].Path() < files[j].Path()
|
||||
return utils2.CompareStrings(files[i].Path(), files[j].Path())
|
||||
})
|
||||
for i, f := range files {
|
||||
st.FileStats = append(st.FileStats, &state.TorrentFileStat{
|
||||
|
||||
@@ -3,6 +3,8 @@ package utils
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -46,3 +48,52 @@ func Format(b float64) string {
|
||||
|
||||
return fmt.Sprintf("%.2f%s", value, multiple)
|
||||
}
|
||||
|
||||
func CommonPrefix(first, second string) string {
|
||||
var result strings.Builder
|
||||
|
||||
minLength := len(first)
|
||||
if len(second) < minLength {
|
||||
minLength = len(second)
|
||||
}
|
||||
|
||||
for i := 0; i < minLength; i++ {
|
||||
if first[i] != second[i] {
|
||||
break
|
||||
}
|
||||
result.WriteByte(first[i])
|
||||
}
|
||||
|
||||
return result.String()
|
||||
}
|
||||
|
||||
func NumberPrefix(str string) (int, error) {
|
||||
var result strings.Builder
|
||||
|
||||
for i := 0; i < len(str); i++ {
|
||||
if !unicode.IsDigit(rune(str[i])) {
|
||||
break
|
||||
}
|
||||
result.WriteByte(str[i])
|
||||
}
|
||||
|
||||
return strconv.Atoi(result.String())
|
||||
}
|
||||
|
||||
func CompareStrings(first, second string) bool {
|
||||
commonPrefix := CommonPrefix(first, second)
|
||||
resultStr1 := strings.TrimPrefix(first, commonPrefix)
|
||||
resultStr2 := strings.TrimPrefix(second, commonPrefix)
|
||||
num1, err1 := NumberPrefix(resultStr1)
|
||||
num2, err2 := NumberPrefix(resultStr2)
|
||||
|
||||
if err1 == nil && err2 == nil {
|
||||
return num1 < num2
|
||||
}
|
||||
if err1 == nil {
|
||||
return true
|
||||
} else if err2 == nil {
|
||||
return false
|
||||
}
|
||||
return resultStr1 < resultStr2
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
// "github.com/anacrolix/torrent"
|
||||
)
|
||||
|
||||
const Version = "MatriX.127.2"
|
||||
const Version = "MatriX.130"
|
||||
|
||||
func GetTorrentVersion() string {
|
||||
bi, ok := debug.ReadBuildInfo()
|
||||
|
||||
@@ -47,7 +47,7 @@ func (f *fileReader) Seek(offset int64, whence int) (int64, error) {
|
||||
//
|
||||
// @Tags API
|
||||
//
|
||||
// @Param size path string true "Test file size"
|
||||
// @Param size path string true "Test file size (in MB)"
|
||||
//
|
||||
// @Produce application/octet-stream
|
||||
// @Success 200 {file} file
|
||||
|
||||
@@ -18,12 +18,12 @@ import (
|
||||
//
|
||||
// @Tags API
|
||||
//
|
||||
// @Param hash query string true "Torrent hash"
|
||||
// @Param id query string true "File index in torrent"
|
||||
// @Param hash path string true "Torrent hash"
|
||||
// @Param id path string true "File index in torrent"
|
||||
//
|
||||
// @Produce json
|
||||
// @Success 200 "Data returned from ffprobe"
|
||||
// @Router /ffp [get]
|
||||
// @Router /ffp/{hash}/{id} [get]
|
||||
func ffp(c *gin.Context) {
|
||||
hash := c.Param("hash")
|
||||
indexStr := c.Param("id")
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/anacrolix/missinggo/httptoo"
|
||||
"github.com/anacrolix/missinggo/v2/httptoo"
|
||||
|
||||
sets "server/settings"
|
||||
"server/torr"
|
||||
|
||||
@@ -19,17 +19,16 @@ import (
|
||||
//
|
||||
// @Tags API
|
||||
//
|
||||
// @Param hash query string true "Torrent hash"
|
||||
// @Param id query string true "File index in torrent"
|
||||
// @Param not_auth query bool false "Not authenticated"
|
||||
// @Param hash path string true "Torrent hash"
|
||||
// @Param id path string true "File index in torrent"
|
||||
//
|
||||
// @Produce application/octet-stream
|
||||
// @Success 200 "Torrent data"
|
||||
// @Router /play [get]
|
||||
// @Router /play/{hash}/{id} [get]
|
||||
func play(c *gin.Context) {
|
||||
hash := c.Param("hash")
|
||||
indexStr := c.Param("id")
|
||||
notAuth := c.GetBool("not_auth")
|
||||
notAuth := c.GetBool("auth_required") && c.GetString(gin.AuthUserKey) == ""
|
||||
|
||||
if hash == "" || indexStr == "" {
|
||||
c.AbortWithError(http.StatusNotFound, errors.New("link should not be empty"))
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
config "server/settings"
|
||||
"server/web/auth"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
@@ -8,15 +11,17 @@ type requestI struct {
|
||||
Action string `json:"action,omitempty"`
|
||||
}
|
||||
|
||||
func SetupRoute(route *gin.RouterGroup) {
|
||||
route.GET("/shutdown", shutdown)
|
||||
func SetupRoute(route gin.IRouter) {
|
||||
authorized := route.Group("/", auth.CheckAuth())
|
||||
|
||||
route.POST("/settings", settings)
|
||||
authorized.GET("/shutdown", shutdown)
|
||||
|
||||
route.POST("/torrents", torrents)
|
||||
route.POST("/torrent/upload", torrentUpload)
|
||||
authorized.POST("/settings", settings)
|
||||
|
||||
route.POST("/cache", cache)
|
||||
authorized.POST("/torrents", torrents)
|
||||
authorized.POST("/torrent/upload", torrentUpload)
|
||||
|
||||
authorized.POST("/cache", cache)
|
||||
|
||||
route.HEAD("/stream", stream)
|
||||
route.HEAD("/stream/*fname", stream)
|
||||
@@ -27,15 +32,19 @@ func SetupRoute(route *gin.RouterGroup) {
|
||||
route.HEAD("/play/:hash/:id", play)
|
||||
route.GET("/play/:hash/:id", play)
|
||||
|
||||
route.POST("/viewed", viewed)
|
||||
authorized.POST("/viewed", viewed)
|
||||
|
||||
route.GET("/playlistall/all.m3u", allPlayList)
|
||||
authorized.GET("/playlistall/all.m3u", allPlayList)
|
||||
route.GET("/playlist", playList)
|
||||
route.GET("/playlist/*fname", playList) // Is this endpoint still needed ? `fname` is never used in handler
|
||||
|
||||
route.GET("/download/:size", download)
|
||||
authorized.GET("/download/:size", download)
|
||||
|
||||
route.GET("/search/*query", rutorSearch)
|
||||
if config.SearchWA {
|
||||
route.GET("/search/*query", rutorSearch)
|
||||
} else {
|
||||
authorized.GET("/search/*query", rutorSearch)
|
||||
}
|
||||
|
||||
route.GET("/ffp/:hash/:id", ffp)
|
||||
authorized.GET("/ffp/:hash/:id", ffp)
|
||||
}
|
||||
|
||||
@@ -41,11 +41,10 @@ import (
|
||||
// @Param stat query string false "Get statistics from torrent"
|
||||
// @Param save query string false "Should save torrent"
|
||||
// @Param m3u query string false "Get torrent as M3U playlist"
|
||||
// @Param fromlast query string false "Get m3u from last play"
|
||||
// @Param fromlast query string false "Get M3U from last played file"
|
||||
// @Param play query string false "Start stream torrent"
|
||||
// @Param title query string true "Set title of torrent"
|
||||
// @Param poster query string true "File index in torrent"
|
||||
// @Param not_auth query string true "Set poster link of torrent"
|
||||
// @Param poster query string true "Set poster link of torrent"
|
||||
//
|
||||
// @Produce application/octet-stream
|
||||
// @Success 200 "Data returned according to query"
|
||||
@@ -62,7 +61,7 @@ func stream(c *gin.Context) {
|
||||
title := c.Query("title")
|
||||
poster := c.Query("poster")
|
||||
data := ""
|
||||
notAuth := c.GetBool("not_auth")
|
||||
notAuth := c.GetBool("auth_required") && c.GetString(gin.AuthUserKey) == ""
|
||||
|
||||
if notAuth && (play || m3u) {
|
||||
streamNoAuth(c)
|
||||
|
||||
@@ -73,6 +73,10 @@ func torrents(c *gin.Context) {
|
||||
{
|
||||
dropTorrent(req, c)
|
||||
}
|
||||
case "wipe":
|
||||
{
|
||||
wipeTorrents(req, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,3 +192,16 @@ func dropTorrent(req torrReqJS, c *gin.Context) {
|
||||
torr.DropTorrent(req.Hash)
|
||||
c.Status(200)
|
||||
}
|
||||
|
||||
func wipeTorrents(req torrReqJS, c *gin.Context) {
|
||||
torrents := torr.ListTorrent()
|
||||
for _, t := range torrents {
|
||||
torr.RemTorrent(t.TorrentSpec.InfoHash.HexString())
|
||||
}
|
||||
// TODO: remove (copied todo from remTorrent())
|
||||
if set.BTsets.EnableDLNA {
|
||||
dlna.Stop()
|
||||
dlna.Start()
|
||||
}
|
||||
c.Status(200)
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"strings"
|
||||
"unsafe"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -16,15 +14,15 @@ import (
|
||||
"server/settings"
|
||||
)
|
||||
|
||||
func SetupAuth(engine *gin.Engine) *gin.RouterGroup {
|
||||
func SetupAuth(engine *gin.Engine) {
|
||||
if !settings.HttpAuth {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
accs := getAccounts()
|
||||
if accs == nil {
|
||||
return nil
|
||||
return
|
||||
}
|
||||
return engine.Group("/", BasicAuth(accs))
|
||||
engine.Use(BasicAuth(accs))
|
||||
}
|
||||
|
||||
func getAccounts() gin.Accounts {
|
||||
@@ -61,21 +59,27 @@ func (a authPairs) searchCredential(authValue string) (string, bool) {
|
||||
func BasicAuth(accounts gin.Accounts) gin.HandlerFunc {
|
||||
pairs := processAccounts(accounts)
|
||||
return func(c *gin.Context) {
|
||||
c.Set("auth_required", true)
|
||||
|
||||
user, found := pairs.searchCredential(c.Request.Header.Get("Authorization"))
|
||||
if !found { // always accessible
|
||||
if strings.HasPrefix(c.FullPath(), "/stream") ||
|
||||
c.FullPath() == "/site.webmanifest" ||
|
||||
// https://github.com/YouROK/TorrServer/issues/172
|
||||
(strings.HasPrefix(c.FullPath(), "/play") && c.FullPath() != "/playlistall/all.m3u") ||
|
||||
(settings.SearchWA && strings.HasPrefix(c.FullPath(), "/search")) {
|
||||
c.Set("not_auth", true)
|
||||
return
|
||||
}
|
||||
c.Header("WWW-Authenticate", "Basic realm=Authorization Required")
|
||||
c.AbortWithStatus(http.StatusUnauthorized)
|
||||
if found {
|
||||
c.Set(gin.AuthUserKey, user)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func CheckAuth() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if !settings.HttpAuth {
|
||||
return
|
||||
}
|
||||
c.Set(gin.AuthUserKey, user)
|
||||
|
||||
if _, ok := c.Get(gin.AuthUserKey); ok {
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("WWW-Authenticate", "Basic realm=Authorization Required")
|
||||
c.AbortWithStatus(http.StatusUnauthorized)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,8 +101,5 @@ func authorizationHeader(user, password string) string {
|
||||
}
|
||||
|
||||
func StringToBytes(s string) (b []byte) {
|
||||
sh := *(*reflect.StringHeader)(unsafe.Pointer(&s))
|
||||
bh := (*reflect.SliceHeader)(unsafe.Pointer(&b))
|
||||
bh.Data, bh.Len, bh.Cap = sh.Data, sh.Len, sh.Len
|
||||
return b
|
||||
return unsafe.Slice(unsafe.StringData(s), len(s))
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"sync"
|
||||
|
||||
"server/version"
|
||||
"server/web/auth"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
@@ -30,10 +31,12 @@ func asset(c *gin.Context, t string, d []byte) {
|
||||
c.Data(200, t+"; charset=UTF-8", d)
|
||||
}
|
||||
|
||||
func SetupRoute(r *gin.RouterGroup) {
|
||||
r.GET("/msx/:pth", msxPTH)
|
||||
r.GET("/msx/imdb", msxIMDB)
|
||||
r.GET("/msx/imdb/:id", msxIMDBID)
|
||||
func SetupRoute(r gin.IRouter) {
|
||||
authorized := r.Group("/", auth.CheckAuth())
|
||||
|
||||
authorized.GET("/msx/:pth", msxPTH)
|
||||
authorized.GET("/msx/imdb", msxIMDB)
|
||||
authorized.GET("/msx/imdb/:id", msxIMDBID)
|
||||
}
|
||||
|
||||
// msxPTH godoc
|
||||
@@ -43,11 +46,11 @@ func SetupRoute(r *gin.RouterGroup) {
|
||||
//
|
||||
// @Tags MSX
|
||||
//
|
||||
// @Param link query string true "Magnet/hash/link to torrent"
|
||||
// @Param link path string true "Route MSX pages"
|
||||
//
|
||||
// @Produce json
|
||||
// @Success 200 "Data returned according to query"
|
||||
// @Router /msx [get]
|
||||
// @Success 200 "Data returned according to path"
|
||||
// @Router /msx/{pth} [get]
|
||||
func msxPTH(c *gin.Context) {
|
||||
js := []string{"http://msx.benzac.de/js/tvx-plugin.min.js"}
|
||||
switch p := c.Param("pth"); p {
|
||||
@@ -114,7 +117,7 @@ func msxIMDB(c *gin.Context) {
|
||||
//
|
||||
// @Produce json
|
||||
// @Success 200 "JSON MSX IMDB informations"
|
||||
// @Router /msx/imdb/:id [get]
|
||||
// @Router /msx/imdb/{id} [get]
|
||||
func msxIMDBID(c *gin.Context) {
|
||||
idb.Lock()
|
||||
defer idb.Unlock()
|
||||
|
||||
@@ -6,13 +6,27 @@ import (
|
||||
|
||||
"server/settings"
|
||||
"server/torr"
|
||||
"server/web/auth"
|
||||
"server/web/pages/template"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
func SetupRoute(route *gin.RouterGroup) {
|
||||
template.RouteWebPages(route)
|
||||
route.GET("/stat", statPage)
|
||||
route.GET("/magnets", getTorrents)
|
||||
func SetupRoute(route gin.IRouter) {
|
||||
authorized := route.Group("/", auth.CheckAuth())
|
||||
|
||||
webPagesAuth := route.Group("/", func() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
if slices.Contains([]string{"/site.webmanifest"}, c.FullPath()) {
|
||||
return
|
||||
}
|
||||
auth.CheckAuth()(c)
|
||||
}
|
||||
}())
|
||||
|
||||
template.RouteWebPages(webPagesAuth)
|
||||
authorized.GET("/stat", statPage)
|
||||
authorized.GET("/magnets", getTorrents)
|
||||
}
|
||||
|
||||
// stat godoc
|
||||
|
||||
@@ -118,20 +118,20 @@ var Mstile150x150png []byte
|
||||
//go:embed pages/site.webmanifest
|
||||
var Sitewebmanifest []byte
|
||||
|
||||
//go:embed pages/static/js/2.41a752aa.chunk.js
|
||||
var Staticjs241a752aachunkjs []byte
|
||||
//go:embed pages/static/js/2.916c2545.chunk.js
|
||||
var Staticjs2916c2545chunkjs []byte
|
||||
|
||||
//go:embed pages/static/js/2.41a752aa.chunk.js.LICENSE.txt
|
||||
var Staticjs241a752aachunkjsLICENSEtxt []byte
|
||||
//go:embed pages/static/js/2.916c2545.chunk.js.LICENSE.txt
|
||||
var Staticjs2916c2545chunkjsLICENSEtxt []byte
|
||||
|
||||
//go:embed pages/static/js/2.41a752aa.chunk.js.map
|
||||
var Staticjs241a752aachunkjsmap []byte
|
||||
//go:embed pages/static/js/2.916c2545.chunk.js.map
|
||||
var Staticjs2916c2545chunkjsmap []byte
|
||||
|
||||
//go:embed pages/static/js/main.b1d76117.chunk.js
|
||||
var Staticjsmainb1d76117chunkjs []byte
|
||||
//go:embed pages/static/js/main.55f380e1.chunk.js
|
||||
var Staticjsmain55f380e1chunkjs []byte
|
||||
|
||||
//go:embed pages/static/js/main.b1d76117.chunk.js.map
|
||||
var Staticjsmainb1d76117chunkjsmap []byte
|
||||
//go:embed pages/static/js/main.55f380e1.chunk.js.map
|
||||
var Staticjsmain55f380e1chunkjsmap []byte
|
||||
|
||||
//go:embed pages/static/js/runtime-main.f542387e.js
|
||||
var Staticjsruntimemainf542387ejs []byte
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"files": {
|
||||
"main.js": "/static/js/main.b1d76117.chunk.js",
|
||||
"main.js.map": "/static/js/main.b1d76117.chunk.js.map",
|
||||
"main.js": "/static/js/main.55f380e1.chunk.js",
|
||||
"main.js.map": "/static/js/main.55f380e1.chunk.js.map",
|
||||
"runtime-main.js": "/static/js/runtime-main.f542387e.js",
|
||||
"runtime-main.js.map": "/static/js/runtime-main.f542387e.js.map",
|
||||
"static/js/2.41a752aa.chunk.js": "/static/js/2.41a752aa.chunk.js",
|
||||
"static/js/2.41a752aa.chunk.js.map": "/static/js/2.41a752aa.chunk.js.map",
|
||||
"static/js/2.916c2545.chunk.js": "/static/js/2.916c2545.chunk.js",
|
||||
"static/js/2.916c2545.chunk.js.map": "/static/js/2.916c2545.chunk.js.map",
|
||||
"index.html": "/index.html",
|
||||
"static/js/2.41a752aa.chunk.js.LICENSE.txt": "/static/js/2.41a752aa.chunk.js.LICENSE.txt"
|
||||
"static/js/2.916c2545.chunk.js.LICENSE.txt": "/static/js/2.916c2545.chunk.js.LICENSE.txt"
|
||||
},
|
||||
"entrypoints": [
|
||||
"static/js/runtime-main.f542387e.js",
|
||||
"static/js/2.41a752aa.chunk.js",
|
||||
"static/js/main.b1d76117.chunk.js"
|
||||
"static/js/2.916c2545.chunk.js",
|
||||
"static/js/main.55f380e1.chunk.js"
|
||||
]
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,191 +1,331 @@
|
||||
package template
|
||||
|
||||
import (
|
||||
"crypto/md5"
|
||||
"fmt"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func RouteWebPages(route *gin.RouterGroup) {
|
||||
func RouteWebPages(route gin.IRouter) {
|
||||
route.GET("/", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Indexhtml))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "text/html; charset=utf-8", Indexhtml)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-1125-2436.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash11252436jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash11252436jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-1136-640.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash1136640jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash1136640jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-1170-2532.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash11702532jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash11702532jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-1242-2208.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash12422208jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash12422208jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-1242-2688.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash12422688jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash12422688jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-1284-2778.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash12842778jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash12842778jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-1334-750.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash1334750jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash1334750jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-1536-2048.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash15362048jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash15362048jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-1620-2160.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash16202160jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash16202160jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-1668-2224.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash16682224jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash16682224jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-1668-2388.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash16682388jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash16682388jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-1792-828.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash1792828jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash1792828jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-2048-1536.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash20481536jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash20481536jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-2048-2732.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash20482732jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash20482732jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-2160-1620.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash21601620jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash21601620jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-2208-1242.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash22081242jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash22081242jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-2224-1668.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash22241668jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash22241668jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-2388-1668.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash23881668jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash23881668jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-2436-1125.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash24361125jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash24361125jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-2532-1170.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash25321170jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash25321170jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-2688-1242.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash26881242jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash26881242jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-2732-2048.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash27322048jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash27322048jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-2778-1284.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash27781284jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash27781284jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-640-1136.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash6401136jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash6401136jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-750-1334.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash7501334jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash7501334jpg)
|
||||
})
|
||||
|
||||
route.GET("/apple-splash-828-1792.jpg", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Applesplash8281792jpg))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/jpeg", Applesplash8281792jpg)
|
||||
})
|
||||
|
||||
route.GET("/asset-manifest.json", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Assetmanifestjson))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "application/json", Assetmanifestjson)
|
||||
})
|
||||
|
||||
route.GET("/browserconfig.xml", func(c *gin.Context) {
|
||||
c.Data(200, "text/xml; charset=utf-8", Browserconfigxml)
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Browserconfigxml))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "application/xml; charset=utf-8", Browserconfigxml)
|
||||
})
|
||||
|
||||
route.GET("/dlnaicon-120.png", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Dlnaicon120png))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/png", Dlnaicon120png)
|
||||
})
|
||||
|
||||
route.GET("/dlnaicon-48.png", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Dlnaicon48png))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/png", Dlnaicon48png)
|
||||
})
|
||||
|
||||
route.GET("/favicon-16x16.png", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Favicon16x16png))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/png", Favicon16x16png)
|
||||
})
|
||||
|
||||
route.GET("/favicon-32x32.png", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Favicon32x32png))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/png", Favicon32x32png)
|
||||
})
|
||||
|
||||
route.GET("/favicon.ico", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Faviconico))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/vnd.microsoft.icon", Faviconico)
|
||||
})
|
||||
|
||||
route.GET("/icon.png", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Iconpng))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/png", Iconpng)
|
||||
})
|
||||
|
||||
route.GET("/index.html", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Indexhtml))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "text/html; charset=utf-8", Indexhtml)
|
||||
})
|
||||
|
||||
route.GET("/logo.png", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Logopng))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/png", Logopng)
|
||||
})
|
||||
|
||||
route.GET("/mstile-150x150.png", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Mstile150x150png))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "image/png", Mstile150x150png)
|
||||
})
|
||||
|
||||
route.GET("/site.webmanifest", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Sitewebmanifest))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "application/manifest+json", Sitewebmanifest)
|
||||
})
|
||||
|
||||
route.GET("/static/js/2.41a752aa.chunk.js", func(c *gin.Context) {
|
||||
c.Data(200, "text/javascript; charset=utf-8", Staticjs241a752aachunkjs)
|
||||
route.GET("/static/js/2.916c2545.chunk.js", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Staticjs2916c2545chunkjs))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "application/javascript; charset=utf-8", Staticjs2916c2545chunkjs)
|
||||
})
|
||||
|
||||
route.GET("/static/js/2.41a752aa.chunk.js.LICENSE.txt", func(c *gin.Context) {
|
||||
c.Data(200, "text/plain; charset=utf-8", Staticjs241a752aachunkjsLICENSEtxt)
|
||||
route.GET("/static/js/2.916c2545.chunk.js.LICENSE.txt", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Staticjs2916c2545chunkjsLICENSEtxt))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "text/plain; charset=utf-8", Staticjs2916c2545chunkjsLICENSEtxt)
|
||||
})
|
||||
|
||||
route.GET("/static/js/2.41a752aa.chunk.js.map", func(c *gin.Context) {
|
||||
c.Data(200, "application/json", Staticjs241a752aachunkjsmap)
|
||||
route.GET("/static/js/2.916c2545.chunk.js.map", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Staticjs2916c2545chunkjsmap))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "application/json", Staticjs2916c2545chunkjsmap)
|
||||
})
|
||||
|
||||
route.GET("/static/js/main.b1d76117.chunk.js", func(c *gin.Context) {
|
||||
c.Data(200, "text/javascript; charset=utf-8", Staticjsmainb1d76117chunkjs)
|
||||
route.GET("/static/js/main.55f380e1.chunk.js", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Staticjsmain55f380e1chunkjs))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "application/javascript; charset=utf-8", Staticjsmain55f380e1chunkjs)
|
||||
})
|
||||
|
||||
route.GET("/static/js/main.b1d76117.chunk.js.map", func(c *gin.Context) {
|
||||
c.Data(200, "application/json", Staticjsmainb1d76117chunkjsmap)
|
||||
route.GET("/static/js/main.55f380e1.chunk.js.map", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Staticjsmain55f380e1chunkjsmap))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "application/json", Staticjsmain55f380e1chunkjsmap)
|
||||
})
|
||||
|
||||
route.GET("/static/js/runtime-main.f542387e.js", func(c *gin.Context) {
|
||||
c.Data(200, "text/javascript; charset=utf-8", Staticjsruntimemainf542387ejs)
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Staticjsruntimemainf542387ejs))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "application/javascript; charset=utf-8", Staticjsruntimemainf542387ejs)
|
||||
})
|
||||
|
||||
route.GET("/static/js/runtime-main.f542387e.js.map", func(c *gin.Context) {
|
||||
etag := fmt.Sprintf("%x", md5.Sum(Staticjsruntimemainf542387ejsmap))
|
||||
c.Header("Cache-Control", "public, max-age=31536000")
|
||||
c.Header("ETag", etag)
|
||||
c.Data(200, "application/json", Staticjsruntimemainf542387ejsmap)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -71,19 +71,14 @@ func Start() {
|
||||
|
||||
route := gin.New()
|
||||
route.Use(log.WebLogger(), blocker.Blocker(), gin.Recovery(), cors.New(corsCfg), location.Default())
|
||||
auth.SetupAuth(route)
|
||||
|
||||
route.GET("/echo", echo)
|
||||
|
||||
routeAuth := auth.SetupAuth(route)
|
||||
if routeAuth != nil {
|
||||
api.SetupRoute(routeAuth)
|
||||
msx.SetupRoute(routeAuth)
|
||||
pages.SetupRoute(routeAuth)
|
||||
} else {
|
||||
api.SetupRoute(&route.RouterGroup)
|
||||
msx.SetupRoute(&route.RouterGroup)
|
||||
pages.SetupRoute(&route.RouterGroup)
|
||||
}
|
||||
api.SetupRoute(route)
|
||||
msx.SetupRoute(route)
|
||||
pages.SetupRoute(route)
|
||||
|
||||
if settings.BTsets.EnableDLNA {
|
||||
dlna.Start()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user