Implement queudtorrents, selecting files, hash rather than id
This commit is contained in:
parent
772631d47f
commit
fc9ea4c29a
3 changed files with 360 additions and 179 deletions
338
client/package-lock.json
generated
338
client/package-lock.json
generated
|
|
@ -35,7 +35,7 @@
|
||||||
"@angular-eslint/eslint-plugin-template": "16.1.1",
|
"@angular-eslint/eslint-plugin-template": "16.1.1",
|
||||||
"@angular-eslint/schematics": "16.1.1",
|
"@angular-eslint/schematics": "16.1.1",
|
||||||
"@angular-eslint/template-parser": "16.1.1",
|
"@angular-eslint/template-parser": "16.1.1",
|
||||||
"@angular/cli": "^16.2.1",
|
"@angular/cli": "^16.2.14",
|
||||||
"@angular/compiler-cli": "^16.2.3",
|
"@angular/compiler-cli": "^16.2.3",
|
||||||
"@angular/language-service": "^16.2.3",
|
"@angular/language-service": "^16.2.3",
|
||||||
"@types/file-saver": "^2.0.5",
|
"@types/file-saver": "^2.0.5",
|
||||||
|
|
@ -352,12 +352,12 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"node_modules/@angular-devkit/schematics": {
|
"node_modules/@angular-devkit/schematics": {
|
||||||
"version": "16.2.1",
|
"version": "16.2.14",
|
||||||
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.14.tgz",
|
||||||
"integrity": "sha512-rXXO5zSI/iN6JtU3oU+vKfOB1N8n1iCH9aLudtJfO5zT9r29FIvV4YMmHO0iu78i4IhQAeJdr42cvrGPp8Y41A==",
|
"integrity": "sha512-B6LQKInCT8w5zx5Pbroext5eFFRTCJdTwHN8GhcVS8IeKCnkeqVTQLjB4lBUg7LEm8Y7UHXwzrVxmk+f+MBXhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular-devkit/core": "16.2.1",
|
"@angular-devkit/core": "16.2.14",
|
||||||
"jsonc-parser": "3.2.0",
|
"jsonc-parser": "3.2.0",
|
||||||
"magic-string": "0.30.1",
|
"magic-string": "0.30.1",
|
||||||
"ora": "5.4.1",
|
"ora": "5.4.1",
|
||||||
|
|
@ -369,6 +369,55 @@
|
||||||
"yarn": ">= 1.13.0"
|
"yarn": ">= 1.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@angular-devkit/schematics/node_modules/@angular-devkit/core": {
|
||||||
|
"version": "16.2.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz",
|
||||||
|
"integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ajv": "8.12.0",
|
||||||
|
"ajv-formats": "2.1.1",
|
||||||
|
"jsonc-parser": "3.2.0",
|
||||||
|
"picomatch": "2.3.1",
|
||||||
|
"rxjs": "7.8.1",
|
||||||
|
"source-map": "0.7.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^16.14.0 || >=18.10.0",
|
||||||
|
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
||||||
|
"yarn": ">= 1.13.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"chokidar": "^3.5.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"chokidar": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@angular-devkit/schematics/node_modules/ajv": {
|
||||||
|
"version": "8.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
|
||||||
|
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"fast-deep-equal": "^3.1.1",
|
||||||
|
"json-schema-traverse": "^1.0.0",
|
||||||
|
"require-from-string": "^2.0.2",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@angular-devkit/schematics/node_modules/json-schema-traverse": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@angular-eslint/builder": {
|
"node_modules/@angular-eslint/builder": {
|
||||||
"version": "16.1.1",
|
"version": "16.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular-eslint/builder/-/builder-16.1.1.tgz",
|
||||||
|
|
@ -544,15 +593,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@angular/cli": {
|
"node_modules/@angular/cli": {
|
||||||
"version": "16.2.1",
|
"version": "16.2.14",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.14.tgz",
|
||||||
"integrity": "sha512-nuCc0VOGjuUFQo1Pu9CyFQ4VTy7OuwTiwxOG9qbut4FSGz2CO9NeqoamPUuy6rpKVu5JxVe+L6Y4OFaNKv2n3Q==",
|
"integrity": "sha512-0y71jtitigVolm4Rim1b8xPQ+B22cGp4Spef2Wunpqj67UowN6tsZaVuWBEQh4u5xauX8LAHKqsvy37ZPWCc4A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular-devkit/architect": "0.1602.1",
|
"@angular-devkit/architect": "0.1602.14",
|
||||||
"@angular-devkit/core": "16.2.1",
|
"@angular-devkit/core": "16.2.14",
|
||||||
"@angular-devkit/schematics": "16.2.1",
|
"@angular-devkit/schematics": "16.2.14",
|
||||||
"@schematics/angular": "16.2.1",
|
"@schematics/angular": "16.2.14",
|
||||||
"@yarnpkg/lockfile": "1.1.0",
|
"@yarnpkg/lockfile": "1.1.0",
|
||||||
"ansi-colors": "4.1.3",
|
"ansi-colors": "4.1.3",
|
||||||
"ini": "4.1.1",
|
"ini": "4.1.1",
|
||||||
|
|
@ -577,6 +626,70 @@
|
||||||
"yarn": ">= 1.13.0"
|
"yarn": ">= 1.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@angular/cli/node_modules/@angular-devkit/architect": {
|
||||||
|
"version": "0.1602.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.14.tgz",
|
||||||
|
"integrity": "sha512-eSdONEV5dbtLNiOMBy9Ue9DdJ1ct6dH9RdZfYiedq6VZn0lejePAjY36MYVXgq2jTE+v/uIiaNy7caea5pt55A==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@angular-devkit/core": "16.2.14",
|
||||||
|
"rxjs": "7.8.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^16.14.0 || >=18.10.0",
|
||||||
|
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
||||||
|
"yarn": ">= 1.13.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@angular/cli/node_modules/@angular-devkit/core": {
|
||||||
|
"version": "16.2.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz",
|
||||||
|
"integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ajv": "8.12.0",
|
||||||
|
"ajv-formats": "2.1.1",
|
||||||
|
"jsonc-parser": "3.2.0",
|
||||||
|
"picomatch": "2.3.1",
|
||||||
|
"rxjs": "7.8.1",
|
||||||
|
"source-map": "0.7.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^16.14.0 || >=18.10.0",
|
||||||
|
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
||||||
|
"yarn": ">= 1.13.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"chokidar": "^3.5.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"chokidar": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@angular/cli/node_modules/ajv": {
|
||||||
|
"version": "8.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
|
||||||
|
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"fast-deep-equal": "^3.1.1",
|
||||||
|
"json-schema-traverse": "^1.0.0",
|
||||||
|
"require-from-string": "^2.0.2",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@angular/cli/node_modules/json-schema-traverse": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@angular/cli/node_modules/semver": {
|
"node_modules/@angular/cli/node_modules/semver": {
|
||||||
"version": "7.5.4",
|
"version": "7.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||||
|
|
@ -3665,13 +3778,13 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@schematics/angular": {
|
"node_modules/@schematics/angular": {
|
||||||
"version": "16.2.1",
|
"version": "16.2.14",
|
||||||
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.14.tgz",
|
||||||
"integrity": "sha512-e3ckgvSv+OA+4xUBpOqVOvNM8FqY/yXaWqs/Ob0uQ/zPL1iVa/MCAoB25KqYQPnq21hEwE4zqIIQFKasKBIqMA==",
|
"integrity": "sha512-YqIv727l9Qze8/OL6H9mBHc2jVXzAGRNBYnxYWqWhLbfvuVbbldo6NNIIjgv6lrl2LJSdPAAMNOD5m/f6210ug==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@angular-devkit/core": "16.2.1",
|
"@angular-devkit/core": "16.2.14",
|
||||||
"@angular-devkit/schematics": "16.2.1",
|
"@angular-devkit/schematics": "16.2.14",
|
||||||
"jsonc-parser": "3.2.0"
|
"jsonc-parser": "3.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
|
|
@ -3680,6 +3793,55 @@
|
||||||
"yarn": ">= 1.13.0"
|
"yarn": ">= 1.13.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@schematics/angular/node_modules/@angular-devkit/core": {
|
||||||
|
"version": "16.2.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz",
|
||||||
|
"integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"ajv": "8.12.0",
|
||||||
|
"ajv-formats": "2.1.1",
|
||||||
|
"jsonc-parser": "3.2.0",
|
||||||
|
"picomatch": "2.3.1",
|
||||||
|
"rxjs": "7.8.1",
|
||||||
|
"source-map": "0.7.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^16.14.0 || >=18.10.0",
|
||||||
|
"npm": "^6.11.0 || ^7.5.6 || >=8.0.0",
|
||||||
|
"yarn": ">= 1.13.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"chokidar": "^3.5.2"
|
||||||
|
},
|
||||||
|
"peerDependenciesMeta": {
|
||||||
|
"chokidar": {
|
||||||
|
"optional": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@schematics/angular/node_modules/ajv": {
|
||||||
|
"version": "8.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
|
||||||
|
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"fast-deep-equal": "^3.1.1",
|
||||||
|
"json-schema-traverse": "^1.0.0",
|
||||||
|
"require-from-string": "^2.0.2",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/epoberezkin"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@schematics/angular/node_modules/json-schema-traverse": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/@sigstore/bundle": {
|
"node_modules/@sigstore/bundle": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@sigstore/bundle/-/bundle-1.1.0.tgz",
|
||||||
|
|
@ -14563,16 +14725,50 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@angular-devkit/schematics": {
|
"@angular-devkit/schematics": {
|
||||||
"version": "16.2.1",
|
"version": "16.2.14",
|
||||||
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-16.2.14.tgz",
|
||||||
"integrity": "sha512-rXXO5zSI/iN6JtU3oU+vKfOB1N8n1iCH9aLudtJfO5zT9r29FIvV4YMmHO0iu78i4IhQAeJdr42cvrGPp8Y41A==",
|
"integrity": "sha512-B6LQKInCT8w5zx5Pbroext5eFFRTCJdTwHN8GhcVS8IeKCnkeqVTQLjB4lBUg7LEm8Y7UHXwzrVxmk+f+MBXhw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@angular-devkit/core": "16.2.1",
|
"@angular-devkit/core": "16.2.14",
|
||||||
"jsonc-parser": "3.2.0",
|
"jsonc-parser": "3.2.0",
|
||||||
"magic-string": "0.30.1",
|
"magic-string": "0.30.1",
|
||||||
"ora": "5.4.1",
|
"ora": "5.4.1",
|
||||||
"rxjs": "7.8.1"
|
"rxjs": "7.8.1"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@angular-devkit/core": {
|
||||||
|
"version": "16.2.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz",
|
||||||
|
"integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ajv": "8.12.0",
|
||||||
|
"ajv-formats": "2.1.1",
|
||||||
|
"jsonc-parser": "3.2.0",
|
||||||
|
"picomatch": "2.3.1",
|
||||||
|
"rxjs": "7.8.1",
|
||||||
|
"source-map": "0.7.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ajv": {
|
||||||
|
"version": "8.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
|
||||||
|
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fast-deep-equal": "^3.1.1",
|
||||||
|
"json-schema-traverse": "^1.0.0",
|
||||||
|
"require-from-string": "^2.0.2",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"json-schema-traverse": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@angular-eslint/builder": {
|
"@angular-eslint/builder": {
|
||||||
|
|
@ -14708,15 +14904,15 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@angular/cli": {
|
"@angular/cli": {
|
||||||
"version": "16.2.1",
|
"version": "16.2.14",
|
||||||
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@angular/cli/-/cli-16.2.14.tgz",
|
||||||
"integrity": "sha512-nuCc0VOGjuUFQo1Pu9CyFQ4VTy7OuwTiwxOG9qbut4FSGz2CO9NeqoamPUuy6rpKVu5JxVe+L6Y4OFaNKv2n3Q==",
|
"integrity": "sha512-0y71jtitigVolm4Rim1b8xPQ+B22cGp4Spef2Wunpqj67UowN6tsZaVuWBEQh4u5xauX8LAHKqsvy37ZPWCc4A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@angular-devkit/architect": "0.1602.1",
|
"@angular-devkit/architect": "0.1602.14",
|
||||||
"@angular-devkit/core": "16.2.1",
|
"@angular-devkit/core": "16.2.14",
|
||||||
"@angular-devkit/schematics": "16.2.1",
|
"@angular-devkit/schematics": "16.2.14",
|
||||||
"@schematics/angular": "16.2.1",
|
"@schematics/angular": "16.2.14",
|
||||||
"@yarnpkg/lockfile": "1.1.0",
|
"@yarnpkg/lockfile": "1.1.0",
|
||||||
"ansi-colors": "4.1.3",
|
"ansi-colors": "4.1.3",
|
||||||
"ini": "4.1.1",
|
"ini": "4.1.1",
|
||||||
|
|
@ -14733,6 +14929,48 @@
|
||||||
"yargs": "17.7.2"
|
"yargs": "17.7.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@angular-devkit/architect": {
|
||||||
|
"version": "0.1602.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@angular-devkit/architect/-/architect-0.1602.14.tgz",
|
||||||
|
"integrity": "sha512-eSdONEV5dbtLNiOMBy9Ue9DdJ1ct6dH9RdZfYiedq6VZn0lejePAjY36MYVXgq2jTE+v/uIiaNy7caea5pt55A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"@angular-devkit/core": "16.2.14",
|
||||||
|
"rxjs": "7.8.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@angular-devkit/core": {
|
||||||
|
"version": "16.2.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz",
|
||||||
|
"integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ajv": "8.12.0",
|
||||||
|
"ajv-formats": "2.1.1",
|
||||||
|
"jsonc-parser": "3.2.0",
|
||||||
|
"picomatch": "2.3.1",
|
||||||
|
"rxjs": "7.8.1",
|
||||||
|
"source-map": "0.7.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ajv": {
|
||||||
|
"version": "8.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
|
||||||
|
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fast-deep-equal": "^3.1.1",
|
||||||
|
"json-schema-traverse": "^1.0.0",
|
||||||
|
"require-from-string": "^2.0.2",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"json-schema-traverse": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "7.5.4",
|
"version": "7.5.4",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz",
|
||||||
|
|
@ -16747,14 +16985,48 @@
|
||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"@schematics/angular": {
|
"@schematics/angular": {
|
||||||
"version": "16.2.1",
|
"version": "16.2.14",
|
||||||
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/@schematics/angular/-/angular-16.2.14.tgz",
|
||||||
"integrity": "sha512-e3ckgvSv+OA+4xUBpOqVOvNM8FqY/yXaWqs/Ob0uQ/zPL1iVa/MCAoB25KqYQPnq21hEwE4zqIIQFKasKBIqMA==",
|
"integrity": "sha512-YqIv727l9Qze8/OL6H9mBHc2jVXzAGRNBYnxYWqWhLbfvuVbbldo6NNIIjgv6lrl2LJSdPAAMNOD5m/f6210ug==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@angular-devkit/core": "16.2.1",
|
"@angular-devkit/core": "16.2.14",
|
||||||
"@angular-devkit/schematics": "16.2.1",
|
"@angular-devkit/schematics": "16.2.14",
|
||||||
"jsonc-parser": "3.2.0"
|
"jsonc-parser": "3.2.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@angular-devkit/core": {
|
||||||
|
"version": "16.2.14",
|
||||||
|
"resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-16.2.14.tgz",
|
||||||
|
"integrity": "sha512-Ui14/d2+p7lnmXlK/AX2ieQEGInBV75lonNtPQgwrYgskF8ufCuN0DyVZQUy9fJDkC+xQxbJyYrby/BS0R0e7w==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"ajv": "8.12.0",
|
||||||
|
"ajv-formats": "2.1.1",
|
||||||
|
"jsonc-parser": "3.2.0",
|
||||||
|
"picomatch": "2.3.1",
|
||||||
|
"rxjs": "7.8.1",
|
||||||
|
"source-map": "0.7.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ajv": {
|
||||||
|
"version": "8.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
|
||||||
|
"integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"fast-deep-equal": "^3.1.1",
|
||||||
|
"json-schema-traverse": "^1.0.0",
|
||||||
|
"require-from-string": "^2.0.2",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"json-schema-traverse": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
|
||||||
|
"dev": true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@sigstore/bundle": {
|
"@sigstore/bundle": {
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@
|
||||||
"@angular-eslint/eslint-plugin-template": "16.1.1",
|
"@angular-eslint/eslint-plugin-template": "16.1.1",
|
||||||
"@angular-eslint/schematics": "16.1.1",
|
"@angular-eslint/schematics": "16.1.1",
|
||||||
"@angular-eslint/template-parser": "16.1.1",
|
"@angular-eslint/template-parser": "16.1.1",
|
||||||
"@angular/cli": "^16.2.1",
|
"@angular/cli": "^16.2.14",
|
||||||
"@angular/compiler-cli": "^16.2.3",
|
"@angular/compiler-cli": "^16.2.3",
|
||||||
"@angular/language-service": "^16.2.3",
|
"@angular/language-service": "^16.2.3",
|
||||||
"@types/file-saver": "^2.0.5",
|
"@types/file-saver": "^2.0.5",
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ using RdtClient.Data.Enums;
|
||||||
using RdtClient.Data.Models.TorrentClient;
|
using RdtClient.Data.Models.TorrentClient;
|
||||||
using RdtClient.Service.Helpers;
|
using RdtClient.Service.Helpers;
|
||||||
using Microsoft.AspNetCore.Mvc.RazorPages;
|
using Microsoft.AspNetCore.Mvc.RazorPages;
|
||||||
|
using System.Diagnostics.Eventing.Reader;
|
||||||
|
|
||||||
namespace RdtClient.Service.Services.TorrentClients;
|
namespace RdtClient.Service.Services.TorrentClients;
|
||||||
|
|
||||||
|
|
@ -72,7 +73,7 @@ public class TorBoxTorrentClient(ILogger<TorBoxTorrentClient> logger, IHttpClien
|
||||||
Hash = torrent.Hash,
|
Hash = torrent.Hash,
|
||||||
Bytes = torrent.Size,
|
Bytes = torrent.Size,
|
||||||
OriginalBytes = torrent.Size,
|
OriginalBytes = torrent.Size,
|
||||||
Host = null,
|
Host = torrent.DownloadPresent.ToString(),
|
||||||
Split = 0,
|
Split = 0,
|
||||||
Progress = (Int64)((torrent.Progress) * 100.0),
|
Progress = (Int64)((torrent.Progress) * 100.0),
|
||||||
Status = torrent.DownloadState,
|
Status = torrent.DownloadState,
|
||||||
|
|
@ -93,9 +94,22 @@ public class TorBoxTorrentClient(ILogger<TorBoxTorrentClient> logger, IHttpClien
|
||||||
|
|
||||||
public async Task<IList<TorrentClientTorrent>> GetTorrents()
|
public async Task<IList<TorrentClientTorrent>> GetTorrents()
|
||||||
{
|
{
|
||||||
var results = await GetClient().Torrents.GetAsync(true);
|
var torrents = new List<Torrent>();
|
||||||
|
|
||||||
return results!.Select(Map).ToList();
|
var currentTorrents = await GetClient().Torrents.GetCurrentAsync(true);
|
||||||
|
if (currentTorrents != null)
|
||||||
|
{
|
||||||
|
torrents.AddRange(currentTorrents);
|
||||||
|
}
|
||||||
|
|
||||||
|
var queuedTorrents = await GetClient().Torrents.GetQueuedAsync(true);
|
||||||
|
if (queuedTorrents != null)
|
||||||
|
{
|
||||||
|
torrents.AddRange(queuedTorrents);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return torrents!.Select(Map).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<TorrentClientUser> GetUser()
|
public async Task<TorrentClientUser> GetUser()
|
||||||
|
|
@ -105,7 +119,7 @@ public class TorBoxTorrentClient(ILogger<TorBoxTorrentClient> logger, IHttpClien
|
||||||
return new()
|
return new()
|
||||||
{
|
{
|
||||||
Username = user.Data!.Email,
|
Username = user.Data!.Email,
|
||||||
Expiration = user.Data!.Plan != 0 ? user.Data!.PremiumExpiresAt.Value : null
|
Expiration = user.Data!.Plan != 0 ? user.Data!.PremiumExpiresAt!.Value : null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,133 +137,20 @@ public class TorBoxTorrentClient(ILogger<TorBoxTorrentClient> logger, IHttpClien
|
||||||
return result.Data?.Torrent_ID.ToString()!;
|
return result.Data?.Torrent_ID.ToString()!;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<IList<TorrentClientAvailableFile>> GetAvailableFiles(String hash)
|
public Task<IList<TorrentClientAvailableFile>> GetAvailableFiles(String hash)
|
||||||
{
|
{
|
||||||
var result = await GetClient().Torrents.GetAvailableFiles(hash);
|
var result = new List<TorrentClientAvailableFile>();
|
||||||
|
return Task.FromResult<IList<TorrentClientAvailableFile>>(result);
|
||||||
var files = result.SelectMany(m => m.Value).SelectMany(m => m.Value).SelectMany(m => m.Values);
|
|
||||||
|
|
||||||
var groups = files.Where(m => m.Filename != null).GroupBy(m => $"{m.Filename}-{m.Filesize}");
|
|
||||||
|
|
||||||
var torrentClientAvailableFiles = groups.Select(m => new TorrentClientAvailableFile
|
|
||||||
{
|
|
||||||
Filename = m.First().Filename!,
|
|
||||||
Filesize = m.First().Filesize
|
|
||||||
}).ToList();
|
|
||||||
|
|
||||||
return torrentClientAvailableFiles;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task SelectFiles(Data.Models.Data.Torrent torrent)
|
public Task SelectFiles(Data.Models.Data.Torrent torrent)
|
||||||
{
|
{
|
||||||
var files = torrent.Files;
|
return Task.CompletedTask;
|
||||||
|
|
||||||
Log("Seleting files", torrent);
|
|
||||||
|
|
||||||
if (torrent.DownloadAction == TorrentDownloadAction.DownloadAvailableFiles)
|
|
||||||
{
|
|
||||||
Log($"Determining which files are already available on RealDebrid", torrent);
|
|
||||||
|
|
||||||
var availableFiles = await GetAvailableFiles(torrent.Hash);
|
|
||||||
|
|
||||||
Log($"Found {files.Count}/{torrent.Files.Count} available files on RealDebrid", torrent);
|
|
||||||
|
|
||||||
files = torrent.Files.Where(m => availableFiles.Any(f => m.Path.EndsWith(f.Filename))).ToList();
|
|
||||||
}
|
|
||||||
else if (torrent.DownloadAction == TorrentDownloadAction.DownloadAll)
|
|
||||||
{
|
|
||||||
Log("Selecting all files", torrent);
|
|
||||||
files = [.. torrent.Files];
|
|
||||||
}
|
|
||||||
else if (torrent.DownloadAction == TorrentDownloadAction.DownloadManual)
|
|
||||||
{
|
|
||||||
Log("Selecting manual selected files", torrent);
|
|
||||||
files = torrent.Files.Where(m => torrent.ManualFiles.Any(f => m.Path.EndsWith(f))).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
Log($"Selecting {files.Count}/{torrent.Files.Count} files", torrent);
|
|
||||||
|
|
||||||
if (torrent.DownloadAction != TorrentDownloadAction.DownloadManual && torrent.DownloadMinSize > 0)
|
|
||||||
{
|
|
||||||
var minFileSize = torrent.DownloadMinSize * 1024 * 1024;
|
|
||||||
|
|
||||||
Log($"Determining which files are over {minFileSize} bytes", torrent);
|
|
||||||
|
|
||||||
files = files.Where(m => m.Bytes > minFileSize)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
Log($"Found {files.Count} files that match the minimum file size criterea", torrent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!String.IsNullOrWhiteSpace(torrent.IncludeRegex))
|
|
||||||
{
|
|
||||||
Log($"Using regular expression {torrent.IncludeRegex} to include only files matching this regex", torrent);
|
|
||||||
|
|
||||||
var newFiles = new List<TorrentClientFile>();
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
|
||||||
if (Regex.IsMatch(file.Path, torrent.IncludeRegex))
|
|
||||||
{
|
|
||||||
Log($"* Including {file.Path}", torrent);
|
|
||||||
newFiles.Add(file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log($"* Excluding {file.Path}", torrent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
files = newFiles;
|
|
||||||
|
|
||||||
Log($"Found {files.Count} files that match the regex", torrent);
|
|
||||||
}
|
|
||||||
else if (!String.IsNullOrWhiteSpace(torrent.ExcludeRegex))
|
|
||||||
{
|
|
||||||
Log($"Using regular expression {torrent.IncludeRegex} to ignore files matching this regex", torrent);
|
|
||||||
|
|
||||||
var newFiles = new List<TorrentClientFile>();
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
|
||||||
if (!Regex.IsMatch(file.Path, torrent.ExcludeRegex))
|
|
||||||
{
|
|
||||||
Log($"* Including {file.Path}", torrent);
|
|
||||||
newFiles.Add(file);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log($"* Excluding {file.Path}", torrent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
files = newFiles;
|
|
||||||
|
|
||||||
Log($"Found {files.Count} files that match the regex", torrent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (files.Count == 0)
|
|
||||||
{
|
|
||||||
Log($"Filtered all files out! Downloading ALL files instead!", torrent);
|
|
||||||
|
|
||||||
files = torrent.Files;
|
|
||||||
}
|
|
||||||
|
|
||||||
var fileIds = files.Select(m => m.Id.ToString()).ToArray();
|
|
||||||
|
|
||||||
Log($"Selecting files:");
|
|
||||||
|
|
||||||
foreach (var file in files)
|
|
||||||
{
|
|
||||||
Log($"{file.Id}: {file.Path} ({file.Bytes}b)");
|
|
||||||
}
|
|
||||||
|
|
||||||
Log("", torrent);
|
|
||||||
|
|
||||||
await GetClient().Torrents.SelectFilesAsync(torrent.RdId!, [.. fileIds]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Delete(String torrentId)
|
public async Task Delete(String torrentId)
|
||||||
{
|
{
|
||||||
await GetClient().Torrents.DeleteAsync(torrentId);
|
await GetClient().Torrents.ControlAsync(Convert.ToInt32(torrentId), "delete");
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<String> Unrestrict(String link)
|
public async Task<String> Unrestrict(String link)
|
||||||
|
|
@ -273,7 +174,7 @@ public class TorBoxTorrentClient(ILogger<TorBoxTorrentClient> logger, IHttpClien
|
||||||
return torrent;
|
return torrent;
|
||||||
}
|
}
|
||||||
|
|
||||||
var rdTorrent = await GetInfo(torrent.RdId) ?? throw new($"Resource not found");
|
var rdTorrent = await GetInfo(torrent.Hash) ?? throw new($"Resource not found");
|
||||||
|
|
||||||
if (!String.IsNullOrWhiteSpace(rdTorrent.Filename))
|
if (!String.IsNullOrWhiteSpace(rdTorrent.Filename))
|
||||||
{
|
{
|
||||||
|
|
@ -308,21 +209,29 @@ public class TorBoxTorrentClient(ILogger<TorBoxTorrentClient> logger, IHttpClien
|
||||||
torrent.RdSeeders = rdTorrent.Seeders;
|
torrent.RdSeeders = rdTorrent.Seeders;
|
||||||
torrent.RdStatusRaw = rdTorrent.Status;
|
torrent.RdStatusRaw = rdTorrent.Status;
|
||||||
|
|
||||||
torrent.RdStatus = rdTorrent.Status switch
|
if (rdTorrent.Host == "true")
|
||||||
{
|
{
|
||||||
"magnet_error" => TorrentStatus.Error,
|
torrent.RdStatus = TorrentStatus.Finished;
|
||||||
"magnet_conversion" => TorrentStatus.Processing,
|
}
|
||||||
"waiting_files_selection" => TorrentStatus.WaitingForFileSelection,
|
else
|
||||||
"queued" => TorrentStatus.Downloading,
|
{
|
||||||
"downloading" => TorrentStatus.Downloading,
|
torrent.RdStatus = rdTorrent.Status switch
|
||||||
"downloaded" => TorrentStatus.Finished,
|
{
|
||||||
"error" => TorrentStatus.Error,
|
"queued" => TorrentStatus.Processing,
|
||||||
"virus" => TorrentStatus.Error,
|
"metaDL" => TorrentStatus.Processing,
|
||||||
"compressing" => TorrentStatus.Downloading,
|
"checkingResumeData" => TorrentStatus.Processing,
|
||||||
"uploading" => TorrentStatus.Uploading,
|
"paused" => TorrentStatus.Downloading,
|
||||||
"dead" => TorrentStatus.Error,
|
"downloading" => TorrentStatus.Downloading,
|
||||||
_ => TorrentStatus.Error
|
"completed" => TorrentStatus.Downloading,
|
||||||
};
|
"uploading" => TorrentStatus.Downloading,
|
||||||
|
"uploading (no peers)" => TorrentStatus.Downloading,
|
||||||
|
"stalled" => TorrentStatus.Downloading,
|
||||||
|
"stalled (no seeds)" => TorrentStatus.Downloading,
|
||||||
|
"cached" => TorrentStatus.Finished,
|
||||||
|
_ => TorrentStatus.Error
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|
@ -410,11 +319,11 @@ public class TorBoxTorrentClient(ILogger<TorBoxTorrentClient> logger, IHttpClien
|
||||||
return dateTimeOffset?.Subtract(_offset.Value).ToOffset(_offset.Value);
|
return dateTimeOffset?.Subtract(_offset.Value).ToOffset(_offset.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<TorrentClientTorrent> GetInfo(String torrentId)
|
private async Task<TorrentClientTorrent> GetInfo(String torrentHash)
|
||||||
{
|
{
|
||||||
var result = await GetClient().Torrents.GetInfoAsync(torrentId);
|
var result = await GetClient().Torrents.GetInfoAsync(torrentHash);
|
||||||
|
|
||||||
return Map(result);
|
return Map(result!);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void Log(String message, Data.Models.Data.Torrent? torrent = null)
|
private void Log(String message, Data.Models.Data.Torrent? torrent = null)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue