├── .gitignore ├── config.js ├── router ├── api.js ├── user.js ├── cloudsync.js └── system.js ├── package.json ├── page └── index.html ├── index.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | domain: 'www.test.site', // 群晖的域名或者ip 3 | port: 5000, // 端口号 4 | https: false,// 是否为https 5 | apiPort: 80, // api启动端口 6 | responseTimeout: 10 // 请求多少秒后超时 7 | } -------------------------------------------------------------------------------- /router/api.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const router = express.Router(); 3 | const axios = require("axios"); 4 | 5 | router.get("/all", (req, res) => { // 获取所有api接口 6 | axios.get(`${req.domain}/webapi/query.cgi?api=SYNO.API.Info&version=1&method=query&query=all`) 7 | .then(response => { 8 | const { data: data } = response.data; 9 | res.send(data) 10 | }).catch(err => res.send(err) 11 | ) 12 | }) 13 | module.exports = router; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "syno_api", 3 | "version": "1.0.0", 4 | "description": "将本项目搭建在任何有网络的地方上,可以通过RESTful API调用群晖nas接口,可用于开发前端项目,也可用于定制自己专属的管理系统,本项目持续更新中", 5 | "main": "index.js", 6 | "scripts": { 7 | "dsm": "npx forever start ./index.js", 8 | "stop": "npx forever stop ./index.js" 9 | }, 10 | "keywords": [ 11 | "群晖", 12 | "synology" 13 | ], 14 | "author": "wushanglin", 15 | "license": "ISC", 16 | "dependencies": { 17 | "axios": "^1.2.1", 18 | "cors": "^2.8.5", 19 | "express": "^4.18.2", 20 | "express-session": "^1.17.3", 21 | "forever": "^4.0.3", 22 | "nodemon": "^2.0.20" 23 | } 24 | } -------------------------------------------------------------------------------- /page/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Document 9 | 10 | 11 | 12 |

test

13 | 14 | 25 | 26 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | "use strict" 2 | const express = require('express'); 3 | const cors = require('cors'); 4 | const app = express(); 5 | const session = require("express-session"); 6 | const config = require("./config.js"); 7 | app.use('/', express.static('./page')); 8 | app.use(cors()); 9 | app.use(session({ 10 | secret: "DSM-api", 11 | resave: false, 12 | saveUninitialized: true 13 | })) 14 | // 处理config.js 15 | app.use(function (req, res, next) { 16 | if (config.https) { 17 | req.domain = `https://${config.domain}:${config.port}` 18 | } else { 19 | req.domain = `http://${config.domain}:${config.port}` 20 | } 21 | req.api = req.domain + '/webapi'; 22 | next(); 23 | }) 24 | 25 | // 获取api接口 26 | const api_router = require('./router/api.js'); 27 | app.use('/api', api_router); 28 | // 用户 29 | const user_router = require("./router/user.js"); 30 | app.use('/user', user_router); 31 | // 系统 32 | const info_router = require("./router/system.js"); 33 | app.use('/system', info_router); 34 | // cloudsync 35 | const cloudsync_router = require("./router/cloudsync.js"); 36 | app.use('/cloudsync', cloudsync_router); 37 | // 接受错误,防止项目崩溃 38 | app.use((err, req, res, next) => { 39 | res.send(err.message); 40 | }) 41 | 42 | app.listen(config.apiPort) -------------------------------------------------------------------------------- /router/user.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const router = express.Router(); 3 | const axios = require("axios"); 4 | const config = require("../config.js"); 5 | // console.log(method.iferror); 6 | router.get('/login', (req, res) => { 7 | if (!req.query.username || !req.query.password) { // 登录群晖 8 | throw new Error('请传入用户名和密码') 9 | } 10 | 11 | axios.get(`${req.api}/entry.cgi?api=SYNO.API.Auth&version=7&method=login&account=${req.query.username}&passwd=${req.query.password}&session=FileStation&format=sid`, { timeout: (config.responseTimeout * 1000) }) 12 | .then(response => { // 判断返回的值是否正确 13 | return new Promise((resolve, reject) => { 14 | if (response.data.data) { 15 | resolve(response.data); 16 | } else if (response.data.error.code == 400) { 17 | reject(new Error("密码或账号错误")) 18 | } else if (response.data.error.code == 407) { 19 | reject(new Error("IP 地址已被封锁,因为它已达到特定时间允许的登录尝试失败最大数。请修改最大访问次数")) 20 | } 21 | }); 22 | }) 23 | .then(response => { // 正确的处理 24 | // console.log(response); 25 | req.session.auth = response.data.sid; 26 | res.send(response) 27 | 28 | }).catch(e => { // 错误的处理 29 | res.send(e.message) 30 | }) 31 | 32 | 33 | }) 34 | 35 | router.get('/logout', (req, res) => {// 登出群晖 BUG 36 | axios.get(`${req.api}/auth.cgi?api=SYNO.API.Auth&version=7&method=logout&session=FileStation&${req.query.cookie}`, { timeout: (config.responseTimeout * 1000) }) 37 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 38 | return new Promise((resolve, reject) => { 39 | const string = JSON.stringify(response.data).slice(0, 85); 40 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 41 | reject(new Error('登录过期,请重新登录')) 42 | } else { 43 | resolve(response.data) 44 | } 45 | }); 46 | }) 47 | .then(response => { 48 | res.send(response) 49 | }) 50 | .catch(e => { 51 | res.send(e.message) 52 | }) 53 | }) 54 | module.exports = router; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 将本项目可以搭建在任何有网络的地方上,使用RESTful API调用群晖nas接口,可用于开发前端项目,也可用于定制自己专属的管理系统,本项目持续更新中" 2 | 3 | # 注意事项 4 | 5 | - **填写好config.js文件** 6 | 7 | - **node.js版本大于或等于14** 8 | 9 | 10 | 11 | **根据测试,群晖7.1.1系统可以正常使用,理论上其他版本也能使用,如有问题请创建issue** 12 | 13 | # 使用教程 14 | 15 | ### 群晖 :确保已安装npm和node.js,在群晖管理页面创建好文件夹,将项目里所有文件上传,通过ssh进入到该文件夹,运行下方命令 16 | 17 | ### windows:安装node.js后,通过powershell打开该项目,运行命令 18 | 19 | ### linux:都用linux了,不用我多说了吧(手动狗头),安装好node环境和npm,运行命令即可 20 | 21 | ```powershell 22 | $ npm install 23 | $ npm run dsm // 运行项目 24 | $ npm run stop // 停止项目 25 | ``` 26 | 27 | # 关于返回结果的问题 28 | 29 | | 状态码 | 解答 | 30 | | ------ | ------------------------------------ | 31 | | 102 | 返回个状态码一般是未安装该应用导致的 | 32 | 33 | 34 | 35 | # 在运行其他api之前先进行登录,本项目采用中间件封装形式,通过调用以下api即可操作群晖系统 36 | 37 | 示例 **http://romain:port/user/login?username=dsm&password=123456** 38 | 39 | romain为域名 40 | 41 | port为端口 42 | 43 | ## /api 简介 44 | 45 | all 获取所有群晖api接口 46 | 47 | ## /user 简介 48 | 49 | /login 登录 50 | 51 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 52 | | -------- | -------- | -------- | -------------- | 53 | | username | true | string | 群晖登录用户名 | 54 | | password | true | string | 群晖登录密码 | 55 | 56 | /logout 退出 57 | 58 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 59 | | -------- | -------- | -------- | ---- | 60 | 61 | ## /system 简介 62 | 63 | /info 获取系统基本信息 64 | 65 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 66 | | -------- | -------- | -------- | ---- | 67 | 68 | /status 获取系统状态 69 | 70 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 71 | | -------- | -------- | -------- | ---- | 72 | 73 | /network 获取网络信息 74 | 75 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 76 | | -------- | -------- | -------- | ---- | 77 | 78 | /service 获取已启用的服务 79 | 80 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 81 | | -------- | -------- | -------- | ---- | 82 | 83 | /terminal 终端设置 84 | 85 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 86 | | ------------ | -------- | -------- | ------------------------------ | 87 | | enablessh | false | boolean | 开启或关闭ssh,不填则不更改 | 88 | | enabletelnet | false | boolean | 开启或关闭telnet,不填则不更改 | 89 | | sshport | false | boolean | ssh端口,不填则不更改 | 90 | 91 | /shutdown 关机 92 | 93 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 94 | | -------- | -------- | -------- | --------------------------- | 95 | | force | false | boolean | true则为强制关机,默认false | 96 | 97 | /reboot 重启 98 | 99 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 100 | | -------- | -------- | -------- | --------------------------- | 101 | | force | false | boolean | true则为强制重启,默认false | 102 | 103 | ## /cloudsync 简介 104 | 105 | /list 获取cloudsync所有已授权的云盘 106 | 107 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 108 | | -------- | -------- | -------- | ---- | 109 | 110 | /settingmsg 获取云盘设置信息 111 | 112 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 113 | | -------- | -------- | -------- | -------------------------- | 114 | | id | true | number | 网盘的对应id,在list里获取 | 115 | 116 | /status 获取云盘状态信息 117 | 118 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 119 | | -------- | -------- | -------- | -------------------------- | 120 | | id | true | number | 网盘的对应id,在list里获取 | 121 | 122 | /property 获取云盘属性信息 123 | 124 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 125 | | -------- | -------- | -------- | -------------------------- | 126 | | id | true | number | 网盘的对应id,在list里获取 | 127 | 128 | /log 同步记录 129 | 130 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 131 | | -------- | -------- | -------- | ------------------------------- | 132 | | id | true | number | 网盘的对应id,在list里获取 | 133 | | limit | false | number | 一次性获取多少数据,默认为200条 | 134 | 135 | /change 更改云盘同步设置 136 | 137 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 138 | | ---------------- | -------- | -------- | -------------------------- | 139 | | id | true | number | 网盘的对应id,在list里获取 | 140 | | name | true | string | cloudsync里显示的名称 | 141 | | Pollingtime | true | number | 轮询时间 | 142 | | maxdownloadspeed | true | number | 最大下载速度,0为不限速 | 143 | | maxuploadspeed | true | number | 最大上传速度,0为不限速 | 144 | 145 | /pause 暂停同步所有云盘 146 | 147 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 148 | | -------- | -------- | -------- | ---- | 149 | 150 | /start 开始同步 151 | 152 | | 参数名称 | 是否必填 | 接口类型 | 说明 | 153 | | -------- | -------- | -------- | ---- | 154 | -------------------------------------------------------------------------------- /router/cloudsync.js: -------------------------------------------------------------------------------- 1 | const { default: axios } = require('axios'); 2 | const express = require('express') 3 | const router = express.Router(); 4 | const config = require("../config.js"); 5 | router.get("/list", (req, res) => { // 获取cloudsync列表 6 | axios.get(`${req.api}/entry.cgi?is_tray=false&group_by="group_by_user"&api=SYNO.CloudSync&method=list_conn&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 7 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 8 | return new Promise((resolve, reject) => { 9 | const string = JSON.stringify(response.data).slice(0, 85); 10 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 11 | reject(new Error('登录过期,请重新登录')) 12 | } else { 13 | resolve(response.data) 14 | } 15 | }); 16 | }) 17 | .then(response => { 18 | res.send(response); 19 | }) 20 | .catch(e => { 21 | res.send(e.message) 22 | }) 23 | }) 24 | 25 | router.get("/settingmsg", (req, res) => { // 获取items设置信息 26 | if (!(req.query.id >= 0) || req.query.id == undefined) { 27 | throw new Error("请添加list的请求id") 28 | } 29 | axios.get(`${req.api}/entry.cgi?connection_id=${req.query.id}&api=SYNO.CloudSync&method=get_connection_setting&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 30 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 31 | return new Promise((resolve, reject) => { 32 | const string = JSON.stringify(response.data).slice(0, 85); 33 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 34 | reject(new Error('登录过期,请重新登录')) 35 | } else { 36 | resolve(response.data) 37 | } 38 | }); 39 | }) 40 | .then(response => { 41 | res.send(response); 42 | }).catch(e => { 43 | res.send(e.message) 44 | }) 45 | }) 46 | 47 | router.get("/status", (req, res) => { // 获取items状态信息 48 | if (!(req.query.id >= 0) || req.query.id == undefined) { 49 | throw new Error("请添加list的请求id") 50 | } 51 | axios.get(`${req.api}/entry.cgi?connection_id=3&api=SYNO.CloudSync&method=list_sess&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 52 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 53 | return new Promise((resolve, reject) => { 54 | const string = JSON.stringify(response.data).slice(0, 85); 55 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 56 | reject(new Error('登录过期,请重新登录')) 57 | } else { 58 | resolve(response.data) 59 | } 60 | }); 61 | }) 62 | .then(response => { 63 | res.send(response); 64 | }) 65 | .catch(e => { 66 | res.send(e.message) 67 | }) 68 | }) 69 | 70 | router.get("/property", (req, res) => { // 获取items属性信息 71 | if (!(req.query.id >= 0) || req.query.id == undefined) { 72 | throw new Error("请添加list的请求id") 73 | } 74 | axios.get(`${req.api}/entry.cgi?connection_id=${req.query.id}&api=SYNO.CloudSync&method=get_property&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 75 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 76 | return new Promise((resolve, reject) => { 77 | const string = JSON.stringify(response.data).slice(0, 85); 78 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 79 | reject(new Error('登录过期,请重新登录')) 80 | } else { 81 | resolve(response.data) 82 | } 83 | }); 84 | }) 85 | .then(response => { 86 | res.send(response); 87 | }) 88 | .catch(e => { 89 | res.send(e.message) 90 | }) 91 | }) 92 | 93 | router.get("/log", (req, res) => { // 获取items同步记录 94 | if (!(req.query.id >= 0) || req.query.id == undefined) { 95 | throw new Error("请添加list的请求id") 96 | } 97 | req.query.limit = req.query.limit || 200; 98 | console.log(req.query.limit); 99 | axios.get(`${req.api}/entry.cgi?offset=0&limit=${req.query.limit}&connection_id=${req.query.id}&api=SYNO.CloudSync&method=get_log&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 100 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 101 | return new Promise((resolve, reject) => { 102 | const string = JSON.stringify(response.data).slice(0, 85); 103 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 104 | reject(new Error('登录过期,请重新登录')) 105 | } else { 106 | resolve(response.data) 107 | } 108 | }); 109 | }) 110 | .then(response => { 111 | res.send(response); 112 | }) 113 | .catch(e => { 114 | res.send(e.message) 115 | }) 116 | }) 117 | 118 | router.get("/change", (req, res) => { // 更改items设置 119 | // 最大上传和下载为0 代表不限速 120 | if (!(req.query.id >= 0) || (req.query.id == undefined)) { 121 | throw new Error("请添加list的请求id") 122 | } else if (!req.query.name || req.query.Pollingtime == undefined || req.query.maxdownloadspeed == undefined || req.query.maxuploadspeed == undefined) { 123 | throw new Error("必须填写所有参数") 124 | } 125 | axios.get(`${req.api}/entry.cgi?connection_id=${req.query.id}&task_name="${req.query.name}"&pull_event_period=${Number(req.query.Pollingtime)}&max_upload_speed=${req.query.maxuploadspeed}&max_download_speed=${req.query.maxdownloadspeed}&storage_class=""&isSSE=false&part_size=128&api=SYNO.CloudSync&method=set_connection_setting&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 126 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 127 | return new Promise((resolve, reject) => { 128 | const string = JSON.stringify(response.data).slice(0, 85); 129 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 130 | reject(new Error('登录过期,请重新登录')) 131 | } else { 132 | resolve(response.data) 133 | } 134 | }); 135 | }) 136 | .then(response => { 137 | res.send(response); 138 | }) 139 | .catch(e => { 140 | res.send(e.message) 141 | }) 142 | }) 143 | 144 | router.get("/pause", (req, res) => { // 暂停所有items同步 145 | axios.get(`${req.api}/entry.cgi?api=SYNO.CloudSync&method=pause&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 146 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 147 | return new Promise((resolve, reject) => { 148 | const string = JSON.stringify(response.data).slice(0, 85); 149 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 150 | reject(new Error('登录过期,请重新登录')) 151 | } else { 152 | resolve(response.data) 153 | } 154 | }); 155 | }) 156 | .then(response => { 157 | res.send(response); 158 | }) 159 | .catch(e => { 160 | res.send(e.message) 161 | }) 162 | }) 163 | 164 | router.get("/start", (req, res) => { // 开始所有items同步 165 | axios.get(`${req.api}/entry.cgi?api=SYNO.CloudSync&method=resume&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 166 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 167 | return new Promise((resolve, reject) => { 168 | const string = JSON.stringify(response.data).slice(0, 85); 169 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 170 | reject(new Error('登录过期,请重新登录')) 171 | } else { 172 | resolve(response.data) 173 | } 174 | }); 175 | }) 176 | .then(response => { 177 | res.send(response); 178 | }) 179 | .catch(e => { 180 | res.send(e.message) 181 | }) 182 | }) 183 | 184 | module.exports = router; -------------------------------------------------------------------------------- /router/system.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const express = require('express') 3 | const router = express.Router(); 4 | const config = require("../config") 5 | router.get("/info", (req, res) => { // 获取系统基本信息 6 | axios.get(`${req.api}/entry.cgi?stop_when_error=false&mode="sequential"&compound=[{"api":"SYNO.Core.System","method":"info","version":3},{"api":"SYNO.Core.QuickConnect","method":"get","version":2},{"api":"SYNO.Core.Hardware.FanSpeed","method":"get","version":1}]&api=SYNO.Entry.Request&method=request&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 7 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 8 | return new Promise((resolve, reject) => { 9 | const string = JSON.stringify(response.data).slice(0, 85); 10 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 11 | reject(new Error('登录过期,请重新登录')) 12 | } else { 13 | resolve(response.data) 14 | } 15 | }); 16 | }) 17 | .then(response => { 18 | res.send(response); 19 | }) 20 | .catch((e) => { 21 | res.send(e.message) 22 | }) 23 | }) 24 | 25 | router.get("/status", (req, res) => { // 获取系统状态 26 | axios.get(`${req.api}/entry.cgi?api=SYNO.Core.System.Utilization&method=get&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 27 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 28 | return new Promise((resolve, reject) => { 29 | const string = JSON.stringify(response.data).slice(0, 85); 30 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 31 | reject(new Error('登录过期,请重新登录')) 32 | } else { 33 | resolve(response.data) 34 | } 35 | }); 36 | }) 37 | .then(response => { 38 | res.send(response); 39 | }) 40 | .catch(e => { 41 | res.send(e.message) 42 | }) 43 | }) 44 | 45 | 46 | router.get("/network", (req, res) => { // 获取网络基本信息 47 | 48 | axios.get(`${req.api}/entry.cgi?stop_when_error=false&mode="sequential"&compound=[{"api":"SYNO.Core.System","method":"info","version":1,"type":"network"},{"api":"SYNO.Core.DDNS.Record","method":"list","version":1}]&api=SYNO.Entry.Request&method=request&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 49 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 50 | return new Promise((resolve, reject) => { 51 | const string = JSON.stringify(response.data).slice(0, 85); 52 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 53 | reject(new Error('登录过期,请重新登录')) 54 | } else { 55 | resolve(response.data) 56 | } 57 | }); 58 | }) 59 | .then(response => { 60 | res.send(response); 61 | }) 62 | .catch(e => { 63 | res.send(e.message) 64 | }) 65 | }) 66 | 67 | router.get("/service", (req, res) => { // 获取获取已启用的服务 68 | axios.get(`${req.api}/entry.cgi?stop_when_error=false&mode="parallel"&compound=[{"api":"SYNO.Core.Service","method":"get","version":3,"additional":["active_status"]},{"api":"SYNO.Core.Package","method":"list","version":1,"additional":["status"]}]&api=SYNO.Entry.Request&method=request&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 69 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 70 | return new Promise((resolve, reject) => { 71 | const string = JSON.stringify(response.data).slice(0, 85); 72 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 73 | reject(new Error('登录过期,请重新登录')) 74 | } else { 75 | resolve(response.data) 76 | } 77 | }); 78 | }) 79 | .then(response => { 80 | res.send(response); 81 | }) 82 | .catch(e => { 83 | res.send(e.message) 84 | }) 85 | }) 86 | 87 | router.get("/terminal", (req, res) => { // 终端设置 88 | if (req.query.enablessh == undefined && req.query.enabletelnet == undefined && req.query.sshport == undefined) { 89 | throw new Error("请输入至少一个参数"); 90 | } 91 | // 先获取原来的数据 92 | axios.get(`${req.api}/entry.cgi?stop_when_error=false&mode="sequential"&compound=[{"api":"SYNO.Core.Terminal","method":"get","version":3},{"api":"SYNO.Core.SNMP","method":"get","version":1}]&api=SYNO.Entry.Request&method=request&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 93 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 94 | return new Promise((resolve, reject) => { 95 | const string = JSON.stringify(response.data).slice(0, 85); 96 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 97 | reject(new Error('登录过期,请重新登录')) 98 | } else { 99 | resolve(response.data) 100 | } 101 | }); 102 | }) 103 | .then(response => { 104 | let enable_telnet = response.data.result[0].data.enable_telnet; 105 | let enable_ssh = response.data.result[0].data.enable_ssh; 106 | let ssh_port = response.data.result[0].data.ssh_port; 107 | 108 | // 处理配置数据 109 | enable_ssh = Boolean(enable_ssh); 110 | enable_telnet = Boolean(enable_telnet); 111 | ssh_port = Number(ssh_port); 112 | 113 | req.query.enablessh = req.query.enablessh == undefined ? enable_ssh : req.query.enablessh; 114 | req.query.enabletelnet = req.query.enabletelnet == undefined ? enable_telnet : req.query.enabletelnet; 115 | req.query.sshport = req.query.sshport == undefined ? ssh_port : req.query.sshport; 116 | 117 | // 发起请求 118 | let compound = `[{ "api": "SYNO.Core.Terminal", "method": "set", "version": "3", "enable_telnet": ${req.query.enabletelnet}, "enable_ssh": ${req.query.enablessh}, "ssh_port": ${req.query.sshport} }, { "api": "SYNO.Core.SNMP", "method": "set", "version": "1", "enable_snmp": false }, { "api": "SYNO.Core.Terminal", "method": "get", "version": 3 }, { "api": "SYNO.Core.SNMP", "method": "get", "version": 1 }]`; 119 | axios.get(`${req.api}/entry.cgi?stop_when_error=false&mode="sequential"&compound=${compound}&api=SYNO.Entry.Request&method=request&version=1&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 120 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 121 | return new Promise((resolve, reject) => { 122 | const string = JSON.stringify(response.data).slice(0, 85); 123 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 124 | reject(new Error('登录过期,请重新登录')) 125 | } else { 126 | resolve(response.data) 127 | } 128 | }); 129 | }) 130 | .then(response => { 131 | res.send(response); 132 | }) 133 | }) 134 | .catch(e => { 135 | res.send(e.message) 136 | }) 137 | }) 138 | router.get("/shutdown", (req, res) => { // 关机 139 | (req.query.force == undefined) && (req.query.force = false); 140 | req.query.force = Boolean(req.query.force); 141 | axios.get(`${req.api}/entry.cgi?force=${req.query.force}&local=true&firmware_upgrade=false&cache_check_shutdown=true&api=SYNO.Core.System&method=shutdown&version=2&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 142 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 143 | return new Promise((resolve, reject) => { 144 | const string = JSON.stringify(response.data).slice(0, 85); 145 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 146 | reject(new Error('登录过期,请重新登录')) 147 | } else { 148 | resolve(response.data) 149 | } 150 | }); 151 | }) 152 | .then(response => { 153 | res.send(response); 154 | }) 155 | .catch(e => { 156 | res.send(e.message) 157 | }) 158 | }) 159 | router.get("/reboot", (req, res) => { // 重启 160 | (req.query.force == undefined) && (req.query.force = false); 161 | req.query.force = Boolean(req.query.force); 162 | axios.get(`${req.api}/entry.cgi?force=${req.query.force}&local=true&firmware_upgrade=false&cache_check_shutdown=false&api=SYNO.Core.System&method=reboot&version=2&_sid=${req.session.auth}`, { timeout: (config.responseTimeout * 1000) }) 163 | .then((response) => { // 判断有没有报错,如果报错证明cookie过期 164 | return new Promise((resolve, reject) => { 165 | const string = JSON.stringify(response.data).slice(0, 85); 166 | if (string.includes('"error":{"code":119}') || string.includes('"has_fail":true')) { 167 | reject(new Error('登录过期,请重新登录')) 168 | } else { 169 | resolve(response.data) 170 | } 171 | }); 172 | }) 173 | .then(response => { 174 | res.send(response); 175 | }) 176 | .catch(e => { 177 | res.send(e.message) 178 | }) 179 | }) 180 | module.exports = router; --------------------------------------------------------------------------------