forked from Outils-PeerTube/peertube-plugin-auto-import-ytb
		
	Compare commits
	
		
			6 Commits
		
	
	
		
			testing
			...
			archive/va
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | ae195d9170 | ||
|  | f579afab16 | ||
|  | 41098d09a7 | ||
| b2b04df23b | |||
| 51126e7f0f | |||
| 8f8f0c3cb0 | 
| @@ -1,9 +1,6 @@ | |||||||
| // import { ImplementableApi } from './implementableApi'; |  | ||||||
| // Api request lib | // Api request lib | ||||||
| import fetch, { FetchError, Headers } from "node-fetch"; | import fetch, { FetchError, Headers } from "node-fetch"; | ||||||
| import { URL, URLSearchParams } from "url"; | import { URL, URLSearchParams } from "url"; | ||||||
| import FormData from "form-data"; |  | ||||||
| // import dedent from "ts-dedent"; |  | ||||||
|  |  | ||||||
| namespace PeerTubeRequester { | namespace PeerTubeRequester { | ||||||
|   export type Config = { |   export type Config = { | ||||||
| @@ -19,22 +16,6 @@ type UploadInstruction = { | |||||||
|   targetUrl: string; |   targetUrl: string; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| type ClientToken = { |  | ||||||
|   client_id: string; |  | ||||||
|   client_secret: string; |  | ||||||
|   grant_type: "password"; |  | ||||||
|   response_type: "code"; |  | ||||||
|   username: string; |  | ||||||
|   password: string; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| type UserToken = { |  | ||||||
|   access_token: string; |  | ||||||
|   token_type: string; |  | ||||||
|   expires_in: string; |  | ||||||
|   refresh_token: string; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| class PeerTubeRequester { | class PeerTubeRequester { | ||||||
|   readonly domain_name: URL; |   readonly domain_name: URL; | ||||||
|   readonly username: string; |   readonly username: string; | ||||||
| @@ -46,7 +27,7 @@ class PeerTubeRequester { | |||||||
|     this.password = config.password; |     this.password = config.password; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async apiRequest(message: UploadInstruction): Promise<void> { |   private async requestAuthToken(): Promise<any> { | ||||||
|     let response = await fetch( |     let response = await fetch( | ||||||
|       new URL(`/api/v1/oauth-clients/local`, this.domain_name) |       new URL(`/api/v1/oauth-clients/local`, this.domain_name) | ||||||
|     ); |     ); | ||||||
| @@ -74,15 +55,18 @@ class PeerTubeRequester { | |||||||
|     if (!response.ok) { |     if (!response.ok) { | ||||||
|       throw new Error(response.statusText); // CRASH |       throw new Error(response.statusText); // CRASH | ||||||
|     } |     } | ||||||
|     const { access_token } = await response.json(); |     const { access_token: accessToken } = await response.json(); | ||||||
|  |     return accessToken; | ||||||
|  |   } | ||||||
|  |  | ||||||
|     // Upload |   async uploadFromUrl(message: UploadInstruction): Promise<void> { | ||||||
|  |     const accessToken = await this.requestAuthToken(); | ||||||
|     const myUploadForm = new URLSearchParams(); |     const myUploadForm = new URLSearchParams(); | ||||||
|     const myHeader = new Headers(); |     const myHeader = new Headers(); | ||||||
|     myHeader.append("Authorization", `Bearer ${access_token}`); |     myHeader.append("Authorization", `Bearer ${accessToken}`); | ||||||
|     for (const key in message) myUploadForm.append(key, message[key]); |     for (const key in message) myUploadForm.append(key, message[key]); | ||||||
|  |  | ||||||
|     response = await fetch( |     const response = await fetch( | ||||||
|       new URL(`/api/v1/videos/imports`, this.domain_name), |       new URL(`/api/v1/videos/imports`, this.domain_name), | ||||||
|       { |       { | ||||||
|         method: "post", |         method: "post", | ||||||
| @@ -95,9 +79,9 @@ class PeerTubeRequester { | |||||||
|       switch (response.status) { |       switch (response.status) { | ||||||
|         case 400: |         case 400: | ||||||
|           throw new Error( |           throw new Error( | ||||||
|             `Your target URL was not accepted by the API.\ |             `Bad or malformed request. Probably because your target URL (from Youtube?) was not accepted by the API.\ | ||||||
|                         Actualy it's : ${message.targetUrl} |                         The target URL you attempted to pass: ${message.targetUrl}. | ||||||
|                         ${response.statusText}` |                         Response from the server: ${response.statusText}` | ||||||
|           ); |           ); | ||||||
|           break; |           break; | ||||||
|         case 403: |         case 403: | ||||||
| @@ -105,15 +89,15 @@ class PeerTubeRequester { | |||||||
|           break; |           break; | ||||||
|         case 409: |         case 409: | ||||||
|           throw new Error( |           throw new Error( | ||||||
|             `Oops, your instance had not allowed the HTTPS import.\ |             `Oops, your instance did not allowed the HTTPS import.\ | ||||||
|                         Contact your administrator. |                         Contact your administrator. | ||||||
|                         ${response.statusText}` |                         ${response.statusText}` | ||||||
|           ); |           ); | ||||||
|           break; |           break; | ||||||
|         default: |         default: | ||||||
|           throw new Error( |           throw new Error( | ||||||
|             `Oh, you resolved an undocumented issues.\ |             `Oh, you encountered an undocumented issues.\ | ||||||
|                         Please report this on the git if you have the time. |                         Please create an issue to the plugin project. | ||||||
|                         ERROR: ${response.statusText}` |                         ERROR: ${response.statusText}` | ||||||
|           ); |           ); | ||||||
|           break; |           break; | ||||||
|   | |||||||
							
								
								
									
										34
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										34
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1,15 +1,15 @@ | |||||||
| { | { | ||||||
|   "name": "peertube-plugin-auto-import-ytb", |   "name": "peertube-plugin-auto-import-ytb", | ||||||
|   "version": "0.0.2", |   "version": "0.0.1", | ||||||
|   "lockfileVersion": 2, |   "lockfileVersion": 2, | ||||||
|   "requires": true, |   "requires": true, | ||||||
|   "packages": { |   "packages": { | ||||||
|     "": { |     "": { | ||||||
|       "version": "0.0.2", |       "version": "0.0.1", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@types/node-fetch": "^2.5.11", |         "@types/node-fetch": "^2.5.11", | ||||||
|         "form-data": "^4.0.0", |         "form-data": "^4.0.0", | ||||||
|         "listener-rss-agregator": "git+https://zeteo.me/gitea/Outils-PeerTube/listener-rss-agregators#1b36afbb34", |         "listener-rss-aggregator": "^0.0.5", | ||||||
|         "node-fetch": "^2.6.1" |         "node-fetch": "^2.6.1" | ||||||
|       }, |       }, | ||||||
|       "devDependencies": { |       "devDependencies": { | ||||||
| @@ -398,11 +398,10 @@ | |||||||
|         "rss-parser": "^3.11.0" |         "rss-parser": "^3.11.0" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/listener-rss-agregator": { |     "node_modules/listener-rss-aggregator": { | ||||||
|       "version": "0.0.3", |       "version": "0.0.5", | ||||||
|       "resolved": "git+https://zeteo.me/gitea/Outils-PeerTube/listener-rss-agregators#1b36afbb344112c3827b5bcea92e1cc60bd8cf6a", |       "resolved": "https://registry.npmjs.org/listener-rss-aggregator/-/listener-rss-aggregator-0.0.5.tgz", | ||||||
|       "hasInstallScript": true, |       "integrity": "sha512-0QE7kkzurjsWr4gNAJ4X+C7UFSyaVuYq2mKYXZ3shvyj81kULpBgFZSg/70MZkUoqixgWQ5P8oxyztRDOP78tw==", | ||||||
|       "license": "MIT", |  | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "@databases/sqlite": "^3.0.0", |         "@databases/sqlite": "^3.0.0", | ||||||
|         "listener-rss": "^0.0.3" |         "listener-rss": "^0.0.3" | ||||||
| @@ -799,9 +798,9 @@ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "node_modules/tar": { |     "node_modules/tar": { | ||||||
|       "version": "4.4.13", |       "version": "4.4.14", | ||||||
|       "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", |       "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.14.tgz", | ||||||
|       "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", |       "integrity": "sha512-ouN3XcSWYOAHmXZ+P4NEFJvqXL50To9OZBSQNNP30vBUFJFZZ0PLX15fnwupv6azfxMUfUDUr2fhYw4zGAEPcg==", | ||||||
|       "dependencies": { |       "dependencies": { | ||||||
|         "chownr": "^1.1.1", |         "chownr": "^1.1.1", | ||||||
|         "fs-minipass": "^1.2.5", |         "fs-minipass": "^1.2.5", | ||||||
| @@ -1270,9 +1269,10 @@ | |||||||
|         "rss-parser": "^3.11.0" |         "rss-parser": "^3.11.0" | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     "listener-rss-agregator": { |     "listener-rss-aggregator": { | ||||||
|       "version": "git+https://zeteo.me/gitea/Outils-PeerTube/listener-rss-agregators#1b36afbb344112c3827b5bcea92e1cc60bd8cf6a", |       "version": "0.0.5", | ||||||
|       "from": "listener-rss-agregator@git+https://zeteo.me/gitea/Outils-PeerTube/listener-rss-agregators#1b36afbb34", |       "resolved": "https://registry.npmjs.org/listener-rss-aggregator/-/listener-rss-aggregator-0.0.5.tgz", | ||||||
|  |       "integrity": "sha512-0QE7kkzurjsWr4gNAJ4X+C7UFSyaVuYq2mKYXZ3shvyj81kULpBgFZSg/70MZkUoqixgWQ5P8oxyztRDOP78tw==", | ||||||
|       "requires": { |       "requires": { | ||||||
|         "@databases/sqlite": "^3.0.0", |         "@databases/sqlite": "^3.0.0", | ||||||
|         "listener-rss": "^0.0.3" |         "listener-rss": "^0.0.3" | ||||||
| @@ -1604,9 +1604,9 @@ | |||||||
|       "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" |       "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" | ||||||
|     }, |     }, | ||||||
|     "tar": { |     "tar": { | ||||||
|       "version": "4.4.13", |       "version": "4.4.14", | ||||||
|       "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.13.tgz", |       "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.14.tgz", | ||||||
|       "integrity": "sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA==", |       "integrity": "sha512-ouN3XcSWYOAHmXZ+P4NEFJvqXL50To9OZBSQNNP30vBUFJFZZ0PLX15fnwupv6azfxMUfUDUr2fhYw4zGAEPcg==", | ||||||
|       "requires": { |       "requires": { | ||||||
|         "chownr": "^1.1.1", |         "chownr": "^1.1.1", | ||||||
|         "fs-minipass": "^1.2.5", |         "fs-minipass": "^1.2.5", | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| { | { | ||||||
|   "name": "peertube-plugin-auto-import-ytb", |   "name": "peertube-plugin-auto-import-ytb", | ||||||
|   "description": "PeerTube plugin quickstart", |   "description": "PeerTube plugin quickstart", | ||||||
|   "version": "0.0.2", |   "version": "0.0.1", | ||||||
|   "author": "AmauryJOLY", |   "author": "AmauryJOLY", | ||||||
|   "bugs": "https://framagit.org/framasoft/peertube/peertube-plugin-quickstart/issues", |   "bugs": "https://framagit.org/framasoft/peertube/peertube-plugin-quickstart/issues", | ||||||
|   "clientScripts": [], |   "clientScripts": [], | ||||||
| @@ -24,7 +24,6 @@ | |||||||
|     "README.md" |     "README.md" | ||||||
|   ], |   ], | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "prepack": "npm i && npm run build", |  | ||||||
|     "predeploy": "npm run build", |     "predeploy": "npm run build", | ||||||
|     "deploy": "bash ./scripts/deploy.sh", |     "deploy": "bash ./scripts/deploy.sh", | ||||||
|     "build": "tsc" |     "build": "tsc" | ||||||
| @@ -34,7 +33,7 @@ | |||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@types/node-fetch": "^2.5.11", |     "@types/node-fetch": "^2.5.11", | ||||||
|     "form-data": "^4.0.0", |     "form-data": "^4.0.0", | ||||||
|     "listener-rss-agregator": "git+https://zeteo.me/gitea/Outils-PeerTube/listener-rss-agregators#1b36afbb34", |     "listener-rss-aggregator": "^0.0.5", | ||||||
|     "node-fetch": "^2.6.1" |     "node-fetch": "^2.6.1" | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										224
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										224
									
								
								src/main.ts
									
									
									
									
									
								
							| @@ -1,113 +1,111 @@ | |||||||
| import { ListenerRssAggregator } from "listener-rss-agregator"; | import { ListenerRssAggregator } from "listener-rss-aggregator"; | ||||||
| import { ListenerRss } from "listener-rss"; | import { ListenerRss } from "listener-rss"; | ||||||
| import { PeerTubeRequester } from "../lib/peertubeRequester"; | import { PeerTubeRequester } from "../lib/peertubeRequester"; | ||||||
|  |  | ||||||
| type ListenerData = ListenerRss.Config & { | type ListenerData = ListenerRss.Config & { | ||||||
|   address: string; |   address: string; | ||||||
|   channelId: string; |   channelId: string; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| let myManager: ListenerRssAggregator; | let myManager: ListenerRssAggregator; | ||||||
| let listenersDataBinding = new Map<string, ListenerData>(); | let listenersDataBinding = new Map<string, ListenerData>(); | ||||||
| let logger: any; | let logger: any; | ||||||
| let peertube: PeerTubeRequester; | let peertube: PeerTubeRequester; | ||||||
|  |  | ||||||
| import * as path from "path"; | import * as path from "path"; | ||||||
| import fs from "fs"; | import fs from "fs"; | ||||||
|  |  | ||||||
| async function register({ | async function register({ | ||||||
|   registerSetting, |   registerSetting, | ||||||
|   settingsManager, |   settingsManager, | ||||||
|   peertubeHelpers, |   peertubeHelpers, | ||||||
| }: any) { | }: any) { | ||||||
|   const basePath = peertubeHelpers.plugin.getDataDirectoryPath(); |   const basePath = peertubeHelpers.plugin.getDataDirectoryPath(); | ||||||
|   logger = peertubeHelpers.logger; |   logger = peertubeHelpers.logger; | ||||||
|  |  | ||||||
|   registerSetting({ |   registerSetting({ | ||||||
|     name: "ytb-urls", |     name: "ytb-urls", | ||||||
|     label: "liste des urls youtube a auto-importer", |     label: "URL list of Youtube channel to synchronize", | ||||||
|     type: "input-textarea", |     type: "input-textarea", | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   logger.warn("setting register"); |   logger.debug("setting register"); | ||||||
|   fs.appendFileSync(path.join(basePath, "/storage.bd"), ""); |   fs.appendFileSync(path.join(basePath, "/storage.bd"), ""); | ||||||
|  |  | ||||||
|   const configAggregator = await ListenerRssAggregator.instantiateAggregator( |   const configAggregator = await ListenerRssAggregator.instantiateAggregator( | ||||||
|     path.join(basePath, "/storage.bd") |     path.join(basePath, "/storage.bd") | ||||||
|   ); |   ); | ||||||
|   myManager = new ListenerRssAggregator(configAggregator); |   myManager = new ListenerRssAggregator(configAggregator); | ||||||
|  |  | ||||||
|   peertube = new PeerTubeRequester({ |   peertube = new PeerTubeRequester({ | ||||||
|     domain_name: "http://localhost:9000", |     domain_name: "http://localhost:9000", | ||||||
|     username: "root", |     username: "root", | ||||||
|     password: "test", |     password: "test", | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   logger.warn("Aggregator created"); |   logger.debug("Aggregator created"); | ||||||
|  |  | ||||||
|   const inputs = await settingsManager.getSetting("ytb-urls"); |   const inputs = await settingsManager.getSetting("ytb-urls"); | ||||||
|   if (inputs) await addListeners(inputs); |   if (inputs) await addListeners(inputs); | ||||||
|  |  | ||||||
|   logger.warn("Config loaded"); |   logger.debug("Config loaded"); | ||||||
|  |  | ||||||
|   settingsManager.onSettingsChange(async (settings: any) => { |   settingsManager.onSettingsChange(async (settings: any) => { | ||||||
|     await addListeners(settings["ytb-urls"]); |     await addListeners(settings["ytb-urls"]); | ||||||
|   }); |   }); | ||||||
|  |  | ||||||
|   myManager.on("newEntries", (entries: any) => { |   myManager.on("newEntries", async (entries: any) => { | ||||||
|     const datas = listenersDataBinding.get(entries.addressListener); |     const datas = listenersDataBinding.get(entries.addressListener); | ||||||
|     if (!datas) return; |     if (!datas) return; | ||||||
|  |  | ||||||
|     logger.warn( |     logger.debug( | ||||||
|       "Nouvelles entrées détéctées: " + |       "New entries detected from channel #%i: %s", | ||||||
|         JSON.stringify(entries) + |       datas.channelId, | ||||||
|         " de " + |       JSON.stringify(entries) | ||||||
|         datas.channelId |     ); | ||||||
|     ); |     for (const item of entries.items) | ||||||
|     for (const item of entries.items) |       await peertube.uploadFromUrl({ | ||||||
|       peertube.apiRequest({ |         channelId: datas.channelId, | ||||||
|         channelId: datas.channelId, |         targetUrl: item.link, | ||||||
|         targetUrl: item.link, |       }); | ||||||
|       }); |   }); | ||||||
|   }); | } | ||||||
| } |  | ||||||
|  | async function addListeners(listenerInput: string) { | ||||||
| async function addListeners(listenerInput: string) { |   let listeners: ListenerData[]; | ||||||
|   let listeners: ListenerData[]; |   try { | ||||||
|   try { |     listeners = JSON.parse(listenerInput); | ||||||
|     listeners = JSON.parse(listenerInput); |   } catch { | ||||||
|   } catch { |     logger.error("Malformed URL"); | ||||||
|     logger.warn("Erreur: malformé"); |     return; | ||||||
|     return; |   } | ||||||
|   } |   let newListeners = listeners.filter( | ||||||
|   let newListeners = listeners.filter( |     (item) => !listenersDataBinding.has(item.address) | ||||||
|     (item) => !listenersDataBinding.has(item.address) |   ); | ||||||
|   ); |   let removedUrls = Array.from(listenersDataBinding.keys()).filter( | ||||||
|   let removedUrls = Array.from(listenersDataBinding.keys()).filter( |     (url) => !listeners.some((listener) => listener.address === url) | ||||||
|     (url) => !listeners.some((listener) => listener.address === url) |   ); | ||||||
|   ); |  | ||||||
|  |   for (const newItem of newListeners) { | ||||||
|   for (const newItem of newListeners) { |     listenersDataBinding.set(newItem.address, newItem); | ||||||
|     listenersDataBinding.set(newItem.address, newItem); |   } | ||||||
|   } |   for (const removedUrl of removedUrls) { | ||||||
|   for (const removedUrl of removedUrls) { |     listenersDataBinding.delete(removedUrl); | ||||||
|     listenersDataBinding.delete(removedUrl); |   } | ||||||
|   } |  | ||||||
|  |   myManager.stopAll(); | ||||||
|   myManager.stopAll(); |   await myManager.saveOverride(listeners); | ||||||
|   await myManager.saveOverride(listeners); |  | ||||||
|  |   if (logger) logger.warn("Configuration changed: " + listenerInput); | ||||||
|   if (logger) logger.warn("Configuration modifiée: " + listenerInput); |  | ||||||
|  |   myManager.startAll(); | ||||||
|   myManager.startAll(); | } | ||||||
| } |  | ||||||
|  | async function unregister() { | ||||||
| async function unregister() { |   myManager.stopAll(); | ||||||
|   myManager.stopAll(); | } | ||||||
|   return; |  | ||||||
| } | module.exports = { | ||||||
|  |   register, | ||||||
| module.exports = { |   unregister, | ||||||
|   register, | }; | ||||||
|   unregister, |  | ||||||
| }; |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user