diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..0967ef4 --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1 @@ +{} diff --git a/.prettierts.json b/.prettierts.json deleted file mode 100644 index 9e26dfe..0000000 --- a/.prettierts.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/lib/peertubeRequester.ts b/lib/peertubeRequester.ts new file mode 100644 index 0000000..9e58271 --- /dev/null +++ b/lib/peertubeRequester.ts @@ -0,0 +1,109 @@ +// Api request lib +import fetch, { FetchError, Headers } from "node-fetch"; +import { URL, URLSearchParams } from "url"; + +namespace PeerTubeRequester { + export type Config = { + domain_name: string | URL; + username: string; + password: string; + }; +} + +type UploadInstruction = { + [key: string]: string; + channelId: string; + targetUrl: string; +}; + +class PeerTubeRequester { + readonly domain_name: URL; + readonly username: string; + readonly password: string; + + constructor(readonly config: PeerTubeRequester.Config) { + this.domain_name = new URL("/", config.domain_name); + this.username = config.username; + this.password = config.password; + } + + private async requestAuthToken(): Promise { + let response = await fetch( + new URL(`/api/v1/oauth-clients/local`, this.domain_name) + ); + if (!response.ok) { + throw new Error(response.statusText); // CRASH + } + const { client_id, client_secret } = await response.json(); + + const client_info: { [key: string]: string } = { + client_id, + client_secret, + grant_type: "password", + response_type: "code", + username: this.username, + password: this.password, + }; + + let myParams = new URLSearchParams(); + for (const key in client_info) myParams.append(key, client_info[key]); + + response = await fetch(new URL(`/api/v1/users/token`, this.domain_name), { + method: "post", + body: myParams, + }); + if (!response.ok) { + throw new Error(response.statusText); // CRASH + } + const { access_token: accessToken } = await response.json(); + return accessToken; + } + + async uploadFromUrl(message: UploadInstruction): Promise { + const accessToken = await this.requestAuthToken(); + const myUploadForm = new URLSearchParams(); + const myHeader = new Headers(); + myHeader.append("Authorization", `Bearer ${accessToken}`); + for (const key in message) myUploadForm.append(key, message[key]); + + const response = await fetch( + new URL(`/api/v1/videos/imports`, this.domain_name), + { + method: "post", + headers: myHeader, + body: myUploadForm, + } + ); + + if (!response.ok) { + switch (response.status) { + case 400: + throw new Error( + `Bad or malformed request. Probably because your target URL (from Youtube?) was not accepted by the API.\ + The target URL you attempted to pass: ${message.targetUrl}. + Response from the server: ${response.statusText}` + ); + break; + case 403: + throw new Error(response.statusText); + break; + case 409: + throw new Error( + `Oops, your instance did not allowed the HTTPS import.\ + Contact your administrator. + ${response.statusText}` + ); + break; + default: + throw new Error( + `Oh, you encountered an undocumented issues.\ + Please create an issue to the plugin project. + ERROR: ${response.statusText}` + ); + break; + } + } + } +} + +export { PeerTubeRequester }; diff --git a/package-lock.json b/package-lock.json index 2281566..26367bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,13 +1,16 @@ { "name": "peertube-plugin-auto-import-ytb", - "version": "0.0.2", + "version": "0.0.1", "lockfileVersion": 2, "requires": true, "packages": { "": { - "version": "0.0.2", + "version": "0.0.1", "dependencies": { - "listener-rss-agregator": "0.0.2" + "@types/node-fetch": "^2.5.11", + "form-data": "^4.0.0", + "listener-rss-aggregator": "^0.0.5", + "node-fetch": "^2.6.1" }, "devDependencies": { "ts-node": "^10.0.0", @@ -69,9 +72,31 @@ "dev": true }, "node_modules/@types/node": { - "version": "15.12.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.5.tgz", - "integrity": "sha512-se3yX7UHv5Bscf8f1ERKvQOD6sTyycH3hdaoozvaLxgUiY5lIGEeH37AD0G0Qi9kPqihPn0HOfd2yaIEN9VwEg==" + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.1.tgz", + "integrity": "sha512-N87VuQi7HEeRJkhzovao/JviiqKjDKMVKxKMfUvSKw+MbkbW8R0nA3fi/MQhhlxV2fQ+2ReM+/Nt4efdrJx3zA==" + }, + "node_modules/@types/node-fetch": { + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.11.tgz", + "integrity": "sha512-2upCKaqVZETDRb8A2VTaRymqFBEgH8u6yr96b/u3+1uQEPDRo3mJLEiPk7vdXBHRtjwkjqzFYMJXrt0Z9QsYjQ==", + "dependencies": { + "@types/node": "*", + "form-data": "^3.0.0" + } + }, + "node_modules/@types/node-fetch/node_modules/form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } }, "node_modules/@types/sqlite3": { "version": "3.1.7", @@ -119,6 +144,11 @@ "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz", "integrity": "sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0=" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -152,6 +182,17 @@ "node": ">=0.10.0" } }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -189,6 +230,14 @@ "node": ">=4.0.0" } }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -222,6 +271,19 @@ "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/fs-minipass": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", @@ -329,20 +391,20 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "node_modules/listener-rss": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/listener-rss/-/listener-rss-0.0.1.tgz", - "integrity": "sha512-ljH6FD4NMypkrZ9ZIMdW2YdAlm/Jer++zPI+1HTWK7BbhPJmUF3sSymqUqAjBcfH3xjt+fpYPqYgNYNM1fEYpA==", + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/listener-rss/-/listener-rss-0.0.3.tgz", + "integrity": "sha512-rccetOTwyyww/KDuaMX0EMjaGi+Jx+bojp18Ucxra6OeCfz2hC9FEasVNeENR096+ndOCS/rkKTJl+RD9rlAAQ==", "dependencies": { - "rss-parser": "3.11.0" + "rss-parser": "^3.11.0" } }, - "node_modules/listener-rss-agregator": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/listener-rss-agregator/-/listener-rss-agregator-0.0.2.tgz", - "integrity": "sha512-ATj4esXtHLThe1/wkJ/ukA9+pC9FwBCNZCbVv7Ywr1eIbxBR+AHR5090lzCQt3WJsBblpTTZMni+vHxmGjRR7Q==", + "node_modules/listener-rss-aggregator": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/listener-rss-aggregator/-/listener-rss-aggregator-0.0.5.tgz", + "integrity": "sha512-0QE7kkzurjsWr4gNAJ4X+C7UFSyaVuYq2mKYXZ3shvyj81kULpBgFZSg/70MZkUoqixgWQ5P8oxyztRDOP78tw==", "dependencies": { "@databases/sqlite": "^3.0.0", - "listener-rss": "^0.0.1" + "listener-rss": "^0.0.3" } }, "node_modules/make-error": { @@ -351,6 +413,25 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "node_modules/mime-db": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "dependencies": { + "mime-db": "1.48.0" + }, + "engines": { + "node": ">= 0.6" + } + }, "node_modules/minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -406,9 +487,9 @@ "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" }, "node_modules/needle": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", - "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.8.0.tgz", + "integrity": "sha512-ZTq6WYkN/3782H1393me3utVYdq2XyqNUFBsprEE3VMAT0+hP/cItpnITpqsY6ep2yeFE4Tqtqwc74VqUlUYtw==", "dependencies": { "debug": "^3.2.6", "iconv-lite": "^0.4.4", @@ -421,6 +502,14 @@ "node": ">= 4.4.x" } }, + "node_modules/node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==", + "engines": { + "node": "4.x || >=6.0.0" + } + }, "node_modules/node-pre-gyp": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", @@ -598,9 +687,9 @@ } }, "node_modules/rss-parser": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/rss-parser/-/rss-parser-3.11.0.tgz", - "integrity": "sha512-oTLoYW+bNqNwkz8OpGinBU9s3As0sdczQjETIZFgyAdi7AopyhoVFGPIyFMYXXEY8hayKzD5CH+4CtmiPtJ89g==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/rss-parser/-/rss-parser-3.12.0.tgz", + "integrity": "sha512-aqD3E8iavcCdkhVxNDIdg1nkBI17jgqF+9OqPS1orwNaOgySdpvq6B+DoONLhzjzwV8mWg37sb60e4bmLK117A==", "dependencies": { "entities": "^2.0.3", "xml2js": "^0.4.19" @@ -709,9 +798,9 @@ } }, "node_modules/tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "version": "4.4.14", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.14.tgz", + "integrity": "sha512-ouN3XcSWYOAHmXZ+P4NEFJvqXL50To9OZBSQNNP30vBUFJFZZ0PLX15fnwupv6azfxMUfUDUr2fhYw4zGAEPcg==", "dependencies": { "chownr": "^1.1.1", "fs-minipass": "^1.2.5", @@ -734,9 +823,9 @@ } }, "node_modules/ts-node": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz", - "integrity": "sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.1.0.tgz", + "integrity": "sha512-6szn3+J9WyG2hE+5W8e0ruZrzyk1uFLYye6IGMBadnOzDh8aP7t8CbFpsfCiEx2+wMixAhjFt7lOZC4+l+WbEA==", "dev": true, "dependencies": { "@tsconfig/node10": "^1.0.7", @@ -761,8 +850,8 @@ "node": ">=12.0.0" }, "peerDependencies": { - "@swc/core": ">=1.2.45", - "@swc/wasm": ">=1.2.45", + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" }, @@ -776,9 +865,9 @@ } }, "node_modules/typescript": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz", - "integrity": "sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", "dev": true, "bin": { "tsc": "bin/tsc", @@ -897,9 +986,30 @@ "dev": true }, "@types/node": { - "version": "15.12.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.12.5.tgz", - "integrity": "sha512-se3yX7UHv5Bscf8f1ERKvQOD6sTyycH3hdaoozvaLxgUiY5lIGEeH37AD0G0Qi9kPqihPn0HOfd2yaIEN9VwEg==" + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.3.1.tgz", + "integrity": "sha512-N87VuQi7HEeRJkhzovao/JviiqKjDKMVKxKMfUvSKw+MbkbW8R0nA3fi/MQhhlxV2fQ+2ReM+/Nt4efdrJx3zA==" + }, + "@types/node-fetch": { + "version": "2.5.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.5.11.tgz", + "integrity": "sha512-2upCKaqVZETDRb8A2VTaRymqFBEgH8u6yr96b/u3+1uQEPDRo3mJLEiPk7vdXBHRtjwkjqzFYMJXrt0Z9QsYjQ==", + "requires": { + "@types/node": "*", + "form-data": "^3.0.0" + }, + "dependencies": { + "form-data": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", + "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } }, "@types/sqlite3": { "version": "3.1.7", @@ -944,6 +1054,11 @@ "resolved": "https://registry.npmjs.org/asap/-/asap-1.0.0.tgz", "integrity": "sha1-sqRdpf36ILBJb8N2jMJ8EvqRan0=" }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -974,6 +1089,14 @@ "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1008,6 +1131,11 @@ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -1029,6 +1157,16 @@ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==" }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "fs-minipass": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.7.tgz", @@ -1124,20 +1262,20 @@ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" }, "listener-rss": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/listener-rss/-/listener-rss-0.0.1.tgz", - "integrity": "sha512-ljH6FD4NMypkrZ9ZIMdW2YdAlm/Jer++zPI+1HTWK7BbhPJmUF3sSymqUqAjBcfH3xjt+fpYPqYgNYNM1fEYpA==", + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/listener-rss/-/listener-rss-0.0.3.tgz", + "integrity": "sha512-rccetOTwyyww/KDuaMX0EMjaGi+Jx+bojp18Ucxra6OeCfz2hC9FEasVNeENR096+ndOCS/rkKTJl+RD9rlAAQ==", "requires": { - "rss-parser": "3.11.0" + "rss-parser": "^3.11.0" } }, - "listener-rss-agregator": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/listener-rss-agregator/-/listener-rss-agregator-0.0.2.tgz", - "integrity": "sha512-ATj4esXtHLThe1/wkJ/ukA9+pC9FwBCNZCbVv7Ywr1eIbxBR+AHR5090lzCQt3WJsBblpTTZMni+vHxmGjRR7Q==", + "listener-rss-aggregator": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/listener-rss-aggregator/-/listener-rss-aggregator-0.0.5.tgz", + "integrity": "sha512-0QE7kkzurjsWr4gNAJ4X+C7UFSyaVuYq2mKYXZ3shvyj81kULpBgFZSg/70MZkUoqixgWQ5P8oxyztRDOP78tw==", "requires": { "@databases/sqlite": "^3.0.0", - "listener-rss": "^0.0.1" + "listener-rss": "^0.0.3" } }, "make-error": { @@ -1146,6 +1284,19 @@ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", "dev": true }, + "mime-db": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.48.0.tgz", + "integrity": "sha512-FM3QwxV+TnZYQ2aRqhlKBMHxk10lTbMt3bBkMAp54ddrNeVSfcQYOOKuGuy3Ddrm38I04If834fOUSq1yzslJQ==" + }, + "mime-types": { + "version": "2.1.31", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.31.tgz", + "integrity": "sha512-XGZnNzm3QvgKxa8dpzyhFTHmpP3l5YNusmne07VUOXxou9CqUqYa/HBy124RqtVh/O2pECas/MOcsDgpilPOPg==", + "requires": { + "mime-db": "1.48.0" + } + }, "minimatch": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", @@ -1195,15 +1346,20 @@ "integrity": "sha512-M2ufzIiINKCuDfBSAUr1vWQ+vuVcA9kqx8JJUsbQi6yf1uGRyb7HfpdfUr5qLXf3B/t8dPvcjhKMmlfnP47EzQ==" }, "needle": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/needle/-/needle-2.6.0.tgz", - "integrity": "sha512-KKYdza4heMsEfSWD7VPUIz3zX2XDwOyX2d+geb4vrERZMT5RMU6ujjaD+I5Yr54uZxQ2w6XRTAhHBbSCyovZBg==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.8.0.tgz", + "integrity": "sha512-ZTq6WYkN/3782H1393me3utVYdq2XyqNUFBsprEE3VMAT0+hP/cItpnITpqsY6ep2yeFE4Tqtqwc74VqUlUYtw==", "requires": { "debug": "^3.2.6", "iconv-lite": "^0.4.4", "sax": "^1.2.4" } }, + "node-fetch": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" + }, "node-pre-gyp": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.11.0.tgz", @@ -1353,9 +1509,9 @@ } }, "rss-parser": { - "version": "3.11.0", - "resolved": "https://registry.npmjs.org/rss-parser/-/rss-parser-3.11.0.tgz", - "integrity": "sha512-oTLoYW+bNqNwkz8OpGinBU9s3As0sdczQjETIZFgyAdi7AopyhoVFGPIyFMYXXEY8hayKzD5CH+4CtmiPtJ89g==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/rss-parser/-/rss-parser-3.12.0.tgz", + "integrity": "sha512-aqD3E8iavcCdkhVxNDIdg1nkBI17jgqF+9OqPS1orwNaOgySdpvq6B+DoONLhzjzwV8mWg37sb60e4bmLK117A==", "requires": { "entities": "^2.0.3", "xml2js": "^0.4.19" @@ -1448,9 +1604,9 @@ "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" }, "tar": { - "version": "4.4.13", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", - "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", + "version": "4.4.14", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.14.tgz", + "integrity": "sha512-ouN3XcSWYOAHmXZ+P4NEFJvqXL50To9OZBSQNNP30vBUFJFZZ0PLX15fnwupv6azfxMUfUDUr2fhYw4zGAEPcg==", "requires": { "chownr": "^1.1.1", "fs-minipass": "^1.2.5", @@ -1470,9 +1626,9 @@ } }, "ts-node": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz", - "integrity": "sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==", + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.1.0.tgz", + "integrity": "sha512-6szn3+J9WyG2hE+5W8e0ruZrzyk1uFLYye6IGMBadnOzDh8aP7t8CbFpsfCiEx2+wMixAhjFt7lOZC4+l+WbEA==", "dev": true, "requires": { "@tsconfig/node10": "^1.0.7", @@ -1488,9 +1644,9 @@ } }, "typescript": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.4.tgz", - "integrity": "sha512-uauPG7XZn9F/mo+7MrsRjyvbxFpzemRjKEZXS4AK83oP2KKOJPvb+9cO/gmnv8arWZvhnjVOXz7B49m1l0e9Ew==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.5.tgz", + "integrity": "sha512-DqQgihaQ9cUrskJo9kIyW/+g0Vxsk8cDtZ52a3NGh0YNTfpUSArXSohyUGnvbPazEPLu398C0UxmKSOrPumUzA==", "dev": true }, "util-deprecate": { diff --git a/package.json b/package.json index 8fc28ba..65eacce 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "peertube-plugin-auto-import-ytb", "description": "PeerTube plugin quickstart", - "version": "0.0.2", + "version": "0.0.1", "author": "AmauryJOLY", "bugs": "https://framagit.org/framasoft/peertube/peertube-plugin-quickstart/issues", "clientScripts": [], @@ -18,19 +18,22 @@ "peertube", "plugin" ], - "library": "./dist/main.js", + "library": "./dist/src/main.js", "files": [ "dist/", "README.md" ], "scripts": { - "buildAndDeploy": "npm run build && npm run deploy", + "predeploy": "npm run build", "deploy": "bash ./scripts/deploy.sh", "build": "tsc" }, "staticDirs": {}, "translations": {}, "dependencies": { - "listener-rss-agregator": "0.0.2" + "@types/node-fetch": "^2.5.11", + "form-data": "^4.0.0", + "listener-rss-aggregator": "^0.0.5", + "node-fetch": "^2.6.1" } } diff --git a/scripts/deploy.sh b/scripts/deploy.sh index 671644d..340dcaf 100644 --- a/scripts/deploy.sh +++ b/scripts/deploy.sh @@ -1,12 +1,13 @@ +#/bin/bash tmp_dir=$(mktemp -d)/peertube-plugin-auto-import-ytb work_dir=$(pwd) -# echo $work_dir +# echo "${work_dir}" -mkdir $tmp_dir +mkdir "${tmp_dir}" # echo "directory created" cp "${work_dir}/dist" "${work_dir}/package.json" "${work_dir}/LICENSE" $tmp_dir -r # echo "rsync --exclude-from=$work_dir.rsyncignore $work_dir $tmp_dir" # echo "rsync done" -cd "../PeerTube" +cd "../PeerTube-cli" node "./dist/server/tools/peertube.js" plugins install --path "${tmp_dir}" # echo $tmp_dir \ No newline at end of file diff --git a/src/main.ts b/src/main.ts index cb52c3f..ab0cf4d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,63 +1,111 @@ -import { ManageListener } from 'listener-rss-agregator'; +import { ListenerRssAggregator } from "listener-rss-aggregator"; +import { ListenerRss } from "listener-rss"; +import { PeerTubeRequester } from "../lib/peertubeRequester"; -let myManager : ManageListener; -let bindistenerChannelId: {[key: string] : string} = {}; +type ListenerData = ListenerRss.Config & { + address: string; + channelId: string; +}; -import * as path from 'path'; +let myManager: ListenerRssAggregator; +let listenersDataBinding = new Map(); +let logger: any; +let peertube: PeerTubeRequester; + +import * as path from "path"; +import fs from "fs"; async function register({ - registerSetting, - settingsManager, + registerSetting, + settingsManager, peertubeHelpers, }: any) { - registerSetting({ - name: 'ytb-urls', - label: 'liste des urls youtube a auto-importer', - type: 'input-textarea' - }) - const basePath = peertubeHelpers.plugin.getDataDirectoryPath(); - myManager = new ManageListener(path.join(basePath, '/data/storage.bd')); + logger = peertubeHelpers.logger; - const inputs = await settingsManager.getSetting('ytb-urls'); + registerSetting({ + name: "ytb-urls", + label: "URL list of Youtube channel to synchronize", + type: "input-textarea", + }); - addListeners(inputs); + logger.debug("setting register"); + fs.appendFileSync(path.join(basePath, "/storage.bd"), ""); - settingsManager.onSettingsChange((settings: any) => { - myManager.stopAll(); - myManager.save(); + const configAggregator = await ListenerRssAggregator.instantiateAggregator( + path.join(basePath, "/storage.bd") + ); + myManager = new ListenerRssAggregator(configAggregator); - addListeners(settings['ytb-urls']); - }) + peertube = new PeerTubeRequester({ + domain_name: "http://localhost:9000", + username: "root", + password: "test", + }); - myManager.on('update', (entries: any) => { - // for (const item in entries.items) - // console.info(item.) - - }) - + logger.debug("Aggregator created"); + + const inputs = await settingsManager.getSetting("ytb-urls"); + if (inputs) await addListeners(inputs); + + logger.debug("Config loaded"); + + settingsManager.onSettingsChange(async (settings: any) => { + await addListeners(settings["ytb-urls"]); + }); + + myManager.on("newEntries", async (entries: any) => { + const datas = listenersDataBinding.get(entries.addressListener); + if (!datas) return; + + logger.debug( + "New entries detected from channel #%i: %s", + datas.channelId, + JSON.stringify(entries) + ); + for (const item of entries.items) + await peertube.uploadFromUrl({ + channelId: datas.channelId, + targetUrl: item.link, + }); + }); } -function addListeners(listenerInput: any) { - for (const line in listenerInput.split('\n')) - if (!myManager.listenerArray.map((it: any) => it.address).includes(line)) // si ligne non présente - { - let splitted = line.split(':'); - bindistenerChannelId[splitted[1]] = splitted[0]; - myManager.registerListener({ address: splitted[0] }); - } +async function addListeners(listenerInput: string) { + let listeners: ListenerData[]; + try { + listeners = JSON.parse(listenerInput); + } catch { + logger.error("Malformed URL"); + return; + } + let newListeners = listeners.filter( + (item) => !listenersDataBinding.has(item.address) + ); + let removedUrls = Array.from(listenersDataBinding.keys()).filter( + (url) => !listeners.some((listener) => listener.address === url) + ); + + for (const newItem of newListeners) { + listenersDataBinding.set(newItem.address, newItem); + } + for (const removedUrl of removedUrls) { + listenersDataBinding.delete(removedUrl); + } + + myManager.stopAll(); + await myManager.saveOverride(listeners); + + if (logger) logger.warn("Configuration changed: " + listenerInput); - myManager.save(); myManager.startAll(); } async function unregister() { myManager.stopAll(); - myManager.save(); - return } module.exports = { register, - unregister -} + unregister, +}; diff --git a/tsconfig.json b/tsconfig.json index 0db43d2..34718e6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,8 +4,8 @@ /* Basic Options */ // "incremental": true, /* Enable incremental compilation */ - "target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */ - "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */ + "target": "es5" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', 'ES2021', or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, // "lib": [], /* Specify library files to be included in the compilation. */ // "allowJs": true, /* Allow javascript files to be compiled. */ // "checkJs": true, /* Report errors in .js files. */ @@ -14,8 +14,8 @@ // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ // "sourceMap": true, /* Generates corresponding '.map' file. */ // "outFile": "./", /* Concatenate and emit output to single file. */ - "outDir": "./dist/", /* Redirect output structure to the directory. */ - "rootDir": "./src/", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + "outDir": "./dist/" /* Redirect output structure to the directory. */, + // "rootDir": "./src/", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ // "composite": true, /* Enable project compilation */ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ // "removeComments": true, /* Do not emit comments to output. */ @@ -25,7 +25,7 @@ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ /* Strict Type-Checking Options */ - "strict": true, /* Enable all strict type-checking options. */ + "strict": true /* Enable all strict type-checking options. */, // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "strictNullChecks": true, /* Enable strict null checks. */ // "strictFunctionTypes": true, /* Enable strict checking of function types. */ @@ -47,11 +47,14 @@ // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ - // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + "rootDirs": [ + "./src/", + "./lib/" + ] /* List of root folders whose combined content represents the structure of the project at runtime. */, // "typeRoots": [], /* List of folders to include type definitions from. */ // "types": [], /* Type declaration files to be included in compilation. */ // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ - "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ @@ -66,7 +69,7 @@ // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ /* Advanced Options */ - "skipLibCheck": true, /* Skip type checking of declaration files. */ - "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ } }