Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save WeslyG/ad40494c0be8788eeff57ed602350ecb to your computer and use it in GitHub Desktop.
Save WeslyG/ad40494c0be8788eeff57ed602350ecb to your computer and use it in GitHub Desktop.
SYNO.DownloadStation2.Task upload torrent nodejs
// yarn add axios form-data
import { createReadStream } from "fs";
import { version } from "os";
import axios, { AxiosInstance } from "axios";
import FormData from "form-data";
interface SynologyAuthResponse {
data: {
sid: string;
};
success: boolean;
}
interface SynologyTaskResponse {
data: {
list: Array<{
id: string;
status: string;
}>;
};
success: boolean;
}
interface SynologyErrorResponse {
error: {
code: number;
message: string;
};
success: boolean;
}
class SynologyDownloadStation {
private baseURL: string;
private username: string;
private password: string;
private sid: string | null = null;
private client: AxiosInstance;
constructor(baseURL: string, username: string, password: string) {
this.baseURL = baseURL;
this.username = username;
this.password = password;
this.client = axios.create({
baseURL: this.baseURL,
validateStatus: () => true,
});
}
private async login(): Promise<void> {
try {
const response = await this.client.get<SynologyAuthResponse>(
"/webapi/auth.cgi",
{
params: {
api: "SYNO.API.Auth",
version: "3",
method: "login",
account: this.username,
passwd: this.password,
session: "DownloadStation",
format: "sid",
},
}
);
if (!response.data.success) {
throw new Error("Login failed");
}
this.sid = response.data.data.sid;
} catch (error) {
throw new Error(`Authentication failed: ${error.message}`);
}
}
private async ensureAuthenticated(): Promise<void> {
if (!this.sid) {
await this.login();
}
}
async uploadTorrent(
torrentPath: string,
destination?: string
): Promise<string> {
try {
await this.ensureAuthenticated();
const formData = new FormData();
// sequence is a key!
formData.append("api", "SYNO.DownloadStation2.Task");
formData.append("method", "create");
formData.append("version", "2");
formData.append("type", `"file"`);
formData.append("file", `["torrent"]`);
if (destination) {
formData.append("destination", `"${destination}"`);
}
formData.append("create_list", "false");
formData.append("torrent", createReadStream(torrentPath));
const response = await this.client.post<
SynologyTaskResponse | SynologyErrorResponse
>(`/webapi/entry.cgi?_sid=${this.sid}`, formData, {
headers: {
...formData.getHeaders(),
Accept: "*/*",
},
});
console.log(response.data);
if ("error" in response.data) {
throw new Error(
`API Error: ${response.data.error.message} (Code: ${response.data.error.code})`
);
}
if (!response.data.success) {
throw new Error("Failed to create download task");
}
const taskId = response.data.data.task_id[0];
if (!taskId) {
throw new Error("No task ID returned");
}
return taskId;
} catch (error) {
throw new Error(`Failed to upload torrent: ${error.message}`);
}
}
async getTaskStatus(taskId: string): Promise<string> {
try {
await this.ensureAuthenticated();
const bodyUrlEncoded = new URLSearchParams();
bodyUrlEncoded.append("api", "SYNO.DownloadStation2.Task");
bodyUrlEncoded.append("version", "2");
bodyUrlEncoded.append("method", "get");
bodyUrlEncoded.append("id", `["${taskId}"]`);
bodyUrlEncoded.append("additional", `["detail", "transfer"]`);
const response = await this.client<SynologyTaskResponse>({
method: "post",
url: `${this.baseURL}/webapi/entry.cgi?_sid=${this.sid}`,
headers: { "Content-Type": "application/x-www-form-urlencoded" },
data: bodyUrlEncoded,
});
if (!response.data.success) {
throw new Error("Failed to get task status");
}
const task = response.data.data.task[0];
console.log(task);
if (!task) {
throw new Error("Task not found");
}
return task.status;
} catch (error) {
throw new Error(`Failed to get task status: ${error.message}`);
}
}
}
// Example usage:
async function main() {
const synology = new SynologyDownloadStation(
"http://IP_ADD:5000",
"username",
"password"
);
try {
// Upload torrent file
const taskId = await synology.uploadTorrent(
"2068935.torrent",
"media/films" // Optional destination path
);
console.log(`Torrent upload successful. Task ID: ${taskId}`);
// Get task status
const status = await synology.getTaskStatus(taskId);
console.log(`Task status: ${status}`);
} catch (error) {
console.error("Error:", error.message);
}
}
main();
// export default SynologyDownloadStation;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment