first commit
This commit is contained in:
commit
0157bb2e68
28
.gitignore
vendored
Normal file
28
.gitignore
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# dev
|
||||
.yarn/
|
||||
!.yarn/releases
|
||||
.vscode/*
|
||||
!.vscode/launch.json
|
||||
!.vscode/*.code-snippets
|
||||
.idea/workspace.xml
|
||||
.idea/usage.statistics.xml
|
||||
.idea/shelf
|
||||
|
||||
# deps
|
||||
node_modules/
|
||||
|
||||
# env
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# logs
|
||||
logs/
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
8
README.md
Normal file
8
README.md
Normal file
@ -0,0 +1,8 @@
|
||||
```
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
```
|
||||
open http://localhost:3000
|
||||
```
|
||||
735
package-lock.json
generated
Normal file
735
package-lock.json
generated
Normal file
@ -0,0 +1,735 @@
|
||||
{
|
||||
"name": "tuberepair",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "tuberepair",
|
||||
"dependencies": {
|
||||
"@hono/node-server": "^1.19.6",
|
||||
"@hono/zod-validator": "^0.7.6",
|
||||
"dotenv": "^17.2.3",
|
||||
"hono": "^4.11.1",
|
||||
"youtubei.js": "^16.0.1",
|
||||
"ytdl-core": "^4.11.5",
|
||||
"ytdlp-nodejs": "^2.3.5",
|
||||
"zod": "^4.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.17",
|
||||
"tsx": "^4.7.1",
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
},
|
||||
"node_modules/@bufbuild/protobuf": {
|
||||
"version": "2.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-2.10.2.tgz",
|
||||
"integrity": "sha512-uFsRXwIGyu+r6AMdz+XijIIZJYpoWeYzILt5yZ2d3mCjQrWUTVpVD9WL/jZAbvp+Ed04rOhrsk7FiTcEDseB5A==",
|
||||
"license": "(Apache-2.0 AND BSD-3-Clause)"
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz",
|
||||
"integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz",
|
||||
"integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz",
|
||||
"integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz",
|
||||
"integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz",
|
||||
"integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz",
|
||||
"integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz",
|
||||
"integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz",
|
||||
"integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz",
|
||||
"integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openharmony-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz",
|
||||
"integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz",
|
||||
"integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz",
|
||||
"integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@hono/node-server": {
|
||||
"version": "1.19.7",
|
||||
"resolved": "https://registry.npmjs.org/@hono/node-server/-/node-server-1.19.7.tgz",
|
||||
"integrity": "sha512-vUcD0uauS7EU2caukW8z5lJKtoGMokxNbJtBiwHgpqxEXokaHCBkQUmCHhjFB1VUTWdqj25QoMkMKzgjq+uhrw==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=18.14.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"hono": "^4"
|
||||
}
|
||||
},
|
||||
"node_modules/@hono/zod-validator": {
|
||||
"version": "0.7.6",
|
||||
"resolved": "https://registry.npmjs.org/@hono/zod-validator/-/zod-validator-0.7.6.tgz",
|
||||
"integrity": "sha512-Io1B6d011Gj1KknV4rXYz4le5+5EubcWEU/speUjuw9XMMIaP3n78yXLhjd2A3PXaXaUwEAluOiAyLqhBEJgsw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"hono": ">=3.9.0",
|
||||
"zod": "^3.25.0 || ^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@types/node": {
|
||||
"version": "20.19.27",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.27.tgz",
|
||||
"integrity": "sha512-N2clP5pJhB2YnZJ3PIHFk5RkygRX5WO/5f0WC08tp0wd+sv0rsJk3MqWn3CbNmT2J505a5336jaQj4ph1AdMug==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"undici-types": "~6.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "17.2.3",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz",
|
||||
"integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.27.2",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz",
|
||||
"integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.27.2",
|
||||
"@esbuild/android-arm": "0.27.2",
|
||||
"@esbuild/android-arm64": "0.27.2",
|
||||
"@esbuild/android-x64": "0.27.2",
|
||||
"@esbuild/darwin-arm64": "0.27.2",
|
||||
"@esbuild/darwin-x64": "0.27.2",
|
||||
"@esbuild/freebsd-arm64": "0.27.2",
|
||||
"@esbuild/freebsd-x64": "0.27.2",
|
||||
"@esbuild/linux-arm": "0.27.2",
|
||||
"@esbuild/linux-arm64": "0.27.2",
|
||||
"@esbuild/linux-ia32": "0.27.2",
|
||||
"@esbuild/linux-loong64": "0.27.2",
|
||||
"@esbuild/linux-mips64el": "0.27.2",
|
||||
"@esbuild/linux-ppc64": "0.27.2",
|
||||
"@esbuild/linux-riscv64": "0.27.2",
|
||||
"@esbuild/linux-s390x": "0.27.2",
|
||||
"@esbuild/linux-x64": "0.27.2",
|
||||
"@esbuild/netbsd-arm64": "0.27.2",
|
||||
"@esbuild/netbsd-x64": "0.27.2",
|
||||
"@esbuild/openbsd-arm64": "0.27.2",
|
||||
"@esbuild/openbsd-x64": "0.27.2",
|
||||
"@esbuild/openharmony-arm64": "0.27.2",
|
||||
"@esbuild/sunos-x64": "0.27.2",
|
||||
"@esbuild/win32-arm64": "0.27.2",
|
||||
"@esbuild/win32-ia32": "0.27.2",
|
||||
"@esbuild/win32-x64": "0.27.2"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/get-tsconfig": {
|
||||
"version": "4.13.0",
|
||||
"resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz",
|
||||
"integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"resolve-pkg-maps": "^1.0.0"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/get-tsconfig?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/hono": {
|
||||
"version": "4.11.1",
|
||||
"resolved": "https://registry.npmjs.org/hono/-/hono-4.11.1.tgz",
|
||||
"integrity": "sha512-KsFcH0xxHes0J4zaQgWbYwmz3UPOOskdqZmItstUG93+Wk1ePBLkLGwbP9zlmh1BFUiL8Qp+Xfu9P7feJWpGNg==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=16.9.0"
|
||||
}
|
||||
},
|
||||
"node_modules/m3u8stream": {
|
||||
"version": "0.8.6",
|
||||
"resolved": "https://registry.npmjs.org/m3u8stream/-/m3u8stream-0.8.6.tgz",
|
||||
"integrity": "sha512-LZj8kIVf9KCphiHmH7sbFQTVe4tOemb202fWwvJwR9W5ENW/1hxJN6ksAWGhQgSBSa3jyWhnjKU1Fw1GaOdbyA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"miniget": "^4.2.2",
|
||||
"sax": "^1.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/meriyah": {
|
||||
"version": "6.1.4",
|
||||
"resolved": "https://registry.npmjs.org/meriyah/-/meriyah-6.1.4.tgz",
|
||||
"integrity": "sha512-Sz8FzjzI0kN13GK/6MVEsVzMZEPvOhnmmI1lU5+/1cGOiK3QUahntrNNtdVeihrO7t9JpoH75iMNXg6R6uWflQ==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/miniget": {
|
||||
"version": "4.2.3",
|
||||
"resolved": "https://registry.npmjs.org/miniget/-/miniget-4.2.3.tgz",
|
||||
"integrity": "sha512-SjbDPDICJ1zT+ZvQwK0hUcRY4wxlhhNpHL9nJOB2MEAXRGagTljsO8MEDzQMTFf0Q8g4QNi8P9lEm/g7e+qgzA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/resolve-pkg-maps": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz",
|
||||
"integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"funding": {
|
||||
"url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/sax": {
|
||||
"version": "1.4.3",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz",
|
||||
"integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==",
|
||||
"license": "BlueOak-1.0.0"
|
||||
},
|
||||
"node_modules/tsx": {
|
||||
"version": "4.21.0",
|
||||
"resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz",
|
||||
"integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"esbuild": "~0.27.0",
|
||||
"get-tsconfig": "^4.7.5"
|
||||
},
|
||||
"bin": {
|
||||
"tsx": "dist/cli.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"fsevents": "~2.3.3"
|
||||
}
|
||||
},
|
||||
"node_modules/typescript": {
|
||||
"version": "5.9.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
|
||||
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
|
||||
"dev": true,
|
||||
"license": "Apache-2.0",
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.17"
|
||||
}
|
||||
},
|
||||
"node_modules/undici-types": {
|
||||
"version": "6.21.0",
|
||||
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
|
||||
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==",
|
||||
"dev": true,
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/youtubei.js": {
|
||||
"version": "16.0.1",
|
||||
"resolved": "https://registry.npmjs.org/youtubei.js/-/youtubei.js-16.0.1.tgz",
|
||||
"integrity": "sha512-3802bCAGkBc2/G5WUTc0l/bO5mPYJbQAHL04d9hE9PnrDHoBUT8MN721Yqt4RCNncAXdHcfee9VdJy3Fhq1r5g==",
|
||||
"funding": [
|
||||
"https://github.com/sponsors/LuanRT"
|
||||
],
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@bufbuild/protobuf": "^2.0.0",
|
||||
"meriyah": "^6.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/ytdl-core": {
|
||||
"version": "4.11.5",
|
||||
"resolved": "https://registry.npmjs.org/ytdl-core/-/ytdl-core-4.11.5.tgz",
|
||||
"integrity": "sha512-27LwsW4n4nyNviRCO1hmr8Wr5J1wLLMawHCQvH8Fk0hiRqrxuIu028WzbJetiYH28K8XDbeinYW4/wcHQD1EXA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"m3u8stream": "^0.8.6",
|
||||
"miniget": "^4.2.2",
|
||||
"sax": "^1.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
}
|
||||
},
|
||||
"node_modules/ytdlp-nodejs": {
|
||||
"version": "2.3.5",
|
||||
"resolved": "https://registry.npmjs.org/ytdlp-nodejs/-/ytdlp-nodejs-2.3.5.tgz",
|
||||
"integrity": "sha512-7V08DRv8C1K0HxJFvRoaoLYFS/reJ9VJBlaMVhEvdi2IsYK/9Hae1Mah65Y+bhk3RAmx7G9eTfpOhkj3bp0Zbw==",
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"ytdlp-nodejs": "dist/cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/zod": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/zod/-/zod-4.2.1.tgz",
|
||||
"integrity": "sha512-0wZ1IRqGGhMP76gLqz8EyfBXKk0J2qo2+H3fi4mcUP/KtTocoX08nmIAHl1Z2kJIZbZee8KOpBCSNPRgauucjw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/colinhacks"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
24
package.json
Normal file
24
package.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "tuberepair",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "tsx watch src/index.ts",
|
||||
"build": "tsc",
|
||||
"start": "node dist/index.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@hono/node-server": "^1.19.6",
|
||||
"@hono/zod-validator": "^0.7.6",
|
||||
"dotenv": "^17.2.3",
|
||||
"hono": "^4.11.1",
|
||||
"youtubei.js": "^16.0.1",
|
||||
"ytdl-core": "^4.11.5",
|
||||
"ytdlp-nodejs": "^2.3.5",
|
||||
"zod": "^4.2.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/node": "^20.11.17",
|
||||
"tsx": "^4.7.1",
|
||||
"typescript": "^5.8.3"
|
||||
}
|
||||
}
|
||||
21
schemas/2007/categories.cat
Normal file
21
schemas/2007/categories.cat
Normal file
@ -0,0 +1,21 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<app:categories
|
||||
xmlns:app='http://www.w3.org/2007/app'
|
||||
xmlns:atom='http://www.w3.org/2005/Atom'
|
||||
xmlns:yt='http://gdata.youtube.com/schemas/2007' fixed='yes' scheme='http://gdata.youtube.com/schemas/2007/categories.cat'>
|
||||
<atom:category term='Film' label='Film & Animation' xml:lang='en-US'>
|
||||
<yt:assignable/>
|
||||
<yt:browsable regions='AE AR AU BD BE BG BR CA CL CO CZ DE DK DZ EE EG ES ET FI FR GB GH GR HK HR HU ID IE IL IN IR IS IT JO JP KE KR LT LV MA MX MY NG NL NO NZ PE PH PK PL PT RO RS RU SA SE SG SI SK SN TH TN TR TW TZ UA UG US VN YE ZA'/>
|
||||
</atom:category>
|
||||
|
||||
<atom:category term='Music' label='Music' xml:lang='en-US'>
|
||||
<yt:assignable/>
|
||||
<yt:browsable regions='AE AR AU BD BE BG BR CA CL CO CZ DE DK DZ EE EG ES ET FI FR GB GH GR HK HR HU ID IE IL IN IR IS IT JO JP KE KR LT LV MA MX MY NG NL NO NZ PE PH PK PL PT RO RS RU SA SE SG SI SK SN TH TN TR TW TZ UA UG US VN YE ZA'/>
|
||||
</atom:category>
|
||||
|
||||
<atom:category term='Games' label='Gaming' xml:lang='en-US'>
|
||||
<yt:assignable/>
|
||||
<yt:browsable regions='AE AR AU BD BE BG BR CA CL CO CZ DE DK DZ EE EG ES ET FI FR GB GH GR HK HR HU ID IE IL IN IR IS IT JO JP KE KR LT LV MA MX MY NG NL NO NZ PE PH PK PL PT RO RS RU SA SE SG SI SK SN TH TN TR TW TZ UA UG US VN YE ZA'/>
|
||||
</atom:category>
|
||||
|
||||
</app:categories>
|
||||
24
src/api/playback.ts
Normal file
24
src/api/playback.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import innertube from "../lib/innertube.js";
|
||||
import { PlayVideo } from "../models/PlayVideo.js";
|
||||
import { Hono } from "hono";
|
||||
|
||||
const playback = new Hono();
|
||||
|
||||
playback.get(
|
||||
"/:id",
|
||||
zValidator("param", PlayVideo),
|
||||
async (c) => {
|
||||
const { id } = c.req.valid("param");
|
||||
const data = await innertube.getStreamingData(id, {
|
||||
type: "video+audio",
|
||||
quality: "best",
|
||||
format: "mp4",
|
||||
client: "TV",
|
||||
});
|
||||
if (!data.url) return c.status(400);
|
||||
return c.redirect(data.url, 307);
|
||||
}
|
||||
)
|
||||
|
||||
export default playback
|
||||
55
src/api/video.ts
Normal file
55
src/api/video.ts
Normal file
@ -0,0 +1,55 @@
|
||||
import { Hono } from "hono";
|
||||
import innertube from "../lib/innertube.js";
|
||||
import { zValidator } from "@hono/zod-validator";
|
||||
import { SearchVideos } from "../models/SearchVideos.js";
|
||||
import search from "../templates/search.js";
|
||||
import { YTNodes } from "youtubei.js";
|
||||
|
||||
const video = new Hono();
|
||||
|
||||
video.get(
|
||||
"/videos",
|
||||
zValidator("query", SearchVideos),
|
||||
async (c) => {
|
||||
const params = c.req.valid("query");
|
||||
const page = params["start-index"] ?? 1;
|
||||
|
||||
if (page > 5) {
|
||||
return c.html(search([], ""));
|
||||
}
|
||||
|
||||
// * fetch all videos up to current page
|
||||
const allVideos: YTNodes.Video[] = [];
|
||||
let searchQuery = await innertube.search(params.q, {
|
||||
duration: params.duration,
|
||||
upload_date: params.time,
|
||||
sort_by: params.orderby
|
||||
});
|
||||
|
||||
for (let i = 1; i <= page; i++) {
|
||||
const videos = searchQuery.results.filter(
|
||||
(node): node is YTNodes.Video => node.type === "Video"
|
||||
);
|
||||
allVideos.push(...videos);
|
||||
|
||||
if (i < page) {
|
||||
try {
|
||||
const nextPage = await searchQuery.getContinuation();
|
||||
if (!nextPage) break;
|
||||
searchQuery = nextPage;
|
||||
} catch (err) {
|
||||
// * no more pages available
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// * build next page URL
|
||||
const nextUrl = new URL(c.req.url);
|
||||
nextUrl.searchParams.set("start-index", (page + 1).toString());
|
||||
|
||||
return c.html(search(allVideos, nextUrl.toString()));
|
||||
}
|
||||
);
|
||||
|
||||
export default video;
|
||||
24
src/index.ts
Normal file
24
src/index.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import "dotenv/config"
|
||||
import { Hono } from "hono"
|
||||
import { logger } from "hono/logger"
|
||||
import { serve } from "@hono/node-server"
|
||||
import { serveStatic } from "@hono/node-server/serve-static"
|
||||
import { config } from "./lib/config.js"
|
||||
|
||||
import video from "./api/video.js"
|
||||
import playback from "./api/playback.js"
|
||||
|
||||
const app = new Hono()
|
||||
|
||||
app.use(logger())
|
||||
app.use("/schemas/*", serveStatic({ root: "./" }))
|
||||
|
||||
app.route("/getvideo", playback);
|
||||
app.route("/feeds/api", video);
|
||||
|
||||
serve({
|
||||
fetch: app.fetch,
|
||||
port: config.PORT
|
||||
}, (info) => {
|
||||
console.log(`Server is running on http://localhost:${info.port}`)
|
||||
})
|
||||
16
src/lib/config.ts
Normal file
16
src/lib/config.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { z } from "zod";
|
||||
import "dotenv/config"
|
||||
|
||||
const EnvSchema = z.object({
|
||||
BASE_URL: z.url(),
|
||||
PORT: z.coerce.number().default(4000)
|
||||
});
|
||||
|
||||
const parsed = EnvSchema.safeParse(process.env);
|
||||
|
||||
if (!parsed.success) {
|
||||
console.error("Invalid config", parsed.error.format());
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
export const config = parsed.data;
|
||||
16
src/lib/innertube.ts
Normal file
16
src/lib/innertube.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { Innertube, Platform, type Types } from 'youtubei.js';
|
||||
|
||||
Platform.shim.eval = async (
|
||||
data: Types.BuildScriptResult,
|
||||
env: Record<string, Types.VMPrimative>
|
||||
) => {
|
||||
const properties: string[] = [];
|
||||
if (env.n) properties.push(`n: exportedVars.nFunction("${env.n}")`);
|
||||
if (env.sig) properties.push(`sig: exportedVars.sigFunction("${env.sig}")`);
|
||||
|
||||
const code = `${data.output}\nreturn { ${properties.join(', ')} }`;
|
||||
return new Function(code)();
|
||||
};
|
||||
|
||||
const innertube = await Innertube.create();
|
||||
export default innertube
|
||||
5
src/models/PlayVideo.ts
Normal file
5
src/models/PlayVideo.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import z from "zod";
|
||||
|
||||
export const PlayVideo = z.object({
|
||||
id: z.string().length(11)
|
||||
});
|
||||
27
src/models/SearchVideos.ts
Normal file
27
src/models/SearchVideos.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import z from "zod";
|
||||
|
||||
export const SearchVideos = z.object({
|
||||
q: z.string().min(1),
|
||||
time: z.preprocess((val) => {
|
||||
if (typeof val !== "string") return undefined;
|
||||
switch (val) {
|
||||
case "all_time": return "all";
|
||||
case "today": return "today";
|
||||
case "this_week": return "week";
|
||||
case "this_month": return "month";
|
||||
case "this_year": return "year";
|
||||
default: return undefined;
|
||||
}
|
||||
}, z.enum(["all", "hour", "today", "week", "month", "year"]).optional()),
|
||||
orderby: z.preprocess((val) => {
|
||||
if (typeof val !== "string") return undefined;
|
||||
switch (val) {
|
||||
case "rating": return "rating";
|
||||
case "published": "upload_date;"
|
||||
case "viewCount": return "view_count";
|
||||
default: return "relevance";
|
||||
}
|
||||
}, z.enum(["relevance", "rating", "upload_date", "view_count"]).optional()),
|
||||
duration: z.enum(['all', 'short', 'medium', 'long']).optional(),
|
||||
"start-index": z.preprocess(val => Number(val), z.number().min(1)).optional(),
|
||||
});
|
||||
106
src/templates/search.ts
Normal file
106
src/templates/search.ts
Normal file
@ -0,0 +1,106 @@
|
||||
import { html } from "hono/html";
|
||||
import { config } from "../lib/config.js";
|
||||
import { YTNodes } from "youtubei.js";
|
||||
|
||||
export default (
|
||||
videos: YTNodes.Video[],
|
||||
nextPage: string
|
||||
) => html`
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed
|
||||
xmlns="http://www.w3.org/2005/Atom"
|
||||
xmlns:gd="http://schemas.google.com/g/2005"
|
||||
xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/"
|
||||
xmlns:yt="${config.BASE_URL}/schemas/2007"
|
||||
xmlns:media="http://search.yahoo.com/mrss/"
|
||||
gd:etag="W/"DkcBQ3g-fip7I2A9XRRXEUw."">
|
||||
|
||||
<id>tag:youtube.com,2008:channels</id>
|
||||
<updated>${new Date().toISOString()}</updated>
|
||||
<category scheme="http://schemas.google.com/g/2005#kind" term="${config.BASE_URL}/schemas/2007#channel"/>
|
||||
<title>Channels matching: webauditors</title>
|
||||
<logo>http://www.gstatic.com/youtube/img/logo.png</logo>
|
||||
|
||||
<link rel="http://schemas.google.com/g/2006#spellcorrection" type="application/atom+xml" href="${config.BASE_URL}/feeds/api/channels?q=web+auditors&start-index=1&max-results=1&oi=spell&spell=1&v=2" title="web auditors"/>
|
||||
<link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="${config.BASE_URL}/feeds/api/channels?v=2"/>
|
||||
<link rel="http://schemas.google.com/g/2005#batch" type="application/atom+xml" href="${config.BASE_URL}/feeds/api/channels/batch?v=2"/>
|
||||
<link rel="self" type="application/atom+xml" href="${config.BASE_URL}/feeds/api/channels?q=webauditors&start-index=1&max-results=1&v=2"/>
|
||||
<link rel="service" type="application/atomsvc+xml" href="${config.BASE_URL}/feeds/api/channels?alt=atom-service&v=2"/>
|
||||
${nextPage ? html`<link rel="next" type="application/atom+xml" href="${nextPage}"/>` : ""}
|
||||
|
||||
<author>
|
||||
<name>YouTube</name>
|
||||
<uri>http://www.youtube.com/</uri>
|
||||
</author>
|
||||
|
||||
<generator version="2.1" uri="${config.BASE_URL}/">YouTube data API</generator>
|
||||
<openSearch:totalResults>${videos.length}</openSearch:totalResults>
|
||||
<openSearch:startIndex>1</openSearch:startIndex>
|
||||
<openSearch:itemsPerPage>${videos.length}</openSearch:itemsPerPage>
|
||||
|
||||
${videos.map(video => html`
|
||||
<entry gd:etag='W/"YDwqeyM."'>
|
||||
<id>tag:youtube.com,2008:playlist:${video.video_id}:${video.video_id}</id>
|
||||
<published>${new Date().toISOString()}</published>
|
||||
<updated>${new Date().toISOString()}</updated>
|
||||
<category scheme='https://schemas.google.com/g/2005#kind' term='https://gdata.youtube.com/schemas/1970#video'/>
|
||||
<category scheme='https://gdata.youtube.com/schemas/1970/categories.cat' term='Howto' label='Howto & Style'/>
|
||||
<title>${video.title}</title>
|
||||
<content type='application/x-shockwave-flash' src="https://www.youtube.com/v/${video.video_id}?version=3&f=playlists&app=youtube_gdata"/>
|
||||
<link rel='alternate' type='text/html' href="https://www.youtube.com/watch?v=${video.video_id}&feature=youtube_gdata"/>
|
||||
<link rel='http://gdata.youtube.com/schemas/2007#video.related' type='application/atom+xml' href="https://gdata.youtube.com/feeds/api/videos/${video.video_id}/related"/>
|
||||
<link rel='https://gdata.youtube.com/schemas/1970#mobile' type='text/html' href="https://m.youtube.com/details?v=${video.video_id}"/>
|
||||
<link rel='https://gdata.youtube.com/schemas/1970#uploader' type='application/atom+xml' href="https://gdata.youtube.com/feeds/api/users/${video.author.id}?v=2"/>
|
||||
<link rel='related' type='application/atom+xml' href="https://gdata.youtube.com/feeds/api/videos/${video.video_id}?v=2"/>
|
||||
<link rel='self' type='application/atom+xml' href='https://gdata.youtube.com/feeds/api/playlists/8E2186857EE27746/PLyl9mKRbpNIpJC5B8qpcgKX8v8NI62Jho?v=2'/>
|
||||
<author>
|
||||
<name>${video.author.name}</name>
|
||||
<uri>https://gdata.youtube.com/feeds/api/users/${video.author.id}</uri>
|
||||
<yt:userId>${video.author.id}</yt:userId>
|
||||
</author>
|
||||
<yt:accessControl action='comment' permission='allowed'/>
|
||||
<yt:accessControl action='commentVote' permission='allowed'/>
|
||||
<yt:accessControl action='videoRespond' permission='moderated'/>
|
||||
<yt:accessControl action='rate' permission='allowed'/>
|
||||
<yt:accessControl action='embed' permission='allowed'/>
|
||||
<yt:accessControl action='list' permission='allowed'/>
|
||||
<yt:accessControl action='autoPlay' permission='allowed'/>
|
||||
<yt:accessControl action='syndicate' permission='allowed'/>
|
||||
<gd:comments>
|
||||
<gd:feedLink rel='https://gdata.youtube.com/schemas/1970#comments' href="${config.BASE_URL}/api/videos/${video.video_id}/comments?v=2" countHint='5'/>
|
||||
</gd:comments>
|
||||
<yt:location>Paris ,FR</yt:location>
|
||||
<media:group>
|
||||
<media:category label='Howto & Style' scheme='https://gdata.youtube.com/schemas/1970/categories.cat'>Howto</media:category>
|
||||
<media:content url="https://www.youtube.com/v/${video.video_id}?version=3&f=playlists&app=youtube_gdata" type='application/x-shockwave-flash' medium='video' isDefault='true' expression='full' duration='0' yt:format='5'/>
|
||||
<media:content url="${config.BASE_URL}/getvideo/${video.video_id}" type='video/3gpp' type='video/3gpp' medium='video' expression='full' duration='0' yt:format='1'/>
|
||||
<media:content url="${config.BASE_URL}/getvideo/${video.video_id}" type='video/3gpp' type='video/3gpp' medium='video' expression='full' duration='0' yt:format='6'/>
|
||||
<media:credit role='uploader' scheme='urn:youtube' yt:display="${video.author.name}" yt:type='partner'>${video.author.id}</media:credit>
|
||||
<media:description type='plain'>${video.description}</media:description>
|
||||
<media:keywords/>
|
||||
<media:license type='text/html' href='https://www.youtube.com/t/terms'>youtube</media:license>
|
||||
<media:player url="https://www.youtube.com/watch?v=${video.video_id}&feature=youtube_gdata_player"/>
|
||||
<media:thumbnail url="https://i.ytimg.com/vi/${video.video_id}/default.jpg" height='90' width='120' time='00:00:00.000' yt:name='default'/>
|
||||
<media:thumbnail url="https://i.ytimg.com/vi/${video.video_id}/mqdefault.jpg" height='180' width='320' yt:name='mqdefault'/>
|
||||
<media:thumbnail url="https://i.ytimg.com/vi/${video.video_id}/mqdefault.jpg" height='360' width='480' yt:name='hqdefault'/>
|
||||
<media:thumbnail url="https://i.ytimg.com/vi/${video.video_id}/default.jpg" height='90' width='120' time='00:00:00.000' yt:name='start'/>
|
||||
<media:thumbnail url="https://i.ytimg.com/vi/${video.video_id}/default.jpg" height='90' width='120' time='00:00:00.000' yt:name='middle'/>
|
||||
<media:thumbnail url="https://i.ytimg.com/vi/${video.video_id}/default.jpg" height='90' width='120' time='00:00:00.000' yt:name='end'/>
|
||||
<media:content url="${config.BASE_URL}/getvideo/${video.video_id}" type="video/mp4" medium="video" isDefault="true" expression="full" duration="0" yt:format="3" />
|
||||
<media:content url="${config.BASE_URL}/getvideo/${video.video_id}" type="video/3gpp" medium="video" expression="full" duration="0" yt:format="2" />
|
||||
<media:content url="${config.BASE_URL}/getvideo/${video.video_id}" type="video/mp4" medium="video" expression="full" duration="0" yt:format="8" />
|
||||
<media:content url="${config.BASE_URL}/getvideo/${video.video_id}" type="video/3gpp" medium="video" expression="full" duration="0" yt:format="9" />
|
||||
<media:title type='plain'>${video.title}</media:title>
|
||||
<yt:duration seconds="${video.length_text?.text}"/>
|
||||
<yt:uploaded>${new Date().toISOString()}</yt:uploaded>
|
||||
<yt:uploaderId>${video.author.id}</yt:uploaderId>
|
||||
<yt:videoid>${video.video_id}</yt:videoid>
|
||||
</media:group>
|
||||
<gd:rating average='0' max='0' min='0' numRaters='0' rel='https://schemas.google.com/g/2005#overall'/>
|
||||
<yt:recorded>1970-08-22</yt:recorded>
|
||||
<yt:statistics favoriteCount='0' viewCount="${video.view_count?.text}"/>
|
||||
<yt:rating numDislikes='100' numLikes='10000'/>
|
||||
<yt:position>1</yt:position>
|
||||
</entry>
|
||||
`)}
|
||||
`;
|
||||
16
tsconfig.json
Normal file
16
tsconfig.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ESNext",
|
||||
"module": "NodeNext",
|
||||
"strict": true,
|
||||
"verbatimModuleSyntax": true,
|
||||
"skipLibCheck": true,
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
"jsx": "react-jsx",
|
||||
"jsxImportSource": "hono/jsx",
|
||||
"outDir": "./dist"
|
||||
},
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user