Skip to content

Instantly share code, notes, and snippets.

@franzwong
Last active November 10, 2022 08:28
Show Gist options
  • Save franzwong/797c1ba6539d2f6de36242fa9faa405c to your computer and use it in GitHub Desktop.
Save franzwong/797c1ba6539d2f6de36242fa9faa405c to your computer and use it in GitHub Desktop.
Synology DownloadStation Task
const axios = require('axios');
const url = require('url');
if (process.argv && process.argv.length < 3) {
console.error('Invalid number of parameters');
process.exit(1);
}
const downloadLink = process.argv[2];
const domain = process.env.domain;
const username = process.env.username;
const password = process.env.password;
async function login() {
const response = await axios({
method: 'GET',
url: url.resolve(domain, '/webapi/auth.cgi'),
params: {
api: 'SYNO.API.Auth',
version: '2',
method: 'login',
account: username,
passwd: password,
session: 'DownloadStation',
format: 'sid',
}
});
const data = response.data;
if (data.success) {
return data.data.sid;
}
}
async function addDownloadTask(sid, downloadLink) {
const response = await axios({
method: 'GET',
url: url.resolve(domain, '/webapi/DownloadStation/task.cgi'),
params: {
api: 'SYNO.DownloadStation.Task',
version: '1',
method: 'create',
uri: downloadLink,
_sid: sid,
}
});
return response.data.success;
}
(async function() {
const sid = await login();
const result = addDownloadTask(sid, downloadLink);
console.log(`result: ${result}`);
})();
// [dependencies]
// reqwest = { version = "0.11.12", features = ["blocking", "json"] }
// serde = { version = "1.0.147", features = ["derive"] }
// toml = "0.5.9"
use std::fs;
use std::env;
use std::process;
use std::path;
use reqwest;
use reqwest::StatusCode;
use serde;
use toml;
#[derive(serde::Deserialize)]
struct Config {
domain: String,
user_name: String,
password: String,
}
#[derive(serde::Deserialize)]
struct LoginResponse {
success: bool,
data: LoginDataResponse,
error: Option<ErrorResponse>,
}
#[derive(serde::Deserialize)]
struct LoginDataResponse {
sid: String,
}
#[derive(serde::Deserialize)]
struct AddDownloadTaskResponse {
success: bool,
error: Option<ErrorResponse>,
}
#[derive(serde::Deserialize)]
struct ErrorResponse {
code: i32
}
fn login(domain: &str, user_name: &str, password: &str) -> String {
let login_params = [
("api", "SYNO.API.Auth"),
("version", "2"),
("method", "login"),
("account", user_name),
("passwd", password),
("session", "DownloadStation"),
("format", "sid")
];
let login_url = format!("http://{}/webapi/auth.cgi", domain);
let login_url = reqwest::Url::parse_with_params(login_url.as_str(), &login_params).unwrap();
let login_response = reqwest::blocking::get(login_url).unwrap();
match login_response.status() {
StatusCode::OK => {
let login_response: LoginResponse = login_response.json().unwrap();
if login_response.success {
println!("Login successful");
return String::from(login_response.data.sid);
} else {
panic!("Fail to login. Code: {}", login_response.error.unwrap().code);
}
}
err => {
panic!("Fail to login. {}", err);
}
}
}
fn add_download_task(domain: &str, download_link: &str, sid: &str) {
let add_download_task_params = [
("api", "SYNO.DownloadStation.Task"),
("version", "1"),
("method", "create"),
("uri", download_link),
("_sid", sid),
];
let add_download_task_url = format!("http://{}/webapi/DownloadStation/task.cgi", domain);
let add_download_task_url = reqwest::Url::parse_with_params(add_download_task_url.as_str(), &add_download_task_params).unwrap();
let add_download_task_response = reqwest::blocking::get(add_download_task_url).unwrap();
match add_download_task_response.status() {
StatusCode::OK => {
let add_download_task_response: AddDownloadTaskResponse = add_download_task_response.json().unwrap();
if add_download_task_response.success {
println!("Task added successfully");
} else {
panic!("Fail to add task. Code: {}", add_download_task_response.error.unwrap().code);
}
}
err => {
panic!("Fail to add task. {}", err);
}
}
}
fn main() {
let application_config_path = path::Path::new("application.toml");
if !application_config_path.exists() {
eprintln!("application.toml does not exist");
process::exit(1);
}
let app_config = fs::read_to_string(application_config_path);
let app_config: Config = toml::from_str(&app_config.unwrap()).unwrap();
let args: Vec<String> = env::args().collect();
if args.len() < 2 {
eprintln!("Invalid number of parameters");
process::exit(1);
}
let download_link = &args[1];
let sid = login(&app_config.domain, &app_config.user_name, &app_config.password);
add_download_task(&app_config.domain, download_link, &sid);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment