From 9a708fce1d7927b540a0a2287099392f037e4b5d Mon Sep 17 00:00:00 2001 From: CJ_Clippy Date: Wed, 3 Dec 2025 03:59:28 -0800 Subject: [PATCH] add vibeui player --- services/pocketbase/.gitignore | 31 +- services/pocketbase/go.mod | 46 + services/pocketbase/go.sum | 141 +++ services/pocketbase/main.go | 148 +++ services/pocketbase/package.json | 2 +- .../pb_hooks/{cdn.pb.js => cdn.pb.js.noexec} | 82 +- .../pb_hooks/pages/(site)/+layout.ejs | 3 +- .../pb_hooks/pages/(site)/about/index.ejs | 19 + .../pages/(site)/auth/_private/oauth2.ejs | 2 +- .../pb_hooks/pages/(site)/vods/[id]/index.ejs | 211 +++- .../pb_hooks/pages/(site)/vt/index.ejs | 6 +- .../pb_hooks/pages/_private/vod-list.ejs | 15 +- .../pb_migrations/1764156924_updated_vods.js | 29 + .../pb_migrations/1764481404_updated_vods.js | 48 + .../pb_migrations/1764574888_updated_vods.js | 29 + .../pb_migrations/1764648351_updated_vods.js | 48 + .../pb_migrations/1764723356_updated_vods.js | 48 + .../pb_migrations/1764758197_updated_vods.js | 48 + .../pb_migrations/1764758246_updated_vods.js | 105 ++ services/pocketbase/pb_public/Funscripts.js | 305 ++++++ .../pb_public/vibrator-controls.png | Bin 0 -> 33607 bytes .../pocketbase/src/handlers/file_download.go | 70 ++ .../pocketbase/src/handlers/hls_package.go | 52 + .../pocketbase/src/handlers/s3_download.go | 56 + services/pocketbase/src/misc/bunny-cdn.go | 80 ++ .../src/plugins/patreon/package-lock.json | 957 ------------------ .../src/plugins/patreon/package.json | 19 - .../src/plugins/patreon/src/index.ts | 40 - .../src/plugins/patreon/tsconfig.json | 19 - .../src/plugins/patreon/tsdown.config.ts | 10 - services/worker/.config/env.ts | 23 +- services/worker/package-lock.json | 102 +- services/worker/package.json | 5 +- services/worker/src/index.ts | 17 +- .../src/processors/announceTorrent.spec.ts | 16 + .../worker/src/processors/announceTorrent.ts | 56 + .../worker/src/processors/cacheCleanup.ts | 67 +- .../worker/src/processors/createFunscript.ts | 271 +++-- .../src/processors/createHlsPlaylist.ts | 166 ++- .../worker/src/processors/createTorrent.ts | 16 +- services/worker/src/processors/findWork.ts | 19 +- .../src/processors/updateTrackerWhitelist.ts | 111 ++ services/worker/src/queues/downloadQueue.ts | 1 - .../worker/src/queues/highPriorityQueue.ts | 12 + services/worker/src/util/b2.ts | 23 +- services/worker/src/util/bunnyCDN.spec.ts | 46 +- services/worker/src/util/bunnyCDN.ts | 63 +- services/worker/src/util/cache.ts | 21 + services/worker/src/util/fsExtra.ts | 29 + services/worker/src/util/funscripts.ts | 15 +- services/worker/src/util/qbittorrent.ts | 82 +- services/worker/src/util/sftp.spec.ts | 6 +- services/worker/src/util/sftp.ts | 64 +- services/worker/src/util/vibeui.ts | 47 +- services/worker/src/workers/downloadWorker.ts | 2 +- services/worker/src/workers/gpuWorker.ts | 10 +- .../worker/src/workers/highPriorityWorker.ts | 4 + services/worker/systemd/up.sh | 2 +- 58 files changed, 2534 insertions(+), 1431 deletions(-) create mode 100644 services/pocketbase/go.mod create mode 100644 services/pocketbase/go.sum create mode 100644 services/pocketbase/main.go rename services/pocketbase/pb_hooks/{cdn.pb.js => cdn.pb.js.noexec} (52%) create mode 100644 services/pocketbase/pb_hooks/pages/(site)/about/index.ejs create mode 100644 services/pocketbase/pb_migrations/1764156924_updated_vods.js create mode 100644 services/pocketbase/pb_migrations/1764481404_updated_vods.js create mode 100644 services/pocketbase/pb_migrations/1764574888_updated_vods.js create mode 100644 services/pocketbase/pb_migrations/1764648351_updated_vods.js create mode 100644 services/pocketbase/pb_migrations/1764723356_updated_vods.js create mode 100644 services/pocketbase/pb_migrations/1764758197_updated_vods.js create mode 100644 services/pocketbase/pb_migrations/1764758246_updated_vods.js create mode 100644 services/pocketbase/pb_public/Funscripts.js create mode 100644 services/pocketbase/pb_public/vibrator-controls.png create mode 100644 services/pocketbase/src/handlers/file_download.go create mode 100644 services/pocketbase/src/handlers/hls_package.go create mode 100644 services/pocketbase/src/handlers/s3_download.go create mode 100644 services/pocketbase/src/misc/bunny-cdn.go delete mode 100644 services/pocketbase/src/plugins/patreon/package-lock.json delete mode 100644 services/pocketbase/src/plugins/patreon/package.json delete mode 100644 services/pocketbase/src/plugins/patreon/src/index.ts delete mode 100644 services/pocketbase/src/plugins/patreon/tsconfig.json delete mode 100644 services/pocketbase/src/plugins/patreon/tsdown.config.ts create mode 100644 services/worker/src/processors/announceTorrent.spec.ts create mode 100644 services/worker/src/processors/announceTorrent.ts create mode 100644 services/worker/src/processors/updateTrackerWhitelist.ts create mode 100644 services/worker/src/util/cache.ts create mode 100644 services/worker/src/util/fsExtra.ts diff --git a/services/pocketbase/.gitignore b/services/pocketbase/.gitignore index e122e2de..fb09640c 100644 --- a/services/pocketbase/.gitignore +++ b/services/pocketbase/.gitignore @@ -2,4 +2,33 @@ node_modules pb_data .DS_Store -.secrets \ No newline at end of file +.secrets + + +# Created by https://www.toptal.com/developers/gitignore/api/go +# Edit at https://www.toptal.com/developers/gitignore?templates=go + +### Go ### +# If you prefer the allow list template instead of the deny list, see community template: +# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore +# +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +# Go workspace file +go.work + +# End of https://www.toptal.com/developers/gitignore/api/go diff --git a/services/pocketbase/go.mod b/services/pocketbase/go.mod new file mode 100644 index 00000000..fec7d6ad --- /dev/null +++ b/services/pocketbase/go.mod @@ -0,0 +1,46 @@ +module futureporn + +go 1.25.1 + +require github.com/pocketbase/pocketbase v0.34.0 + +require ( + github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect + github.com/disintegration/imaging v1.6.2 // indirect + github.com/dlclark/regexp2 v1.11.5 // indirect + github.com/domodwyer/mailyak/v3 v3.6.2 // indirect + github.com/dop251/base64dec v0.0.0-20231022112746-c6c9f9a96217 // indirect + github.com/dop251/goja v0.0.0-20251103141225-af2ceb9156d7 // indirect + github.com/dop251/goja_nodejs v0.0.0-20250409162600-f7acab6894b0 // indirect + github.com/dustin/go-humanize v1.0.1 // indirect + github.com/fatih/color v1.18.0 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.11 // indirect + github.com/ganigeorgiev/fexpr v0.5.0 // indirect + github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect + github.com/go-sourcemap/sourcemap v2.1.4+incompatible // indirect + github.com/golang-jwt/jwt/v5 v5.3.0 // indirect + github.com/google/pprof v0.0.0-20251007162407-5df77e3f7d1d // indirect + github.com/google/uuid v1.6.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/mattn/go-colorable v0.1.14 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/ncruces/go-strftime v1.0.0 // indirect + github.com/pocketbase/dbx v1.11.0 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/spf13/cobra v1.10.1 // indirect + github.com/spf13/pflag v1.0.10 // indirect + golang.org/x/crypto v0.45.0 // indirect + golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6 // indirect + golang.org/x/image v0.33.0 // indirect + golang.org/x/net v0.47.0 // indirect + golang.org/x/oauth2 v0.33.0 // indirect + golang.org/x/sync v0.18.0 // indirect + golang.org/x/sys v0.38.0 // indirect + golang.org/x/text v0.31.0 // indirect + modernc.org/libc v1.66.10 // indirect + modernc.org/mathutil v1.7.1 // indirect + modernc.org/memory v1.11.0 // indirect + modernc.org/sqlite v1.40.1 // indirect +) diff --git a/services/pocketbase/go.sum b/services/pocketbase/go.sum new file mode 100644 index 00000000..63a8d4be --- /dev/null +++ b/services/pocketbase/go.sum @@ -0,0 +1,141 @@ +github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= +github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3dyBCFEj5IhUbnKptjxatkF07cF2ak3yi77so= +github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= +github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= +github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= +github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44amcmDAg8hxG0Ewe4= +github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= +github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/domodwyer/mailyak/v3 v3.6.2 h1:x3tGMsyFhTCaxp6ycgR0FE/bu5QiNp+hetUuCOBXMn8= +github.com/domodwyer/mailyak/v3 v3.6.2/go.mod h1:lOm/u9CyCVWHeaAmHIdF4RiKVxKUT/H5XX10lIKAL6c= +github.com/dop251/base64dec v0.0.0-20231022112746-c6c9f9a96217 h1:16iT9CBDOniJwFGPI41MbUDfEk74hFaKTqudrX8kenY= +github.com/dop251/base64dec v0.0.0-20231022112746-c6c9f9a96217/go.mod h1:eIb+f24U+eWQCIsj9D/ah+MD9UP+wdxuqzsdLD+mhGM= +github.com/dop251/goja v0.0.0-20251103141225-af2ceb9156d7 h1:jxmXU5V9tXxJnydU5v/m9SG8TRUa/Z7IXODBpMs/P+U= +github.com/dop251/goja v0.0.0-20251103141225-af2ceb9156d7/go.mod h1:MxLav0peU43GgvwVgNbLAj1s/bSGboKkhuULvq/7hx4= +github.com/dop251/goja_nodejs v0.0.0-20250409162600-f7acab6894b0 h1:fuHXpEVTTk7TilRdfGRLHpiTD6tnT0ihEowCfWjlFvw= +github.com/dop251/goja_nodejs v0.0.0-20250409162600-f7acab6894b0/go.mod h1:Tb7Xxye4LX7cT3i8YLvmPMGCV92IOi4CDZvm/V8ylc0= +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/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/gabriel-vasile/mimetype v1.4.11 h1:AQvxbp830wPhHTqc1u7nzoLT+ZFxGY7emj5DR5DYFik= +github.com/gabriel-vasile/mimetype v1.4.11/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= +github.com/ganigeorgiev/fexpr v0.5.0 h1:XA9JxtTE/Xm+g/JFI6RfZEHSiQlk+1glLvRK1Lpv/Tk= +github.com/ganigeorgiev/fexpr v0.5.0/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE= +github.com/go-ozzo/ozzo-validation/v4 v4.3.0 h1:byhDUpfEwjsVQb1vBunvIjh2BHQ9ead57VkAEY4V+Es= +github.com/go-ozzo/ozzo-validation/v4 v4.3.0/go.mod h1:2NKgrcHl3z6cJs+3Oo940FPRiTzuqKbvfrL2RxCj6Ew= +github.com/go-sourcemap/sourcemap v2.1.4+incompatible h1:a+iTbH5auLKxaNwQFg0B+TCYl6lbukKPc7b5x0n1s6Q= +github.com/go-sourcemap/sourcemap v2.1.4+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= +github.com/go-sql-driver/mysql v1.4.1 h1:g24URVg0OFbNUTx9qqY1IRZ9D9z3iPyi5zKhQZpNwpA= +github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= +github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +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/pprof v0.0.0-20251007162407-5df77e3f7d1d h1:KJIErDwbSHjnp/SGzE5ed8Aol7JsKiI5X7yWKAtzhM0= +github.com/google/pprof v0.0.0-20251007162407-5df77e3f7d1d/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= +github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= +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/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= +github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pocketbase/dbx v1.11.0 h1:LpZezioMfT3K4tLrqA55wWFw1EtH1pM4tzSVa7kgszU= +github.com/pocketbase/dbx v1.11.0/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs= +github.com/pocketbase/pocketbase v0.34.0 h1:5W80PrGvkRYIMAIK90F7w031/hXgZVz1KSuCJqSpgJo= +github.com/pocketbase/pocketbase v0.34.0/go.mod h1:K/9z/Zb9PR9yW2Qyoc73jHV/EKT8cMTk9bQWyrzYlvI= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/cobra v1.10.1 h1:lJeBwCfmrnXthfAupyUTzJ/J4Nc1RsHC/mSRU2dll/s= +github.com/spf13/cobra v1.10.1/go.mod h1:7SmJGaTHFVBY0jW4NXGluQoLvhqFQM+6XSKD+P4XaB0= +github.com/spf13/pflag v1.0.9/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.45.0 h1:jMBrvKuj23MTlT0bQEOBcAE0mjg8mK9RXFhRH6nyF3Q= +golang.org/x/crypto v0.45.0/go.mod h1:XTGrrkGJve7CYK7J8PEww4aY7gM3qMCElcJQ8n8JdX4= +golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6 h1:zfMcR1Cs4KNuomFFgGefv5N0czO2XZpUbxGUy8i8ug0= +golang.org/x/exp v0.0.0-20251113190631-e25ba8c21ef6/go.mod h1:46edojNIoXTNOhySWIWdix628clX9ODXwPsQuG6hsK0= +golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/image v0.33.0 h1:LXRZRnv1+zGd5XBUVRFmYEphyyKJjQjCRiOuAP3sZfQ= +golang.org/x/image v0.33.0/go.mod h1:DD3OsTYT9chzuzTQt+zMcOlBHgfoKQb1gry8p76Y1sc= +golang.org/x/mod v0.30.0 h1:fDEXFVZ/fmCKProc/yAXXUijritrDzahmwwefnjoPFk= +golang.org/x/mod v0.30.0/go.mod h1:lAsf5O2EvJeSFMiBxXDki7sCgAxEUcZHXoXMKT4GJKc= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.47.0 h1:Mx+4dIFzqraBXUugkia1OOvlD6LemFo1ALMHjrXDOhY= +golang.org/x/net v0.47.0/go.mod h1:/jNxtkgq5yWUGYkaZGqo27cfGZ1c5Nen03aYrrKpVRU= +golang.org/x/oauth2 v0.33.0 h1:4Q+qn+E5z8gPRJfmRy7C2gGG3T4jIprK6aSYgTXGRpo= +golang.org/x/oauth2 v0.33.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= +golang.org/x/sync v0.18.0 h1:kr88TuHDroi+UVf+0hZnirlk8o8T+4MrK6mr60WkH/I= +golang.org/x/sync v0.18.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= +golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= +golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.39.0 h1:ik4ho21kwuQln40uelmciQPp9SipgNDdrafrYA4TmQQ= +golang.org/x/tools v0.39.0/go.mod h1:JnefbkDPyD8UU2kI5fuf8ZX4/yUeh9W877ZeBONxUqQ= +google.golang.org/appengine v1.6.5 h1:tycE03LOZYQNhDpS27tcQdAzLCVMaj7QT2SXxebnpCM= +google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +modernc.org/cc/v4 v4.26.5 h1:xM3bX7Mve6G8K8b+T11ReenJOT+BmVqQj0FY5T4+5Y4= +modernc.org/cc/v4 v4.26.5/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= +modernc.org/ccgo/v4 v4.28.1 h1:wPKYn5EC/mYTqBO373jKjvX2n+3+aK7+sICCv4Fjy1A= +modernc.org/ccgo/v4 v4.28.1/go.mod h1:uD+4RnfrVgE6ec9NGguUNdhqzNIeeomeXf6CL0GTE5Q= +modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA= +modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= +modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= +modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= +modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= +modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= +modernc.org/libc v1.66.10 h1:yZkb3YeLx4oynyR+iUsXsybsX4Ubx7MQlSYEw4yj59A= +modernc.org/libc v1.66.10/go.mod h1:8vGSEwvoUoltr4dlywvHqjtAqHBaw0j1jI7iFBTAr2I= +modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= +modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= +modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= +modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= +modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= +modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= +modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= +modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= +modernc.org/sqlite v1.40.1 h1:VfuXcxcUWWKRBuP8+BR9L7VnmusMgBNNnBYGEe9w/iY= +modernc.org/sqlite v1.40.1/go.mod h1:9fjQZ0mB1LLP0GYrp39oOJXx/I2sxEnZtzCmEQIKvGE= +modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= +modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= diff --git a/services/pocketbase/main.go b/services/pocketbase/main.go new file mode 100644 index 00000000..61316ab5 --- /dev/null +++ b/services/pocketbase/main.go @@ -0,0 +1,148 @@ +// @see https://github.com/pocketbase/pocketbase/blob/master/examples/base/main.go + +package main + +import ( + "futureporn/src/handlers" + "log" + "net/http" + "os" + "path/filepath" + + "github.com/pocketbase/pocketbase" + "github.com/pocketbase/pocketbase/apis" + "github.com/pocketbase/pocketbase/core" + "github.com/pocketbase/pocketbase/plugins/ghupdate" + "github.com/pocketbase/pocketbase/plugins/jsvm" + "github.com/pocketbase/pocketbase/plugins/migratecmd" + "github.com/pocketbase/pocketbase/tools/hook" + "github.com/pocketbase/pocketbase/tools/osutils" +) + +func main() { + app := pocketbase.New() + + // --------------------------------------------------------------- + // Optional plugin flags: + // --------------------------------------------------------------- + + var hooksDir string + app.RootCmd.PersistentFlags().StringVar( + &hooksDir, + "hooksDir", + "", + "the directory with the JS app hooks", + ) + + var hooksWatch bool + app.RootCmd.PersistentFlags().BoolVar( + &hooksWatch, + "hooksWatch", + true, + "auto restart the app on pb_hooks file change; it has no effect on Windows", + ) + + var hooksPool int + app.RootCmd.PersistentFlags().IntVar( + &hooksPool, + "hooksPool", + 15, + "the total prewarm goja.Runtime instances for the JS app hooks execution", + ) + + var migrationsDir string + app.RootCmd.PersistentFlags().StringVar( + &migrationsDir, + "migrationsDir", + "", + "the directory with the user defined migrations", + ) + + var automigrate bool + app.RootCmd.PersistentFlags().BoolVar( + &automigrate, + "automigrate", + true, + "enable/disable auto migrations", + ) + + var publicDir string + app.RootCmd.PersistentFlags().StringVar( + &publicDir, + "publicDir", + defaultPublicDir(), + "the directory to serve static files", + ) + + var indexFallback bool + app.RootCmd.PersistentFlags().BoolVar( + &indexFallback, + "indexFallback", + true, + "fallback the request to index.html on missing static path, e.g. when pretty urls are used with SPA", + ) + + app.RootCmd.ParseFlags(os.Args[1:]) + + // --------------------------------------------------------------- + // Plugins and hooks: + // --------------------------------------------------------------- + + // load jsvm (pb_hooks and pb_migrations) + jsvm.MustRegister(app, jsvm.Config{ + MigrationsDir: migrationsDir, + HooksDir: hooksDir, + HooksWatch: hooksWatch, + HooksPoolSize: hooksPool, + }) + + // migrate command (with js templates) + migratecmd.MustRegister(app, app.RootCmd, migratecmd.Config{ + TemplateLang: migratecmd.TemplateLangJS, + Automigrate: automigrate, + Dir: migrationsDir, + }) + + // GitHub selfupdate + ghupdate.MustRegister(app, app.RootCmd, ghupdate.Config{}) + + // route for generating hls playlists with BunnyCDN signed URLs + app.OnServe().BindFunc(func(se *core.ServeEvent) error { + se.Router.GET("/api/hls/{collectionId}/{recordId}/hls/{fileName}", handlers.PackageHandler) + return se.Next() + }) + + // route for direct downloads (patrons only) + app.OnServe().BindFunc(func(se *core.ServeEvent) error { + se.Router.GET("/api/download/{collectionId}/{recordId}/{fileName}", handlers.S3Download) + return se.Next() + }) + + // static route to serves files from the provided public dir + // (if publicDir exists and the route path is not already defined) + app.OnServe().Bind(&hook.Handler[*core.ServeEvent]{ + Func: func(e *core.ServeEvent) error { + if !e.Router.HasRoute(http.MethodGet, "/{path...}") { + e.Router.GET("/{path...}", apis.Static(os.DirFS(publicDir), indexFallback)) + } + + return e.Next() + }, + Priority: 999, // execute as latest as possible to allow users to provide their own route + }) + + app.OnFileDownloadRequest().BindFunc(handlers.HandleFileDownload) + + if err := app.Start(); err != nil { + log.Fatal(err) + } +} + +// the default pb_public dir location is relative to the executable +func defaultPublicDir() string { + if osutils.IsProbablyGoRun() { + return "./pb_public" + } + + return filepath.Join(os.Args[0], "../pb_public") +} diff --git a/services/pocketbase/package.json b/services/pocketbase/package.json index 771b24aa..5d21b77f 100644 --- a/services/pocketbase/package.json +++ b/services/pocketbase/package.json @@ -1,6 +1,6 @@ { "name": "futureporn", - "version": "4.0.0", + "version": "4.2.0", "private": true, "description": "Dedication to the preservation of lewdtuber history", "license": "Unlicense", diff --git a/services/pocketbase/pb_hooks/cdn.pb.js b/services/pocketbase/pb_hooks/cdn.pb.js.noexec similarity index 52% rename from services/pocketbase/pb_hooks/cdn.pb.js rename to services/pocketbase/pb_hooks/cdn.pb.js.noexec index 21d0aa8b..209b0e5f 100644 --- a/services/pocketbase/pb_hooks/cdn.pb.js +++ b/services/pocketbase/pb_hooks/cdn.pb.js.noexec @@ -1,7 +1,5 @@ /// - - /** * onFileDownloadRequest hook is triggered before each API File download request. Could be used to validate or modify the file response before returning it to the client. * @see https://pocketbase.io/docs/js-event-hooks/#onfiledownloadrequest @@ -13,7 +11,12 @@ onFileDownloadRequest((event) => { - // console.log('event', JSON.stringify(event)) + console.log('>>> We got a file download request event', JSON.stringify(event)) + + + console.log('the below the following is event.request'); + console.log(JSON.stringify(event.request)); + console.log('the above the previous line is event.request'); // e.app // e.collection // e.record @@ -24,7 +27,7 @@ onFileDownloadRequest((event) => { const securityKey = process.env?.BUNNY_TOKEN_KEY; const baseUrl = process.env?.BUNNY_ZONE_URL; - // console.log(`securityKey=${securityKey}, baseUrl=${baseUrl}`) + console.log(`securityKey=${securityKey}, baseUrl=${baseUrl}`) if (!securityKey) { console.error('BUNNY_TOKEN_KEY was missing from env'); @@ -37,34 +40,52 @@ onFileDownloadRequest((event) => { /** * Generate a signed BunnyCDN URL. + * + * @see https://support.bunny.net/hc/en-us/articles/360016055099-How-to-sign-URLs-for-BunnyCDN-Token-Authentication + * * @param {string} securityKey - Your BunnyCDN security token - * @param {string} baseUrl - The base URL (protocol + host) - * @param {string} path - Path to the file (starting with /) - * @param {string} rawQuery - Raw query string, e.g., "width=500&quality=5" + * @param {string} inputUrl - The base URL (protocol + host + path + (optional) qs) * @param {number} expires - Unix timestamp for expiration + * @param {string} tokenPath - (optional) create a token that has access to any file within that path */ - function signUrlCool(securityKey, baseUrl, path, rawQuery = "", expires) { + function signUrlCool(securityKey, inputUrl, expires, tokenPath = '') { - if (!path.startsWith('/')) path = '/' + path; - if (baseUrl.endsWith('/')) throw new Error(`baseUrl must not end with a slash. got baseUrl=${baseUrl}`); + if (inputUrl.endsWith('/')) throw new Error(`url must not end with a slash. got inputUrl=${inputUrl}`); + + + // reading query parameters + // let search = e.request.url.query().get("search") + const URL = event.request.url + + + + let parsedURL = URL.parse(inputUrl); // this is pre-parsed. no need to parse again + let params = (URL.parse(parsedURL)).searchParams; // these are pre-parsed as event.request.url.rawQuery. no need to parse again + let signaturePath = ''; + let parameterData = ''; + let parameterDataUrl = ''; + + console.log(`eyy we got parsedURL=${parsedURL}`); + + throw new Error('@todo'); // Build parameter string (sort keys alphabetically) - let parameterData = ""; - if (rawQuery) { - const params = rawQuery - .split("&") - .map(p => p.split("=")) - .filter(([key]) => key && key !== "token" && key !== "expires") - .sort(([a], [b]) => a.localeCompare(b)); + // let parameterData = ""; + // if (rawQuery) { + // const params = rawQuery + // .split("&") + // .map(p => p.split("=")) + // .filter(([key]) => key && key !== "token" && key !== "expires") + // .sort(([a], [b]) => a.localeCompare(b)); - if (params.length) { - parameterData = params.map(([k, v]) => `${k}=${v}`).join("&"); - } - } + // if (params.length) { + // parameterData = params.map(([k, v]) => `${k}=${v}`).join("&"); + // } + // } // Build hashable base const hashableBase = securityKey + path + expires + parameterData; - // console.log(`hashableBase`, hashableBase) + console.log(`hashableBase`, hashableBase) // Compute token using your $security.sha256 workflow const tokenH = $security.sha256(hashableBase); @@ -79,6 +100,7 @@ onFileDownloadRequest((event) => { let tokenUrl = baseUrl + path + "?token=" + token; if (parameterData) tokenUrl += "&" + parameterData; tokenUrl += "&expires=" + expires; + if (tokenPath) tokenUrl += "&token_path=" + tokenPath; return tokenUrl; } @@ -87,12 +109,12 @@ onFileDownloadRequest((event) => { const rawQuery = event.requestEvent.request.url.rawQuery; - // console.log(`record: ${JSON.stringify(event.record)}`) - // // console.log(`collection: ${JSON.stringify(event.collection)}`) - // console.log(`app: ${JSON.stringify(event.app)}`) - // console.log(`fileField: ${JSON.stringify(event.fileField)}`) - // console.log(`servedPath: ${JSON.stringify(event.servedPath)}`) - // console.log(`servedName: ${JSON.stringify(event.servedName)}`) + console.log(`record: ${JSON.stringify(event.record)}`) + // console.log(`collection: ${JSON.stringify(event.collection)}`) + console.log(`app: ${JSON.stringify(event.app)}`) + console.log(`fileField: ${JSON.stringify(event.fileField)}`) + console.log(`servedPath: ${JSON.stringify(event.servedPath)}`) + console.log(`servedName: ${JSON.stringify(event.servedName)}`) // Our job here is to take the servedPath, and sign it using bunnycdn method // Then serve a 302 redirect instead of serving the file proxied thru PB @@ -100,8 +122,8 @@ onFileDownloadRequest((event) => { const path = event.servedPath; const expires = Math.round(Date.now() / 1000) + 7 * 24 * 3600; // 7 days const signedUrl = signUrlCool(securityKey, baseUrl, path, rawQuery, expires); - // console.log(`rawQUery`, rawQuery, 'path', path); - // console.log(`signedUrl=${signedUrl}`); + console.log(`rawQuery`, rawQuery, 'path', path); + console.log(`signedUrl=${signedUrl}`); // This redirect is a tricky thing. We do this to avoid proxying file requests via our pocketbase origin server. // The idea is to reduce load. diff --git a/services/pocketbase/pb_hooks/pages/(site)/+layout.ejs b/services/pocketbase/pb_hooks/pages/(site)/+layout.ejs index 2b966f64..e1c18d26 100644 --- a/services/pocketbase/pb_hooks/pages/(site)/+layout.ejs +++ b/services/pocketbase/pb_hooks/pages/(site)/+layout.ejs @@ -71,8 +71,9 @@