mirror of
https://github.com/ProtoThis/python-synology.git
synced 2026-01-19 09:28:42 +00:00
Add DownloadStation (#62)
* Add DownloadStation * Add test * Add resume, fix create * Add get_config, create destination * Added readme
This commit is contained in:
28
README.rst
28
README.rst
@ -126,6 +126,34 @@ The ``SynologyDSM`` class can also ``update()`` all APIs at once.
|
||||
print("Space used: " + str(api.share.share_size(share_uuid, human_readable=True)))
|
||||
print("Recycle Bin Enabled: " + str(api.share.share_recycle_bin(share_uuid)))
|
||||
print("--")
|
||||
|
||||
|
||||
Download Station usage
|
||||
--------------------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from synology_dsm import SynologyDSM
|
||||
|
||||
api = SynologyDSM("<IP/DNS>", "<port>", "<username>", "<password>")
|
||||
|
||||
if "SYNO.DownloadStation.Info" in api.apis:
|
||||
|
||||
api.download_station.get_info()
|
||||
api.download_station.get_config()
|
||||
|
||||
# The download list will be updated after each of the following functions:
|
||||
# You should have the right on the (default) directory that the download will be saved, or you will get a 403 or 406 error
|
||||
api.download_station.create("http://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4")
|
||||
api.download_station.pause("dbid_1")
|
||||
# Like the other function, you can eather pass a str or a list
|
||||
api.download_station.resume(["dbid_1", "dbid_2"])
|
||||
api.download_station.delete("dbid_3")
|
||||
|
||||
# Manual update
|
||||
api.download_station.update()
|
||||
|
||||
|
||||
Surveillance Station usage
|
||||
--------------------------
|
||||
|
||||
|
||||
95
synology_dsm/api/download_station/__init__.py
Normal file
95
synology_dsm/api/download_station/__init__.py
Normal file
@ -0,0 +1,95 @@
|
||||
"""Synology DownloadStation API wrapper."""
|
||||
from .task import SynoDownloadTask
|
||||
|
||||
|
||||
class SynoDownloadStation(object):
|
||||
"""An implementation of a Synology DownloadStation."""
|
||||
|
||||
API_KEY = "SYNO.DownloadStation.*"
|
||||
INFO_API_KEY = "SYNO.DownloadStation.Info"
|
||||
TASK_API_KEY = "SYNO.DownloadStation.Task"
|
||||
|
||||
def __init__(self, dsm):
|
||||
"""Initialize a Download Station."""
|
||||
self._dsm = dsm
|
||||
self._tasks_by_id = {}
|
||||
self.additionals = [
|
||||
"detail",
|
||||
"file",
|
||||
] # Can contain: detail, transfer, file, tracker, peer
|
||||
|
||||
def update(self):
|
||||
"""Update tasks from API."""
|
||||
list_data = self._dsm.get(
|
||||
self.TASK_API_KEY, "List", {"additional": ",".join(self.additionals)}
|
||||
)["data"]
|
||||
for task_data in list_data["tasks"]:
|
||||
if task_data["id"] in self._tasks_by_id:
|
||||
self._tasks_by_id[task_data["id"]].update(task_data)
|
||||
else:
|
||||
self._tasks_by_id[task_data["id"]] = SynoDownloadTask(task_data)
|
||||
|
||||
# Global
|
||||
def get_info(self):
|
||||
"""Return general informations about the Download Station instance."""
|
||||
return self._dsm.get(self.INFO_API_KEY, "GetInfo")
|
||||
|
||||
def get_config(self):
|
||||
"""Return configuration about the Download Station instance."""
|
||||
return self._dsm.get(self.INFO_API_KEY, "GetConfig")
|
||||
|
||||
# Downloads
|
||||
def get_all_tasks(self):
|
||||
"""Return a list of tasks."""
|
||||
return self._tasks_by_id.values()
|
||||
|
||||
def get_task(self, task_id):
|
||||
"""Return task matching task_id."""
|
||||
return self._tasks_by_id[task_id]
|
||||
|
||||
def create(self, uri, unzip_password=None, destination=None):
|
||||
"""Create a new task (uri accepts HTTP/FTP/magnet/ED2K links)."""
|
||||
res = self._dsm.post(
|
||||
self.TASK_API_KEY,
|
||||
"Create",
|
||||
{
|
||||
"uri": ",".join(uri) if isinstance(uri, list) else uri,
|
||||
"unzip_password": unzip_password,
|
||||
"destination": destination,
|
||||
},
|
||||
)
|
||||
self.update()
|
||||
return res
|
||||
|
||||
def pause(self, task_id):
|
||||
"""Pause a download task."""
|
||||
res = self._dsm.get(
|
||||
self.TASK_API_KEY,
|
||||
"Pause",
|
||||
{"id": ",".join(task_id) if isinstance(task_id, list) else task_id},
|
||||
)
|
||||
self.update()
|
||||
return res
|
||||
|
||||
def resume(self, task_id):
|
||||
"""Resume a paused download task."""
|
||||
res = self._dsm.get(
|
||||
self.TASK_API_KEY,
|
||||
"Resume",
|
||||
{"id": ",".join(task_id) if isinstance(task_id, list) else task_id},
|
||||
)
|
||||
self.update()
|
||||
return res
|
||||
|
||||
def delete(self, task_id, force_complete=False):
|
||||
"""Delete a download task."""
|
||||
res = self._dsm.get(
|
||||
self.TASK_API_KEY,
|
||||
"Delete",
|
||||
{
|
||||
"id": ",".join(task_id) if isinstance(task_id, list) else task_id,
|
||||
"force_complete": force_complete,
|
||||
},
|
||||
)
|
||||
self.update()
|
||||
return res
|
||||
53
synology_dsm/api/download_station/task.py
Normal file
53
synology_dsm/api/download_station/task.py
Normal file
@ -0,0 +1,53 @@
|
||||
"""DownloadStation task."""
|
||||
|
||||
|
||||
class SynoDownloadTask(object):
|
||||
"""An representation of a Synology DownloadStation task."""
|
||||
|
||||
def __init__(self, data):
|
||||
"""Initialize a Download Station task."""
|
||||
self._data = data
|
||||
|
||||
def update(self, data):
|
||||
"""Update the task."""
|
||||
self._data = data
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
"""Return id of the task."""
|
||||
return self._data["id"]
|
||||
|
||||
@property
|
||||
def title(self):
|
||||
"""Return title of the task."""
|
||||
return self._data["title"]
|
||||
|
||||
@property
|
||||
def type(self):
|
||||
"""Return type of the task (bt, nzb, http(s), ftp, emule)."""
|
||||
return self._data["type"]
|
||||
|
||||
@property
|
||||
def username(self):
|
||||
"""Return username of the task."""
|
||||
return self._data["username"]
|
||||
|
||||
@property
|
||||
def size(self):
|
||||
"""Return size of the task."""
|
||||
return self._data["size"]
|
||||
|
||||
@property
|
||||
def status(self):
|
||||
"""Return status of the task (waiting, downloading, paused, finishing, finished, hash_checking, seeding, filehosting_waiting, extracting, error)."""
|
||||
return self._data["status"]
|
||||
|
||||
@property
|
||||
def status_extra(self):
|
||||
"""Return status_extra of the task."""
|
||||
return self._data.get("status_extra")
|
||||
|
||||
@property
|
||||
def additional(self):
|
||||
"""Return additional data of the task."""
|
||||
return self._data["additional"]
|
||||
@ -22,6 +22,7 @@ from .exceptions import (
|
||||
from .api.core.security import SynoCoreSecurity
|
||||
from .api.core.utilization import SynoCoreUtilization
|
||||
from .api.core.share import SynoCoreShare
|
||||
from .api.download_station import SynoDownloadStation
|
||||
from .api.dsm.information import SynoDSMInformation
|
||||
from .api.dsm.network import SynoDSMNetwork
|
||||
from .api.storage.storage import SynoStorage
|
||||
@ -70,6 +71,7 @@ class SynologyDSM(object):
|
||||
self._apis = {
|
||||
"SYNO.API.Info": {"maxVersion": 1, "minVersion": 1, "path": "query.cgi"}
|
||||
}
|
||||
self._download = None
|
||||
self._information = None
|
||||
self._network = None
|
||||
self._security = None
|
||||
@ -183,11 +185,9 @@ class SynologyDSM(object):
|
||||
"""Handles API GET request."""
|
||||
return self._request("GET", api, method, params, **kwargs)
|
||||
|
||||
def post(self, api, method, params=None, data=None, json=None, **kwargs):
|
||||
def post(self, api, method, params=None, **kwargs):
|
||||
"""Handles API POST request."""
|
||||
return self._request(
|
||||
"POST", api, method, params, data=data, json=json, **kwargs
|
||||
)
|
||||
return self._request("POST", api, method, params, **kwargs)
|
||||
|
||||
def _request(
|
||||
self, request_method, api, method, params=None, retry_once=True, **kwargs
|
||||
@ -227,20 +227,6 @@ class SynologyDSM(object):
|
||||
|
||||
url = self._build_url(api)
|
||||
|
||||
# If the request method is POST and the API is SynoCoreShare the params
|
||||
# to the request body. Used to support the weird Syno use of POST
|
||||
# to choose what fields to return. See ./api/core/share.py
|
||||
# for an example.
|
||||
if request_method == "POST" and api == SynoCoreShare.API_KEY:
|
||||
body = {}
|
||||
body.update(params)
|
||||
body.update(kwargs.pop("data"))
|
||||
body["mimeType"] = "application/json"
|
||||
# Request data via POST (excluding FileStation file uploads)
|
||||
self._debuglog("POST BODY: " + str(body))
|
||||
|
||||
kwargs["data"] = body
|
||||
|
||||
# Request data
|
||||
response = self._execute_request(request_method, url, params, **kwargs)
|
||||
self._debuglog("Request Method: " + request_method)
|
||||
@ -279,6 +265,13 @@ class SynologyDSM(object):
|
||||
url, params=encoded_params, timeout=self._timeout, **kwargs
|
||||
)
|
||||
elif method == "POST":
|
||||
data = {}
|
||||
data.update(params)
|
||||
data.update(kwargs.pop("data", {}))
|
||||
data["mimeType"] = "application/json"
|
||||
kwargs["data"] = data
|
||||
self._debuglog("POST data: " + str(data))
|
||||
|
||||
response = self._session.post(
|
||||
url, params=params, timeout=self._timeout, **kwargs
|
||||
)
|
||||
@ -308,6 +301,9 @@ class SynologyDSM(object):
|
||||
|
||||
def update(self, with_information=False, with_network=False):
|
||||
"""Updates the various instanced modules."""
|
||||
if self._download:
|
||||
self._download.update()
|
||||
|
||||
if self._information and with_information:
|
||||
self._information.update()
|
||||
|
||||
@ -337,6 +333,9 @@ class SynologyDSM(object):
|
||||
if hasattr(self, "_" + api):
|
||||
setattr(self, "_" + api, None)
|
||||
return True
|
||||
if api == SynoDownloadStation.API_KEY:
|
||||
self._download = None
|
||||
return True
|
||||
if api == SynoCoreSecurity.API_KEY:
|
||||
self._security = None
|
||||
return True
|
||||
@ -352,6 +351,9 @@ class SynologyDSM(object):
|
||||
if api == SynoSurveillanceStation.API_KEY:
|
||||
self._surveillance = None
|
||||
return True
|
||||
if isinstance(api, SynoDownloadStation):
|
||||
self._download = None
|
||||
return True
|
||||
if isinstance(api, SynoCoreSecurity):
|
||||
self._security = None
|
||||
return True
|
||||
@ -370,6 +372,13 @@ class SynologyDSM(object):
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def download_station(self):
|
||||
"""Gets NAS DownloadStation."""
|
||||
if not self._download:
|
||||
self._download = SynoDownloadStation(self)
|
||||
return self._download
|
||||
|
||||
@property
|
||||
def information(self):
|
||||
"""Gets NAS informations."""
|
||||
|
||||
@ -10,6 +10,7 @@ from synology_dsm.api.core.security import SynoCoreSecurity
|
||||
from synology_dsm.api.core.utilization import SynoCoreUtilization
|
||||
from synology_dsm.api.dsm.information import SynoDSMInformation
|
||||
from synology_dsm.api.dsm.network import SynoDSMNetwork
|
||||
from synology_dsm.api.download_station import SynoDownloadStation
|
||||
from synology_dsm.api.storage.storage import SynoStorage
|
||||
from synology_dsm.api.core.share import SynoCoreShare
|
||||
from synology_dsm.api.surveillance_station import SynoSurveillanceStation
|
||||
@ -44,6 +45,9 @@ from .api_data.dsm_6 import (
|
||||
DSM_6_SURVEILLANCE_STATION_CAMERA_LIST,
|
||||
DSM_6_SURVEILLANCE_STATION_HOME_MODE_GET_INFO,
|
||||
DSM_6_SURVEILLANCE_STATION_HOME_MODE_SWITCH,
|
||||
DSM_6_DOWNLOAD_STATION_INFO_INFO,
|
||||
DSM_6_DOWNLOAD_STATION_INFO_CONFIG,
|
||||
DSM_6_DOWNLOAD_STATION_TASK_LIST,
|
||||
)
|
||||
from .api_data.dsm_5 import (
|
||||
DSM_5_API_INFO,
|
||||
@ -193,24 +197,32 @@ class SynologyDSMMock(SynologyDSM):
|
||||
if not self._session_id:
|
||||
return ERROR_INSUFFICIENT_USER_PRIVILEGE
|
||||
|
||||
if SynoCoreSecurity.API_KEY in url:
|
||||
if self.error:
|
||||
return DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE
|
||||
return API_SWITCHER[self.dsm_version]["CORE_SECURITY"]
|
||||
|
||||
if SynoCoreShare.API_KEY in url:
|
||||
return API_SWITCHER[self.dsm_version]["CORE_SHARE"]
|
||||
|
||||
if SynoCoreUtilization.API_KEY in url:
|
||||
if self.error:
|
||||
return DSM_6_CORE_UTILIZATION_ERROR_1055
|
||||
return API_SWITCHER[self.dsm_version]["CORE_UTILIZATION"]
|
||||
|
||||
if SynoDSMInformation.API_KEY in url:
|
||||
return API_SWITCHER[self.dsm_version]["DSM_INFORMATION"]
|
||||
|
||||
if SynoDSMNetwork.API_KEY in url:
|
||||
return API_SWITCHER[self.dsm_version]["DSM_NETWORK"]
|
||||
|
||||
if SynoCoreShare.API_KEY in url:
|
||||
return API_SWITCHER[self.dsm_version]["CORE_SHARE"]
|
||||
|
||||
if SynoCoreSecurity.API_KEY in url:
|
||||
if self.error:
|
||||
return DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE
|
||||
return API_SWITCHER[self.dsm_version]["CORE_SECURITY"]
|
||||
|
||||
if SynoCoreUtilization.API_KEY in url:
|
||||
if self.error:
|
||||
return DSM_6_CORE_UTILIZATION_ERROR_1055
|
||||
return API_SWITCHER[self.dsm_version]["CORE_UTILIZATION"]
|
||||
if SynoDownloadStation.TASK_API_KEY in url:
|
||||
if "GetInfo" in url:
|
||||
return DSM_6_DOWNLOAD_STATION_INFO_INFO
|
||||
if "GetConfig" in url:
|
||||
return DSM_6_DOWNLOAD_STATION_INFO_CONFIG
|
||||
if "List" in url:
|
||||
return DSM_6_DOWNLOAD_STATION_TASK_LIST
|
||||
|
||||
if SynoStorage.API_KEY in url:
|
||||
return API_SWITCHER[self.dsm_version]["STORAGE_STORAGE"][
|
||||
|
||||
@ -13,6 +13,13 @@ from .core.const_6_core_security import (
|
||||
DSM_6_CORE_SECURITY,
|
||||
DSM_6_CORE_SECURITY_UPDATE_OUTOFDATE,
|
||||
)
|
||||
from .download_station.const_6_download_station_info import (
|
||||
DSM_6_DOWNLOAD_STATION_INFO_INFO,
|
||||
DSM_6_DOWNLOAD_STATION_INFO_CONFIG,
|
||||
)
|
||||
from .download_station.const_6_download_station_task import (
|
||||
DSM_6_DOWNLOAD_STATION_TASK_LIST,
|
||||
)
|
||||
from .dsm.const_6_dsm_info import DSM_6_DSM_INFORMATION
|
||||
from .dsm.const_6_dsm_network import DSM_6_DSM_NETWORK
|
||||
from .storage.const_6_storage_storage import (
|
||||
|
||||
1
tests/api_data/dsm_6/download_station/__init__.py
Normal file
1
tests/api_data/dsm_6/download_station/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
"""DSM 6 SYNO.DownloadStation.* datas."""
|
||||
@ -0,0 +1,24 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""DSM 6 SYNO.DownloadStation.Info data."""
|
||||
|
||||
DSM_6_DOWNLOAD_STATION_INFO_INFO = {
|
||||
"data": {"is_manager": True, "version": 3543, "version_string": "3.8-3543"},
|
||||
"success": True,
|
||||
}
|
||||
|
||||
DSM_6_DOWNLOAD_STATION_INFO_CONFIG = {
|
||||
"data": {
|
||||
"bt_max_download": 0,
|
||||
"bt_max_upload": 800,
|
||||
"default_destination": "downloads",
|
||||
"emule_default_destination": None,
|
||||
"emule_enabled": False,
|
||||
"emule_max_download": 0,
|
||||
"emule_max_upload": 20,
|
||||
"ftp_max_download": 0,
|
||||
"http_max_download": 0,
|
||||
"nzb_max_download": 0,
|
||||
"unzip_service_enabled": False,
|
||||
},
|
||||
"success": True,
|
||||
}
|
||||
@ -0,0 +1,299 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""DSM 6 SYNO.DownloadStation.Task data."""
|
||||
|
||||
DSM_6_DOWNLOAD_STATION_TASK_LIST = {
|
||||
"data": {
|
||||
"offset": 0,
|
||||
"tasks": [
|
||||
{
|
||||
"additional": {
|
||||
"detail": {
|
||||
"completed_time": 0,
|
||||
"connected_leechers": 0,
|
||||
"connected_peers": 0,
|
||||
"connected_seeders": 0,
|
||||
"create_time": 1550089068,
|
||||
"destination": "Folder/containing/downloads",
|
||||
"seedelapsed": 0,
|
||||
"started_time": 1592549339,
|
||||
"total_peers": 0,
|
||||
"total_pieces": 1239,
|
||||
"unzip_password": "",
|
||||
"uri": "magnet:?xt=urn:btih:1234ABCD1234ABCD1234ABCD1234ABCD1234ABCD&dn=1234",
|
||||
"waiting_seconds": 0,
|
||||
},
|
||||
"file": [
|
||||
{
|
||||
"filename": "INFO.nfo",
|
||||
"index": 0,
|
||||
"priority": "low",
|
||||
"size": 1335,
|
||||
"size_downloaded": 0,
|
||||
"wanted": True,
|
||||
},
|
||||
{
|
||||
"filename": "My super movie 2 2022.mkv",
|
||||
"index": 1,
|
||||
"priority": "normal",
|
||||
"size": 1591087515,
|
||||
"size_downloaded": 0,
|
||||
"wanted": True,
|
||||
},
|
||||
{
|
||||
"filename": "My super movie 2 sample.mkv",
|
||||
"index": 2,
|
||||
"priority": "normal",
|
||||
"size": 2754524,
|
||||
"size_downloaded": 0,
|
||||
"wanted": False,
|
||||
},
|
||||
{
|
||||
"filename": "My super movie 2021.mkv",
|
||||
"index": 3,
|
||||
"priority": "normal",
|
||||
"size": 1155085341,
|
||||
"size_downloaded": 0,
|
||||
"wanted": True,
|
||||
},
|
||||
{
|
||||
"filename": "My super movie 2021 sample.mkv",
|
||||
"index": 4,
|
||||
"priority": "normal",
|
||||
"size": 4359701,
|
||||
"size_downloaded": 0,
|
||||
"wanted": False,
|
||||
},
|
||||
{
|
||||
"filename": "My super movie 3 2023.mkv",
|
||||
"index": 5,
|
||||
"priority": "normal",
|
||||
"size": 1288819263,
|
||||
"size_downloaded": 0,
|
||||
"wanted": True,
|
||||
},
|
||||
{
|
||||
"filename": "My super movie 3 sample.mkv",
|
||||
"index": 6,
|
||||
"priority": "normal",
|
||||
"size": 3077684,
|
||||
"size_downloaded": 0,
|
||||
"wanted": False,
|
||||
},
|
||||
{
|
||||
"filename": "My super movie 4 2031.mkv",
|
||||
"index": 7,
|
||||
"priority": "normal",
|
||||
"size": 1149397942,
|
||||
"size_downloaded": 0,
|
||||
"wanted": True,
|
||||
},
|
||||
{
|
||||
"filename": "My super movie 4 sample.mkv",
|
||||
"index": 8,
|
||||
"priority": "normal",
|
||||
"size": 2023179,
|
||||
"size_downloaded": 0,
|
||||
"wanted": False,
|
||||
},
|
||||
],
|
||||
},
|
||||
"id": "dbid_86",
|
||||
"size": 5196586484,
|
||||
"status": "downloading",
|
||||
"title": "My super movie Complete 2021-2031",
|
||||
"type": "bt",
|
||||
"username": "Test_useR",
|
||||
},
|
||||
{
|
||||
"additional": {
|
||||
"detail": {
|
||||
"completed_time": 0,
|
||||
"connected_leechers": 0,
|
||||
"connected_peers": 0,
|
||||
"connected_seeders": 0,
|
||||
"create_time": 1551214114,
|
||||
"destination": "Folder/containing/downloads",
|
||||
"seedelapsed": 0,
|
||||
"started_time": 1592549348,
|
||||
"total_peers": 0,
|
||||
"total_pieces": 948,
|
||||
"unzip_password": "",
|
||||
"uri": "magnet:?xt=urn:btih:1234ABCD1234ABCD1234ABCD1234ABCD1234ABCD&dn=1234",
|
||||
"waiting_seconds": 0,
|
||||
},
|
||||
"file": [
|
||||
{
|
||||
"filename": "Blade Swipper 1984.mkv",
|
||||
"index": 0,
|
||||
"priority": "normal",
|
||||
"size": 1986298376,
|
||||
"size_downloaded": 1602519560,
|
||||
"wanted": True,
|
||||
}
|
||||
],
|
||||
},
|
||||
"id": "dbid_164",
|
||||
"size": 1986298376,
|
||||
"status": "downloading",
|
||||
"title": "Blade Swipper 1984.mkv",
|
||||
"type": "bt",
|
||||
"username": "Test_useR",
|
||||
},
|
||||
{
|
||||
"additional": {
|
||||
"detail": {
|
||||
"completed_time": 0,
|
||||
"connected_leechers": 0,
|
||||
"connected_peers": 50,
|
||||
"connected_seeders": 50,
|
||||
"create_time": 1585435581,
|
||||
"destination": "Folder/containing/downloads",
|
||||
"seedelapsed": 0,
|
||||
"started_time": 1592549349,
|
||||
"total_peers": 0,
|
||||
"total_pieces": 0,
|
||||
"unzip_password": "",
|
||||
"uri": "magnet:?xt=urn:btih:1234ABCD1234ABCD1234ABCD1234ABCD1234ABCD&dn=1234",
|
||||
"waiting_seconds": 0,
|
||||
},
|
||||
"file": [],
|
||||
},
|
||||
"id": "dbid_486",
|
||||
"size": 0,
|
||||
"status": "downloading",
|
||||
"title": "The falling State",
|
||||
"type": "bt",
|
||||
"username": "Test_useR",
|
||||
},
|
||||
{
|
||||
"additional": {
|
||||
"detail": {
|
||||
"completed_time": 0,
|
||||
"connected_leechers": 0,
|
||||
"connected_peers": 1,
|
||||
"connected_seeders": 1,
|
||||
"create_time": 1591562665,
|
||||
"destination": "Folder/containing/downloads",
|
||||
"seedelapsed": 0,
|
||||
"started_time": 1591563597,
|
||||
"total_peers": 0,
|
||||
"total_pieces": 1494,
|
||||
"unzip_password": "",
|
||||
"uri": "magnet:?xt=urn:btih:1234ABCD1234ABCD1234ABCD1234ABCD1234ABCD&dn=1234",
|
||||
"waiting_seconds": 0,
|
||||
}
|
||||
},
|
||||
"id": "dbid_518",
|
||||
"size": 391580448,
|
||||
"status": "paused",
|
||||
"title": "Welcome to the North.mkv",
|
||||
"type": "bt",
|
||||
"username": "Test_useR",
|
||||
},
|
||||
{
|
||||
"additional": {
|
||||
"detail": {
|
||||
"completed_time": 1591565351,
|
||||
"connected_leechers": 0,
|
||||
"connected_peers": 0,
|
||||
"connected_seeders": 0,
|
||||
"create_time": 1591563606,
|
||||
"destination": "Folder/containing/downloads",
|
||||
"seedelapsed": 172800,
|
||||
"started_time": 1592601577,
|
||||
"total_peers": 0,
|
||||
"total_pieces": 5466,
|
||||
"unzip_password": "",
|
||||
"uri": "magnet:?xt=urn:btih:1234ABCD1234ABCD1234ABCD1234ABCD1234ABCD&dn=1234",
|
||||
"waiting_seconds": 0,
|
||||
}
|
||||
},
|
||||
"id": "dbid_522",
|
||||
"size": 5731285821,
|
||||
"status": "finished",
|
||||
"title": "Birds of Pokémon.mkv",
|
||||
"type": "bt",
|
||||
"username": "Test_useR",
|
||||
},
|
||||
{
|
||||
"additional": {
|
||||
"detail": {
|
||||
"completed_time": 1591566799,
|
||||
"connected_leechers": 0,
|
||||
"connected_peers": 0,
|
||||
"connected_seeders": 0,
|
||||
"create_time": 1591566523,
|
||||
"destination": "Folder/containing/downloads",
|
||||
"seedelapsed": 0,
|
||||
"started_time": 1591566696,
|
||||
"total_peers": 0,
|
||||
"total_pieces": 0,
|
||||
"unzip_password": "",
|
||||
"uri": "https://1fichier.com/?1234ABCD1234ABCD1234&af=22123",
|
||||
"waiting_seconds": 0,
|
||||
}
|
||||
},
|
||||
"id": "dbid_531",
|
||||
"size": 2811892495,
|
||||
"status": "finished",
|
||||
"title": "1234ABCD1234ABCD1234",
|
||||
"type": "https",
|
||||
"username": "Test_useR",
|
||||
},
|
||||
{
|
||||
"additional": {
|
||||
"detail": {
|
||||
"completed_time": 0,
|
||||
"connected_leechers": 0,
|
||||
"connected_peers": 0,
|
||||
"connected_seeders": 0,
|
||||
"create_time": 1591566903,
|
||||
"destination": "Folder/containing/downloads",
|
||||
"seedelapsed": 0,
|
||||
"started_time": 0,
|
||||
"total_peers": 0,
|
||||
"total_pieces": 0,
|
||||
"unzip_password": "",
|
||||
"uri": "https://1fichier.com/?123ABC123ABC123ABC12",
|
||||
"waiting_seconds": 0,
|
||||
}
|
||||
},
|
||||
"id": "dbid_533",
|
||||
"size": 0,
|
||||
"status": "error",
|
||||
"status_extra": {"error_detail": "unknown"},
|
||||
"title": "?123ABC123ABC123ABC12",
|
||||
"type": "https",
|
||||
"username": "Test_useR",
|
||||
},
|
||||
{
|
||||
"additional": {
|
||||
"detail": {
|
||||
"completed_time": 0,
|
||||
"connected_leechers": 0,
|
||||
"connected_peers": 0,
|
||||
"connected_seeders": 0,
|
||||
"create_time": 1592605687,
|
||||
"destination": "Folder/containing/downloads",
|
||||
"seedelapsed": 0,
|
||||
"started_time": 1592605731,
|
||||
"total_peers": 0,
|
||||
"total_pieces": 0,
|
||||
"unzip_password": "",
|
||||
"uri": "https://1fichier.com/?123ABC123ABC123ABC12",
|
||||
"waiting_seconds": 0,
|
||||
}
|
||||
},
|
||||
"id": "dbid_549",
|
||||
"size": 0,
|
||||
"status": "error",
|
||||
"status_extra": {"error_detail": "broken_link"},
|
||||
"title": "123ABC123ABC123ABC12",
|
||||
"type": "https",
|
||||
"username": "Test_useR",
|
||||
},
|
||||
],
|
||||
"total": 8,
|
||||
},
|
||||
"success": True,
|
||||
}
|
||||
@ -698,8 +698,37 @@ class TestSynologyDSM(TestCase):
|
||||
assert self.api.storage.disk_below_remain_life_thr("test_disk") is None
|
||||
assert self.api.storage.disk_temp("test_disk") is None
|
||||
|
||||
def test_surveillance_camera(self):
|
||||
"""Test surveillance."""
|
||||
def test_download_station(self):
|
||||
"""Test DownloadStation."""
|
||||
assert self.api.download_station
|
||||
assert not self.api.download_station.get_all_tasks()
|
||||
|
||||
assert self.api.download_station.get_info()
|
||||
assert self.api.download_station.get_config()
|
||||
self.api.download_station.update()
|
||||
assert self.api.download_station.get_all_tasks()
|
||||
assert len(self.api.download_station.get_all_tasks()) == 8
|
||||
|
||||
# BT DL
|
||||
assert self.api.download_station.get_task("dbid_86").status == "downloading"
|
||||
assert not self.api.download_station.get_task("dbid_86").status_extra
|
||||
assert self.api.download_station.get_task("dbid_86").type == "bt"
|
||||
assert self.api.download_station.get_task("dbid_86").additional.get("file")
|
||||
assert (
|
||||
len(self.api.download_station.get_task("dbid_86").additional.get("file"))
|
||||
== 9
|
||||
)
|
||||
|
||||
# HTTPS error
|
||||
assert self.api.download_station.get_task("dbid_549").status == "error"
|
||||
assert (
|
||||
self.api.download_station.get_task("dbid_549").status_extra["error_detail"]
|
||||
== "broken_link"
|
||||
)
|
||||
assert self.api.download_station.get_task("dbid_549").type == "https"
|
||||
|
||||
def test_surveillance_station(self):
|
||||
"""Test SurveillanceStation."""
|
||||
self.api.with_surveillance = True
|
||||
assert self.api.surveillance_station
|
||||
assert not self.api.surveillance_station.get_all_cameras()
|
||||
|
||||
Reference in New Issue
Block a user