diff --git a/app/src/downloader/downloader-interface.ts b/app/src/downloader/downloader-interface.ts index 41e2269..7c112f3 100644 --- a/app/src/downloader/downloader-interface.ts +++ b/app/src/downloader/downloader-interface.ts @@ -2,7 +2,8 @@ import File from "../file/file"; import {DownloadFile} from "../file/download-file"; export enum DownloaderType { - FILESYSTEM = 'filesystem' + FILESYSTEM = 'filesystem', + SYNOLOGY_DS = 'synology_ds', } export default interface DownloaderInterface { diff --git a/app/src/downloader/synology-ds-downloader.ts b/app/src/downloader/synology-ds-downloader.ts new file mode 100644 index 0000000..9d574eb --- /dev/null +++ b/app/src/downloader/synology-ds-downloader.ts @@ -0,0 +1,54 @@ +import Downloader from "./decorator/downloader"; +import DownloaderInterface, {DownloaderType} from "./downloader-interface"; +import {ServiceParamType} from "../dependency-injection/param-provider"; +import {DownloadEvent, DownloadFile} from "../file/download-file"; +import SynologyDsClient from "./synology/synology-ds-client"; +import EventEmitter from "events"; +import File from "../file/file"; + +@Downloader( + DownloaderType.SYNOLOGY_DS, + [ + { + id: SynologyDsClient.name, + type: ServiceParamType.INJECTABLE_SERVICE + } + ] +) +export default class SynologyDsDownloader implements DownloaderInterface { + private readonly client: SynologyDsClient; + + constructor(client: SynologyDsClient) { + this.client = client; + } + + initialize(): void { + } + + getDownloadFile(file: File): DownloadFile { + const eventEmitter = new EventEmitter(); + return new DownloadFile(file, () => { + this.onDownload(eventEmitter, file); + }, eventEmitter); + } + + private async onDownload(eventEmitter: EventEmitter, file: File) { + await this.client.launchDownload(file.link); + eventEmitter.emit(DownloadEvent.START_DOWNLOAD); + + const interval = setInterval(async () => { + try { + if ('finished' === await this.client.getStatus(file.link)) { + eventEmitter.emit(DownloadEvent.DONE); + clearInterval(interval); + } + } catch (error) { + eventEmitter.emit(DownloadEvent.ERROR, error); + clearInterval(interval); + } + }, 3000); + } + + close(): void { + } +} \ No newline at end of file diff --git a/app/src/downloader/synology/synology-ds-client.ts b/app/src/downloader/synology/synology-ds-client.ts new file mode 100644 index 0000000..aa31ad3 --- /dev/null +++ b/app/src/downloader/synology/synology-ds-client.ts @@ -0,0 +1,89 @@ +import Service from "../../dependency-injection/decorator/service"; +import {ServiceParamType} from "../../dependency-injection/param-provider"; +import axios from "axios"; + +const urlencode = require('urlencode') + +@Service( + SynologyDsClient.name, + [ + { + id: 'SYNOLOGY_ENDPOINT', + type: ServiceParamType.ENVIRONMENT_VARIABLE + }, + { + id: 'SYNOLOGY_USERNAME', + type: ServiceParamType.ENVIRONMENT_VARIABLE + }, + { + id: 'SYNOLOGY_PASSWORD', + type: ServiceParamType.ENVIRONMENT_VARIABLE + }, + ] +) +export default class SynologyDsClient { + private readonly endpoint: string; + private readonly username: string; + private readonly password: string; + + constructor(endpoint: string, username: string, password: string) { + this.endpoint = endpoint; + this.username = username; + this.password = password; + } + + private getUrlParams (params) { + return '?' + Object + .keys(params) + .map(key => `${key}=${urlencode(params[key])}`) + .join('&') + } + + private getUrl (uri: string, params: object = {}) { + const defaultParams = { username: this.username, password: this.password } + const host = this.endpoint; + + return host + uri + this.getUrlParams({ ...defaultParams, ...params }) + } + + async launchDownload(fileUrl: string): Promise { + await axios.post( + this.getUrl( + '/webapi/DownloadStation/task.cgi', + { + api: 'SYNO.DownloadStation.Task', + version: 1, + method: 'create', + uri: fileUrl + } + ) + ) + } + + async getStatus(fileUrl: string): Promise { + const response = await axios.post( + this.getUrl( + '/webapi/DownloadStation/task.cgi', + { + api: 'SYNO.DownloadStation.Task', + version: 1, + method: 'list', + additional: 'file' + } + ) + ) + console.log(response); + + // @ts-ignore + for (let task of response.data.tasks) { + + // @ts-ignore + if (fileUrl === task.additional.detail.uri) { + // @ts-ignore + return task.status; + } + } + + return 'unknow' + } +} \ No newline at end of file diff --git a/app/src/services.ts b/app/src/services.ts index d9ff3b2..9024161 100644 --- a/app/src/services.ts +++ b/app/src/services.ts @@ -3,6 +3,7 @@ import AllDebridDebrider from "./debrider/all-debrid-debrider"; import FilesystemDownloader from "./downloader/filesystem-downloader"; import PushoverNotifier from "./notifier/pushover-notifier"; import StdoutNotifier from "./notifier/stdout-notifier"; +import SynologyDsDownloader from "./downloader/synology-ds-downloader"; /** * Declaration of services @@ -16,7 +17,8 @@ const services = { AllDebridDebrider }, downloader: { - FilesystemDownloader + FilesystemDownloader, + SynologyDsDownloader, }, notifier: { PushoverNotifier,