Experimental usability stage
This commit is contained in:
@@ -16,7 +16,8 @@
|
||||
"folder": "/mnt/remote/realdebrid/__all__/",
|
||||
"rate_limit": "250/minute",
|
||||
"download_uncached": false,
|
||||
"check_cached": false
|
||||
"check_cached": false,
|
||||
"use_webdav": true
|
||||
},
|
||||
{
|
||||
"name": "debridlink",
|
||||
@@ -91,4 +92,8 @@
|
||||
"allowed_file_types": [],
|
||||
"use_auth": false,
|
||||
"discord_webhook_url": "https://discord.com/api/webhooks/...",
|
||||
"webdav": {
|
||||
"torrents_refresh_interval": "5m",
|
||||
"download_links_refresh_interval": "1h"
|
||||
}
|
||||
}
|
||||
19
go.mod
19
go.mod
@@ -6,12 +6,15 @@ toolchain go1.23.2
|
||||
|
||||
require (
|
||||
github.com/anacrolix/torrent v1.55.0
|
||||
github.com/beevik/etree v1.5.0
|
||||
github.com/cavaliergopher/grab/v3 v3.0.1
|
||||
github.com/elazarl/goproxy v0.0.0-20240726154733-8b0c20506380
|
||||
github.com/elazarl/goproxy/ext v0.0.0-20190711103511-473e67f1d7d2
|
||||
github.com/go-chi/chi/v5 v5.1.0
|
||||
github.com/goccy/go-json v0.10.5
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/sessions v1.4.0
|
||||
github.com/puzpuzpuz/xsync/v3 v3.5.1
|
||||
github.com/rs/zerolog v1.33.0
|
||||
github.com/valyala/fastjson v1.6.4
|
||||
golang.org/x/crypto v0.33.0
|
||||
@@ -24,32 +27,16 @@ require (
|
||||
require (
|
||||
github.com/anacrolix/missinggo v1.3.0 // indirect
|
||||
github.com/anacrolix/missinggo/v2 v2.7.3 // indirect
|
||||
github.com/beevik/etree v1.5.0 // indirect
|
||||
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/dgraph-io/badger/v4 v4.6.0 // indirect
|
||||
github.com/dgraph-io/ristretto/v2 v2.1.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/google/flatbuffers v25.2.10+incompatible // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/gorilla/securecookie v1.1.2 // indirect
|
||||
github.com/huandu/xstrings v1.3.2 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/rogpeppe/go-internal v1.13.1 // indirect
|
||||
github.com/stretchr/testify v1.10.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/otel v1.34.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.34.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.34.0 // indirect
|
||||
golang.org/x/sys v0.30.0 // indirect
|
||||
golang.org/x/text v0.22.0 // indirect
|
||||
google.golang.org/protobuf v1.36.5 // indirect
|
||||
)
|
||||
|
||||
36
go.sum
36
go.sum
@@ -48,25 +48,16 @@ github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 h1:GKTyiRCL6zVf5wWaq
|
||||
github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8/go.mod h1:spo1JLcs67NmW1aVLEgtA8Yy1elc+X8y5SRW1sFW4Og=
|
||||
github.com/cavaliergopher/grab/v3 v3.0.1 h1:4z7TkBfmPjmLAAmkkAZNX/6QJ1nNFdv3SdIHXju0Fr4=
|
||||
github.com/cavaliergopher/grab/v3 v3.0.1/go.mod h1:1U/KNnD+Ft6JJiYoYBAimKH2XrYptb8Kl3DFGmsjpq4=
|
||||
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgraph-io/badger/v4 v4.6.0 h1:acOwfOOZ4p1dPRnYzvkVm7rUk2Y21TgPVepCy5dJdFQ=
|
||||
github.com/dgraph-io/badger/v4 v4.6.0/go.mod h1:KSJ5VTuZNC3Sd+YhvVjk2nYua9UZnnTr/SkXvdtiPgI=
|
||||
github.com/dgraph-io/ristretto/v2 v2.1.0 h1:59LjpOJLNDULHh8MC4UaegN52lC4JnO2dITsie/Pa8I=
|
||||
github.com/dgraph-io/ristretto/v2 v2.1.0/go.mod h1:uejeqfYXpUomfse0+lO+13ATz4TypQYLJZzBSAemuB4=
|
||||
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
|
||||
github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
|
||||
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
|
||||
@@ -89,11 +80,6 @@ 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-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
@@ -116,8 +102,6 @@ github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8l
|
||||
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=
|
||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||
github.com/google/flatbuffers v25.2.10+incompatible h1:F3vclr7C3HpB1k9mxCGRMXq6FdUalZ6H/pNX4FP1v0Q=
|
||||
github.com/google/flatbuffers v25.2.10+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
@@ -152,8 +136,6 @@ github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVY
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
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/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
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=
|
||||
@@ -185,7 +167,6 @@ github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG
|
||||
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
@@ -206,10 +187,11 @@ github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R
|
||||
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
|
||||
github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.5.1 h1:GJYJZwO6IdxN/IKbneznS6yPkVC+c3zyY/j19c++5Fg=
|
||||
github.com/puzpuzpuz/xsync/v3 v3.5.1/go.mod h1:VjzYrABPabuM4KyBh1Ftq6u8nhwY5tBPKP9jpmh0nnA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/go-charset v0.0.0-20180617210344-2471d30d28b4/go.mod h1:qgYeAmZ5ZIpBWTGllZSQnw97Dj+woV0toclVaRGI8pc=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
@@ -239,14 +221,6 @@ github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPy
|
||||
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=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
|
||||
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
|
||||
go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
|
||||
go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
|
||||
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
|
||||
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
|
||||
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.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
|
||||
@@ -266,8 +240,6 @@ golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73r
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
|
||||
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
@@ -322,8 +294,6 @@ 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.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
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=
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/goccy/go-json"
|
||||
@@ -23,7 +24,12 @@ type Debrid struct {
|
||||
DownloadUncached bool `json:"download_uncached"`
|
||||
CheckCached bool `json:"check_cached"`
|
||||
RateLimit string `json:"rate_limit"` // 200/minute or 10/second
|
||||
EnableWebDav bool `json:"enable_webdav"`
|
||||
|
||||
// Webdav
|
||||
UseWebdav bool `json:"use_webdav"`
|
||||
TorrentRefreshInterval string `json:"torrent_refresh_interval"`
|
||||
DownloadLinksRefreshInterval string `json:"downloads_refresh_interval"`
|
||||
TorrentRefreshWorkers int `json:"torrent_refresh_workers"`
|
||||
}
|
||||
|
||||
type Proxy struct {
|
||||
@@ -67,6 +73,16 @@ type Auth struct {
|
||||
Password string `json:"password"`
|
||||
}
|
||||
|
||||
type WebDav struct {
|
||||
TorrentsRefreshInterval string `json:"torrents_refresh_interval"`
|
||||
DownloadLinksRefreshInterval string `json:"download_links_refresh_interval"`
|
||||
Workers int `json:"workers"`
|
||||
|
||||
RcUrl string `json:"rc_url"`
|
||||
RcUser string `json:"rc_user"`
|
||||
RcPass string `json:"rc_pass"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
LogLevel string `json:"log_level"`
|
||||
Debrid Debrid `json:"debrid"`
|
||||
@@ -76,6 +92,7 @@ type Config struct {
|
||||
QBitTorrent QBitTorrent `json:"qbittorrent"`
|
||||
Arrs []Arr `json:"arrs"`
|
||||
Repair Repair `json:"repair"`
|
||||
WebDav WebDav `json:"webdav"`
|
||||
AllowedExt []string `json:"allowed_file_types"`
|
||||
MinFileSize string `json:"min_file_size"` // Minimum file size to download, 10MB, 1GB, etc
|
||||
MaxFileSize string `json:"max_file_size"` // Maximum file size to download (0 means no limit)
|
||||
@@ -286,3 +303,16 @@ func (c *Config) NeedsSetup() bool {
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Config) GetDebridWebDav(d Debrid) Debrid {
|
||||
if d.TorrentRefreshInterval == "" {
|
||||
d.TorrentRefreshInterval = cmp.Or(c.WebDav.TorrentsRefreshInterval, "15s") // 15 seconds
|
||||
}
|
||||
if d.DownloadLinksRefreshInterval == "" {
|
||||
d.DownloadLinksRefreshInterval = cmp.Or(c.WebDav.DownloadLinksRefreshInterval, "40m") // 40 minutes
|
||||
}
|
||||
if d.TorrentRefreshWorkers == 0 {
|
||||
d.TorrentRefreshWorkers = cmp.Or(c.WebDav.Workers, 30) // 30 workers
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
@@ -40,6 +41,11 @@ func JoinURL(base string, paths ...string) (string, error) {
|
||||
return joined, nil
|
||||
}
|
||||
|
||||
var (
|
||||
once sync.Once
|
||||
instance *Client
|
||||
)
|
||||
|
||||
type ClientOption func(*Client)
|
||||
|
||||
// Client represents an HTTP client with additional capabilities
|
||||
@@ -83,6 +89,11 @@ func (c *Client) WithLogger(logger zerolog.Logger) *Client {
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Client) WithTransport(transport *http.Transport) *Client {
|
||||
c.client.Transport = transport
|
||||
return c
|
||||
}
|
||||
|
||||
// WithRetryableStatus adds status codes that should trigger a retry
|
||||
func (c *Client) WithRetryableStatus(statusCodes ...int) *Client {
|
||||
for _, code := range statusCodes {
|
||||
@@ -307,3 +318,10 @@ func Gzip(body []byte) []byte {
|
||||
}
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func Default() *Client {
|
||||
once.Do(func() {
|
||||
instance = New()
|
||||
})
|
||||
return instance
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/puzpuzpuz/xsync/v3"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/sirrobot01/debrid-blackhole/internal/logger"
|
||||
"github.com/sirrobot01/debrid-blackhole/internal/utils"
|
||||
@@ -44,16 +45,17 @@ type Cache struct {
|
||||
torrentsNames map[string]*CachedTorrent // key: torrent.Name, value: torrent
|
||||
listings atomic.Value
|
||||
downloadLinks map[string]string // key: file.Link, value: download link
|
||||
PropfindResp sync.Map
|
||||
PropfindResp *xsync.MapOf[string, PropfindResponse]
|
||||
|
||||
// config
|
||||
workers int
|
||||
|
||||
LastUpdated time.Time `json:"last_updated"`
|
||||
torrentRefreshInterval time.Duration
|
||||
downloadLinksRefreshInterval time.Duration
|
||||
|
||||
// refresh mutex
|
||||
listingRefreshMu sync.Mutex // for refreshing torrents
|
||||
downloadLinksRefreshMu sync.Mutex // for refreshing download links
|
||||
torrentsRefreshMu sync.Mutex // for refreshing torrents
|
||||
listingRefreshMu sync.RWMutex // for refreshing torrents
|
||||
downloadLinksRefreshMu sync.RWMutex // for refreshing download links
|
||||
torrentsRefreshMu sync.RWMutex // for refreshing torrents
|
||||
|
||||
// Data Mutexes
|
||||
torrentsMutex sync.RWMutex // for torrents and torrentsNames
|
||||
@@ -81,7 +83,7 @@ func (c *Cache) setTorrent(t *CachedTorrent) {
|
||||
c.torrentsNames[t.Name] = t
|
||||
c.torrentsMutex.Unlock()
|
||||
|
||||
tryLock(&c.listingRefreshMu, c.refreshListings)
|
||||
c.refreshListings()
|
||||
|
||||
go func() {
|
||||
if err := c.SaveTorrent(t); err != nil {
|
||||
@@ -106,7 +108,7 @@ func (c *Cache) setTorrents(torrents map[string]*CachedTorrent) {
|
||||
|
||||
c.torrentsMutex.Unlock()
|
||||
|
||||
tryLock(&c.listingRefreshMu, c.refreshListings)
|
||||
c.refreshListings()
|
||||
|
||||
go func() {
|
||||
if err := c.SaveTorrents(); err != nil {
|
||||
@@ -131,17 +133,27 @@ func (c *Cache) GetTorrentNames() map[string]*CachedTorrent {
|
||||
return c.torrentsNames
|
||||
}
|
||||
|
||||
func NewCache(client types.Client) *Cache {
|
||||
func NewCache(dc config.Debrid, client types.Client) *Cache {
|
||||
cfg := config.GetConfig()
|
||||
dbPath := filepath.Join(cfg.Path, "cache", client.GetName())
|
||||
torrentRefreshInterval, err := time.ParseDuration(dc.TorrentRefreshInterval)
|
||||
if err != nil {
|
||||
torrentRefreshInterval = time.Second * 15
|
||||
}
|
||||
downloadLinksRefreshInterval, err := time.ParseDuration(dc.DownloadLinksRefreshInterval)
|
||||
if err != nil {
|
||||
downloadLinksRefreshInterval = time.Minute * 40
|
||||
}
|
||||
return &Cache{
|
||||
dir: dbPath,
|
||||
dir: filepath.Join(cfg.Path, "cache", dc.Name), // path to save cache files
|
||||
torrents: make(map[string]*CachedTorrent),
|
||||
torrentsNames: make(map[string]*CachedTorrent),
|
||||
client: client,
|
||||
logger: logger.NewLogger(fmt.Sprintf("%s-cache", client.GetName())),
|
||||
workers: 200,
|
||||
downloadLinks: make(map[string]string),
|
||||
torrentRefreshInterval: torrentRefreshInterval,
|
||||
downloadLinksRefreshInterval: downloadLinksRefreshInterval,
|
||||
PropfindResp: xsync.NewMapOf[string, PropfindResponse](),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +172,7 @@ func (c *Cache) Start() error {
|
||||
c.downloadLinksRefreshMu.Lock()
|
||||
defer c.downloadLinksRefreshMu.Unlock()
|
||||
// This prevents the download links from being refreshed twice
|
||||
tryLock(&c.downloadLinksRefreshMu, c.refreshDownloadLinks)
|
||||
c.refreshDownloadLinks()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
@@ -462,7 +474,19 @@ func (c *Cache) GetClient() types.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *Cache) DeleteTorrent(ids []string) {
|
||||
func (c *Cache) DeleteTorrent(id string) {
|
||||
c.logger.Info().Msgf("Deleting torrent %s", id)
|
||||
c.torrentsMutex.Lock()
|
||||
defer c.torrentsMutex.Unlock()
|
||||
if t, ok := c.torrents[id]; ok {
|
||||
delete(c.torrents, id)
|
||||
delete(c.torrentsNames, t.Name)
|
||||
|
||||
c.removeFromDB(id)
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) DeleteTorrents(ids []string) {
|
||||
c.logger.Info().Msgf("Deleting %d torrents", len(ids))
|
||||
c.torrentsMutex.Lock()
|
||||
defer c.torrentsMutex.Unlock()
|
||||
@@ -483,6 +507,6 @@ func (c *Cache) removeFromDB(torrentId string) {
|
||||
}
|
||||
|
||||
func (c *Cache) OnRemove(torrentId string) {
|
||||
go c.DeleteTorrent([]string{torrentId})
|
||||
go tryLock(&c.listingRefreshMu, c.refreshListings)
|
||||
go c.DeleteTorrent(torrentId)
|
||||
go c.refreshListings()
|
||||
}
|
||||
|
||||
@@ -18,11 +18,16 @@ func NewEngine() *Engine {
|
||||
caches := make(map[string]*Cache)
|
||||
|
||||
for _, dc := range cfg.Debrids {
|
||||
dc = cfg.GetDebridWebDav(dc)
|
||||
client := createDebridClient(dc)
|
||||
logger := client.GetLogger()
|
||||
if dc.UseWebdav {
|
||||
caches[dc.Name] = NewCache(dc, client)
|
||||
logger.Info().Msg("Debrid Service started with WebDAV")
|
||||
} else {
|
||||
logger.Info().Msg("Debrid Service started")
|
||||
}
|
||||
clients[dc.Name] = client
|
||||
caches[dc.Name] = NewCache(client)
|
||||
}
|
||||
|
||||
d := &Engine{
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package debrid
|
||||
|
||||
import "sync"
|
||||
|
||||
func tryLock(mu *sync.Mutex, f func()) {
|
||||
if mu.TryLock() {
|
||||
defer mu.Unlock()
|
||||
f()
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,26 @@
|
||||
package debrid
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/sirrobot01/debrid-blackhole/internal/config"
|
||||
"github.com/sirrobot01/debrid-blackhole/internal/request"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/debrid/types"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (c *Cache) refreshListings() {
|
||||
if c.listingRefreshMu.TryLock() {
|
||||
defer c.listingRefreshMu.Unlock()
|
||||
} else {
|
||||
return
|
||||
}
|
||||
// Copy the current torrents to avoid concurrent issues
|
||||
c.torrentsMutex.RLock()
|
||||
torrents := make([]string, 0, len(c.torrents))
|
||||
@@ -47,6 +55,11 @@ func (c *Cache) refreshListings() {
|
||||
}
|
||||
|
||||
func (c *Cache) refreshTorrents() {
|
||||
if c.torrentsRefreshMu.TryLock() {
|
||||
defer c.torrentsRefreshMu.Unlock()
|
||||
} else {
|
||||
return
|
||||
}
|
||||
c.torrentsMutex.RLock()
|
||||
currentTorrents := c.torrents //
|
||||
// Create a copy of the current torrents to avoid concurrent issues
|
||||
@@ -69,12 +82,12 @@ func (c *Cache) refreshTorrents() {
|
||||
}
|
||||
|
||||
// Get the newly added torrents only
|
||||
newTorrents := make([]*types.Torrent, 0)
|
||||
_newTorrents := make([]*types.Torrent, 0)
|
||||
idStore := make(map[string]bool, len(debTorrents))
|
||||
for _, t := range debTorrents {
|
||||
idStore[t.Id] = true
|
||||
if _, ok := torrents[t.Id]; !ok {
|
||||
newTorrents = append(newTorrents, t)
|
||||
_newTorrents = append(_newTorrents, t)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,9 +98,15 @@ func (c *Cache) refreshTorrents() {
|
||||
deletedTorrents = append(deletedTorrents, id)
|
||||
}
|
||||
}
|
||||
newTorrents := make([]*types.Torrent, 0)
|
||||
for _, t := range _newTorrents {
|
||||
if !slices.Contains(deletedTorrents, t.Id) {
|
||||
_newTorrents = append(_newTorrents, t)
|
||||
}
|
||||
}
|
||||
|
||||
if len(deletedTorrents) > 0 {
|
||||
c.DeleteTorrent(deletedTorrents)
|
||||
c.DeleteTorrents(deletedTorrents)
|
||||
}
|
||||
|
||||
if len(newTorrents) == 0 {
|
||||
@@ -112,34 +131,37 @@ func (c *Cache) refreshTorrents() {
|
||||
}
|
||||
|
||||
func (c *Cache) RefreshRclone() error {
|
||||
params := map[string]interface{}{
|
||||
"recursive": "false",
|
||||
}
|
||||
client := request.Default()
|
||||
cfg := config.GetConfig().WebDav
|
||||
|
||||
// Convert parameters to JSON
|
||||
jsonParams, err := json.Marshal(params)
|
||||
if cfg.RcUrl == "" {
|
||||
return nil
|
||||
}
|
||||
// Create form data
|
||||
data := "dir=__all__&dir2=torrents"
|
||||
|
||||
// Create a POST request with form URL-encoded content
|
||||
forgetReq, err := http.NewRequest("POST", fmt.Sprintf("%s/vfs/forget", cfg.RcUrl), strings.NewReader(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Create HTTP request
|
||||
url := "http://192.168.0.219:9990/vfs/refresh" // Switch to config
|
||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonParams))
|
||||
if err != nil {
|
||||
return err
|
||||
if cfg.RcUser != "" && cfg.RcPass != "" {
|
||||
forgetReq.SetBasicAuth(cfg.RcUser, cfg.RcPass)
|
||||
}
|
||||
|
||||
// Set the appropriate headers
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
// Set the appropriate content type for form data
|
||||
forgetReq.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
|
||||
// Send the request
|
||||
client := &http.Client{}
|
||||
resp, err := client.Do(req)
|
||||
forgetResp, err := client.Do(forgetReq)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if resp.StatusCode != 200 {
|
||||
return fmt.Errorf("failed to refresh rclone: %s", resp.Status)
|
||||
defer forgetResp.Body.Close()
|
||||
|
||||
if forgetResp.StatusCode != 200 {
|
||||
body, _ := io.ReadAll(forgetResp.Body)
|
||||
return fmt.Errorf("failed to forget rclone: %s - %s", forgetResp.Status, string(body))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -166,6 +188,11 @@ func (c *Cache) refreshTorrent(t *CachedTorrent) *CachedTorrent {
|
||||
}
|
||||
|
||||
func (c *Cache) refreshDownloadLinks() {
|
||||
if c.downloadLinksRefreshMu.TryLock() {
|
||||
defer c.downloadLinksRefreshMu.Unlock()
|
||||
} else {
|
||||
return
|
||||
}
|
||||
c.downloadLinksMutex.Lock()
|
||||
defer c.downloadLinksMutex.Unlock()
|
||||
|
||||
|
||||
@@ -11,25 +11,25 @@ func (c *Cache) Refresh() error {
|
||||
}
|
||||
|
||||
func (c *Cache) refreshDownloadLinksWorker() {
|
||||
refreshTicker := time.NewTicker(40 * time.Minute)
|
||||
refreshTicker := time.NewTicker(c.downloadLinksRefreshInterval)
|
||||
defer refreshTicker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-refreshTicker.C:
|
||||
tryLock(&c.downloadLinksRefreshMu, c.refreshDownloadLinks)
|
||||
c.refreshDownloadLinks()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Cache) refreshTorrentsWorker() {
|
||||
refreshTicker := time.NewTicker(5 * time.Second)
|
||||
refreshTicker := time.NewTicker(c.torrentRefreshInterval)
|
||||
defer refreshTicker.Stop()
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-refreshTicker.C:
|
||||
tryLock(&c.torrentsRefreshMu, c.refreshTorrents)
|
||||
c.refreshTorrents()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,14 +6,16 @@ import (
|
||||
"github.com/sirrobot01/debrid-blackhole/internal/request"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
path "path/filepath"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (c *Cache) RefreshXml() error {
|
||||
parents := []string{"__all__", "torrents"}
|
||||
torrents := c.GetListing()
|
||||
for _, parent := range parents {
|
||||
if err := c.refreshParentXml(parent); err != nil {
|
||||
if err := c.refreshParentXml(torrents, parent); err != nil {
|
||||
return fmt.Errorf("failed to refresh XML for %s: %v", parent, err)
|
||||
}
|
||||
}
|
||||
@@ -22,7 +24,7 @@ func (c *Cache) RefreshXml() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Cache) refreshParentXml(parent string) error {
|
||||
func (c *Cache) refreshParentXml(torrents []os.FileInfo, parent string) error {
|
||||
// Define the WebDAV namespace
|
||||
davNS := "DAV:"
|
||||
|
||||
@@ -37,20 +39,21 @@ func (c *Cache) refreshParentXml(parent string) error {
|
||||
currentTime := time.Now().UTC().Format(http.TimeFormat)
|
||||
|
||||
// Add the parent directory
|
||||
parentPath := fmt.Sprintf("/webdav/%s/%s/", c.client.GetName(), parent)
|
||||
baseUrl := path.Clean(fmt.Sprintf("/webdav/%s/%s", c.client.GetName(), parent))
|
||||
parentPath := fmt.Sprintf("%s/", baseUrl)
|
||||
addDirectoryResponse(multistatus, parentPath, parent, currentTime)
|
||||
|
||||
// Add torrents to the XML
|
||||
torrents := c.GetListing()
|
||||
for _, torrent := range torrents {
|
||||
torrentName := torrent.Name()
|
||||
name := torrent.Name()
|
||||
// Note the path structure change - parent first, then torrent name
|
||||
torrentPath := fmt.Sprintf("/webdav/%s/%s/%s/",
|
||||
c.client.GetName(),
|
||||
url.PathEscape(torrentName),
|
||||
parent,
|
||||
url.PathEscape(name),
|
||||
)
|
||||
|
||||
addDirectoryResponse(multistatus, torrentPath, torrentName, currentTime)
|
||||
addDirectoryResponse(multistatus, torrentPath, name, currentTime)
|
||||
}
|
||||
|
||||
// Convert to XML string
|
||||
@@ -60,8 +63,6 @@ func (c *Cache) refreshParentXml(parent string) error {
|
||||
}
|
||||
|
||||
// Store in cache
|
||||
// Construct the keys
|
||||
baseUrl := path.Clean(fmt.Sprintf("/webdav/%s/%s", c.client.GetName()))
|
||||
key0 := fmt.Sprintf("propfind:%s:0", baseUrl)
|
||||
key1 := fmt.Sprintf("propfind:%s:1", baseUrl)
|
||||
|
||||
@@ -78,7 +79,7 @@ func (c *Cache) refreshParentXml(parent string) error {
|
||||
func addDirectoryResponse(multistatus *etree.Element, href, displayName, modTime string) *etree.Element {
|
||||
responseElem := multistatus.CreateElement("D:response")
|
||||
|
||||
// Add href
|
||||
// Add href - ensure it's properly formatted
|
||||
hrefElem := responseElem.CreateElement("D:href")
|
||||
hrefElem.SetText(href)
|
||||
|
||||
@@ -100,6 +101,14 @@ func addDirectoryResponse(multistatus *etree.Element, href, displayName, modTime
|
||||
lastModElem := propElem.CreateElement("D:getlastmodified")
|
||||
lastModElem.SetText(modTime)
|
||||
|
||||
// Add content type for directories
|
||||
contentTypeElem := propElem.CreateElement("D:getcontenttype")
|
||||
contentTypeElem.SetText("httpd/unix-directory")
|
||||
|
||||
// Add length (size) - directories typically have zero size
|
||||
contentLengthElem := propElem.CreateElement("D:getcontentlength")
|
||||
contentLengthElem.SetText("0")
|
||||
|
||||
// Add supported lock
|
||||
lockElem := propElem.CreateElement("D:supportedlock")
|
||||
lockEntryElem := lockElem.CreateElement("D:lockentry")
|
||||
|
||||
@@ -116,9 +116,6 @@ func (q *QBit) ProcessFiles(torrent *Torrent, debridTorrent *debrid.Torrent, arr
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if err := cache.RefreshRclone(); err != nil {
|
||||
q.logger.Trace().Msgf("Error refreshing rclone: %v", err)
|
||||
}
|
||||
rclonePath := filepath.Join(debridTorrent.MountPath, debridTorrent.Name)
|
||||
torrentSymlinkPath, err = q.createSymlinks(debridTorrent, rclonePath, debridTorrent.Name)
|
||||
|
||||
|
||||
@@ -127,8 +127,8 @@
|
||||
}
|
||||
} else {
|
||||
createToast(`Successfully added ${result.results.length} torrents!`);
|
||||
document.getElementById('magnetURI').value = '';
|
||||
document.getElementById('torrentFiles').value = '';
|
||||
//document.getElementById('magnetURI').value = '';
|
||||
//document.getElementById('torrentFiles').value = '';
|
||||
}
|
||||
} catch (error) {
|
||||
createToast(`Error adding downloads: ${error.message}`, 'error');
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/sirrobot01/debrid-blackhole/internal/request"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/debrid/debrid"
|
||||
"github.com/sirrobot01/debrid-blackhole/pkg/debrid/types"
|
||||
"golang.org/x/net/webdav"
|
||||
@@ -29,9 +30,6 @@ type Handler struct {
|
||||
lastRefresh time.Time
|
||||
refreshMutex sync.Mutex
|
||||
RootPath string
|
||||
responseCache sync.Map
|
||||
cacheTTL time.Duration
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func NewHandler(name string, cache *debrid.Cache, logger zerolog.Logger) *Handler {
|
||||
@@ -40,7 +38,6 @@ func NewHandler(name string, cache *debrid.Cache, logger zerolog.Logger) *Handle
|
||||
cache: cache,
|
||||
logger: logger,
|
||||
RootPath: fmt.Sprintf("/%s", name),
|
||||
ctx: context.Background(),
|
||||
}
|
||||
return h
|
||||
}
|
||||
@@ -278,21 +275,31 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
handler.ServeHTTP(responseRecorder, r)
|
||||
responseData := responseRecorder.Body.Bytes()
|
||||
gzippedData := request.Gzip(responseData)
|
||||
|
||||
// Create compressed version
|
||||
|
||||
//h.cache.PropfindResp.Store(cacheKey, debrid.PropfindResponse{
|
||||
// Data: responseData,
|
||||
// GzippedData: request.Gzip(responseData),
|
||||
// Ts: time.Now(),
|
||||
//})
|
||||
h.cache.PropfindResp.Store(cacheKey, debrid.PropfindResponse{
|
||||
Data: responseData,
|
||||
GzippedData: gzippedData,
|
||||
Ts: time.Now(),
|
||||
})
|
||||
|
||||
// Forward the captured response to the client.
|
||||
for k, v := range responseRecorder.Header() {
|
||||
w.Header()[k] = v
|
||||
}
|
||||
w.WriteHeader(responseRecorder.Code)
|
||||
|
||||
if acceptsGzip(r) {
|
||||
w.Header().Set("Content-Encoding", "gzip")
|
||||
w.Header().Set("Vary", "Accept-Encoding")
|
||||
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(gzippedData)))
|
||||
w.Write(gzippedData)
|
||||
} else {
|
||||
w.Header().Set("Content-Length", fmt.Sprintf("%d", len(responseData)))
|
||||
w.Write(responseData)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -394,12 +401,7 @@ func (h *Handler) isParentPath(_path string) bool {
|
||||
}
|
||||
|
||||
func (h *Handler) serveFromCacheIfValid(w http.ResponseWriter, r *http.Request, cacheKey string, ttl time.Duration) bool {
|
||||
cached, ok := h.cache.PropfindResp.Load(cacheKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
respCache, ok := cached.(debrid.PropfindResponse)
|
||||
respCache, ok := h.cache.PropfindResp.Load(cacheKey)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user